Mercurial > octave
diff mkoctfile.cc.in @ 8091:4e7527a7b3f9
mkoctfile.cc.in, octave-config.cc.in, octave-bug.cc.in: new files
author | Michael Goffioul |
---|---|
date | Mon, 08 Sep 2008 15:34:05 -0400 |
parents | |
children | 6a292b0fa88c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mkoctfile.cc.in Mon Sep 08 15:34:05 2008 -0400 @@ -0,0 +1,702 @@ +#if defined (HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <string> +#include <map> +#include <list> +#include <algorithm> +#include <iostream> +#include <fstream> +#include <vector> +#include <cstdlib> + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) +#include <windows.h> +#ifdef _MSC_VER +#define popen _popen +#define pclose _pclose +#endif +#endif + +using namespace std; + +static bool initialized = false; +static map<string,string> vars; + +static string OCTAVE_VERSION = %OCTAVE_CONF_VERSION%; + +static std::string substitute_prefix(const std::string& s, const std::string& prefix, const std::string& new_prefix) +{ + std::string retval = s; + + if (!prefix.empty() && new_prefix != prefix) + { + int len = prefix.length(); + if (retval.find(prefix) == 0) + retval.replace(0, len, new_prefix); + } + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + std::replace(retval.begin(), retval.end(), '/', '\\'); +#endif + + return retval; +} + +static string get_line(FILE *fp) +{ + static vector<char> buf(100); + int idx = 0; + char c; + + while (1) + { + c = (char)fgetc(fp); + if (c == '\n' || c == EOF) + break; + if (buf.size() <= idx) + buf.resize(buf.size() + 100); + buf[idx++] = c; + } + if (idx == 0) + return string(""); + else + return string(&buf[0], idx); +} + + +static string get_variable(const char *name, const string& defval) +{ + const char *val = getenv(name); + if (val == NULL || val[0] == '\0') + return defval; + else + return string(val); +} + +static string quote_path(const string& s) +{ + if (s.find(' ') != string::npos && s[0] != '"') + return "\"" + s + "\""; + return s; +} + +static void initialize(void) +{ + if (initialized) + return; + + initialized = true; + + vars["OCTAVE_HOME"] = get_variable("OCTAVE_HOME", ""); + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + int n = 1024; + + std::string bin_dir (n, '\0'); + + while (true) + { + int status = GetModuleFileName (0, &bin_dir[0], n); + + if (status < n) + { + bin_dir.resize (status); + break; + } + else + { + n *= 2; + bin_dir.resize (n); + } + } + + if (! bin_dir.empty ()) + { + size_t pos = bin_dir.rfind ("\\bin\\"); + + if (pos != string::npos) + vars["OCTAVE_HOME"] = bin_dir.substr (0, pos); + } +#endif + + vars["SED"] = get_variable("SED", %OCTAVE_CONF_SED%); + + vars["OCTAVE_PREFIX"] = %OCTAVE_CONF_PREFIX%; + + std::string DEFAULT_OCTINCLUDEDIR = %OCTAVE_CONF_OCTINCLUDEDIR%; + std::string DEFAULT_INCLUDEDIR = %OCTAVE_CONF_INCLUDEDIR%; + std::string DEFAULT_LIBDIR = %OCTAVE_CONF_LIBDIR%; + std::string DEFAULT_OCTLIBDIR = %OCTAVE_CONF_OCTLIBDIR%; + + if (! vars["OCTAVE_HOME"].empty()) + { + DEFAULT_OCTINCLUDEDIR = substitute_prefix(DEFAULT_OCTINCLUDEDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_INCLUDEDIR = substitute_prefix(DEFAULT_INCLUDEDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_LIBDIR = substitute_prefix(DEFAULT_LIBDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_OCTLIBDIR = substitute_prefix(DEFAULT_OCTLIBDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + } + + vars["OCTINCLUDEDIR"] = get_variable("OCTINCLUDEDIR", DEFAULT_OCTINCLUDEDIR); + vars["INCLUDEDIR"] = get_variable("INCLUDEDIR", DEFAULT_INCLUDEDIR); + vars["LIBDIR"] = get_variable("LIBDIR", DEFAULT_LIBDIR); + vars["OCTLIBDIR"] = get_variable("OCTLIBDIR", DEFAULT_OCTLIBDIR); + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + std::string DEFAULT_INCFLAGS = "-I" + quote_path(vars["OCTINCLUDEDIR"]) + " -I" + quote_path(vars["OCTINCLUDEDIR"] + "\\octave"); +#else + std::string DEFAULT_INCFLAGS = "-I" + quote_path(vars["OCTINCLUDEDIR"]) + " -I" + quote_path(vars["OCTINCLUDEDIR"] + "/octave"); +#endif + if (vars["INCLUDEDIR"] != "/usr/include") + DEFAULT_INCFLAGS += " -I" + quote_path(vars["INCLUDEDIR"]); + + std::string DEFAULT_LFLAGS = "-L" + quote_path(vars["OCTLIBDIR"]); + if (vars["LIBDIR"] != "/usr/lib") + DEFAULT_LFLAGS += " -L" + quote_path(vars["LIBDIR"]); + + vars["CPPFLAGS"] = get_variable("CPPFLAGS", %OCTAVE_CONF_CPPFLAGS%); + vars["INCFLAGS"] = get_variable("INCFLAGS", DEFAULT_INCFLAGS); + vars["F2C"] = get_variable("F2C", %OCTAVE_CONF_F2C%); + vars["F2CFLAGS"] = get_variable("F2CFLAGS", %OCTAVE_CONF_F2CFLAGS%); + vars["F77"] = get_variable("F77", %OCTAVE_CONF_F77%); + vars["FFLAGS"] = get_variable("FFLAGS", %OCTAVE_CONF_FFLAGS%); + vars["FPICFLAG"] = get_variable("FPICFLAG", %OCTAVE_CONF_FPICFLAG%); + vars["CC"] = get_variable("CC", %OCTAVE_CONF_CC%); + vars["CFLAGS"] = get_variable("CFLAGS", %OCTAVE_CONF_CFLAGS%); + vars["CPICFLAG"] = get_variable("CPICFLAG", %OCTAVE_CONF_CPICFLAG%); + vars["CXX"] = get_variable("CXX", %OCTAVE_CONF_CXX%); + vars["CXXFLAGS"] = get_variable("CXXFLAGS", %OCTAVE_CONF_CXXFLAGS%); + vars["CXXPICFLAG"] = get_variable("CXXPICFLAG", %OCTAVE_CONF_CXXPICFLAG%); + vars["XTRA_CFLAGS"] = get_variable("XTRA_CFLAGS", %OCTAVE_CONF_XTRA_CFLAGS%); + vars["XTRA_CXXFLAGS"] = get_variable("XTRA_CXXFLAGS", %OCTAVE_CONF_XTRA_CXXFLAGS%); + + vars["DEPEND_FLAGS"] = get_variable("DEPEND_FLAGS", %OCTAVE_CONF_DEPEND_FLAGS%); + vars["DEPEND_EXTRA_SED_PATTERN"] = get_variable("DEPEND_EXTRA_SED_PATTERN", %OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%); + + vars["DL_LD"] = get_variable("DL_LD", %OCTAVE_CONF_DL_LD%); + vars["DL_LDFLAGS"] = get_variable("DL_LDFLAGS", %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%); + + vars["RLD_FLAG"] = get_variable("RLD_FLAG", %OCTAVE_CONF_RLD_FLAG%); + vars["RDYNAMIC_FLAG"] = get_variable("RDYNAMIC_FLAG", %OCTAVE_CONF_RDYNAMIC_FLAG%); + vars["LIBOCTAVE"] = "-loctave"; + vars["LIBOCTINTERP"] = "-loctinterp"; + vars["LIBREADLINE"] = "-lreadline"; + vars["LIBCRUFT"] = "-lcruft"; + vars["BLAS_LIBS"] = get_variable("BLAS_LIBS", %OCTAVE_CONF_BLAS_LIBS%); + vars["FFTW_LIBS"] = get_variable("FFTW_LIBS", %OCTAVE_CONF_FFTW_LIBS%); + vars["LIBS"] = get_variable("LIBS", %OCTAVE_CONF_LIBS%); + vars["FLIBS"] = get_variable("FLIBS", %OCTAVE_CONF_FLIBS%); + vars["LD_CXX"] = get_variable("LD_CXX", %OCTAVE_CONF_LD_CXX%); + vars["LDFLAGS"] = get_variable("LDFLAGS", %OCTAVE_CONF_LDFLAGS%); + vars["LD_STATIC_FLAG"] = get_variable("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%); + vars["LFLAGS"] = get_variable("LFLAGS", DEFAULT_LFLAGS); + + vars["ALL_FFLAGS"] = vars["FFLAGS"]; + + vars["ALL_CFLAGS"] = vars["INCFLAGS"] + " " + vars["XTRA_CFLAGS"] + " " + vars["CFLAGS"]; + + vars["ALL_CXXFLAGS"] = vars["INCFLAGS"] + " " + vars["XTRA_CXXFLAGS"] + " " + vars["CXXFLAGS"]; + + vars["ALL_LDFLAGS"] = vars["LD_STATIC_FLAG"] + " " + vars["CPICFLAG"] + " " + vars["LDFLAGS"]; + + vars["OCTAVE_LIBS"] = vars["LIBOCTINTERP"] + " " + vars["LIBOCTAVE"] + " " + vars["SPECIAL_MATH_LIB"] + " " + vars["LIBCRUFT"]; +} + +static string usage_msg = "usage: mkoctfile [options] file ..."; +static string version_msg = "mkoctfile, version " + OCTAVE_VERSION; +static bool debug = false; +static string help_msg = +"\n" +"Options:\n" +"\n" +" -h, -?, --help Print this message.\n" +"\n" +" -IDIR Add -IDIR to compile commands.\n" +"\n" +" -idirafter DIR Add -idirafter DIR to compile commands.\n" +"\n" +" -DDEF Add -DDEF to compile commands.\n" +"\n" +" -lLIB Add library LIB to link command.\n" +"\n" +" -LDIR Add -LDIR to link command.\n" +"\n" +" -M, --depend Generate dependency files (.d) for C and C++\n" +" source files.\n" +"\n" +" -RDIR Add -RDIR to link command.\n" +"\n" +" -Wl,... Pass flags though the linker like -Wl,-rpath=...\n" +"\n" +" -W... Pass flags though the compiler like -Wa,OPTION.\n" +"\n" +" -c, --compile Compile, but do not link.\n" +"\n" +" -o FILE, --output FILE Output file name. Default extension is .oct\n" +" (or .mex if --mex is specified) unless linking\n" +" a stand-alone executable.\n" +"\n" +" -g Enable debugging options for compilers.\n" +"\n" +" -p VAR, --print VAR Print configuration variable VAR. Recognized\n" +" variables are:\n" +"\n" +" ALL_CFLAGS FFTW_LIBS \n" +" ALL_CXXFLAGS FLIBS \n" +" ALL_FFLAGS FPICFLAG \n" +" ALL_LDFLAGS INCFLAGS \n" +" BLAS_LIBS LDFLAGS \n" +" CC LD_CXX \n" +" CFLAGS LD_STATIC_FLAG\n" +" CPICFLAG LFLAGS \n" +" CPPFLAGS LIBCRUFT \n" +" CXX LIBOCTAVE \n" +" CXXFLAGS LIBOCTINTERP \n" +" CXXPICFLAG LIBREADLINE \n" +" DEPEND_EXTRA_SED_PATTERN LIBS \n" +" DEPEND_FLAGS OCTAVE_LIBS \n" +" DL_LD RDYNAMIC_FLAG \n" +" DL_LDFLAGS RLD_FLAG \n" +" F2C SED \n" +" F2CFLAGS XTRA_CFLAGS \n" +" F77 XTRA_CXXFLAGS \n" +" FFLAGS\n" +"\n" +" --link-stand-alone Link a stand-alone executable file.\n" +"\n" +" --mex Assume we are creating a MEX file. Set the\n" +" default output extension to \".mex\".\n" +"\n" +" -s, --strip Strip output file.\n" +"\n" +" -v, --verbose Echo commands as they are executed.\n" +"\n" +" FILE Compile or link FILE. Recognized file types are:\n" +"\n" +" .c C source\n" +" .cc C++ source\n" +" .C C++ source\n" +" .cpp C++ source\n" +" .f Fortran source (fixed form)\n" +" .F Fortran source (fixed form)\n" +" .f90 Fortran source (free form)\n" +" .F90 Fortran source (free form)\n" +" .o object file\n" +" .a library file\n" +#ifdef _MSC_VER +" .lib library file\n" +#endif +"\n"; + +static string basename(const string& s, bool strip_path = false) +{ + size_t pos = s.rfind('.'); + string retval; + + if (pos == string::npos) + retval = s; + else + retval = s.substr(0, pos); + if (strip_path) + { + size_t p1 = retval.rfind('/'), p2 = retval.rfind('\\'); + pos = (p1 != string::npos && p2 != string::npos ? max(p1, p2) : (p2 != string::npos ? p2 : p1)); + if (pos != string::npos) + retval = retval.substr(0, pos); + } + return retval; +} + +inline bool starts_with(const string& s, const string& prefix) +{ + return (s.length() >= prefix.length() && s.find(prefix) == 0); +} + +inline bool ends_with(const string& s, const string& suffix) +{ + return (s.length() >= suffix.length() && s.rfind(suffix) == s.length()-suffix.length()); +} + +static int run_command(const string& cmd) +{ + if (debug) + cout << cmd << endl; + return system(cmd.c_str()); +} + +int main(int argc, char **argv) +{ + initialize(); + + string objfiles, libfiles, octfile, outputfile, incflags, defs, ldflags, pass_on_options, output_ext, file, output_option, cmd; + bool strip, no_oct_file_strip_on_this_platform, link, link_stand_alone, depend, compile; + list<string> cfiles, ccfiles, f77files; + int result = 0; + + //cfiles = ""; + //ccfiles = ""; + //f77files = ""; + objfiles = ""; + libfiles = ""; + octfile = ""; + outputfile = ""; + incflags = ""; + defs = ""; + ldflags = ""; + pass_on_options = ""; + strip = false; + no_oct_file_strip_on_this_platform = %NO_OCT_FILE_STRIP%; + link = true; + link_stand_alone = false; + output_ext = ".oct"; + depend = false; + compile = true; + + if (argc == 1) + { + cout << usage_msg << endl; + return 1; + } + + if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) + { + cout << version_msg << endl; + return 0; + } + + for (int i=1; i<argc; i++) + { + string arg = argv[i]; + size_t len = arg.length(); + + if (ends_with(arg, ".c")) + { + file = arg; + cfiles.push_back(file); + } + else if (ends_with(arg, ".cc") || ends_with(arg, ".C") || ends_with(arg, ".cpp")) + { + file = arg; + ccfiles.push_back(file); + } + else if (ends_with(arg, ".f") || ends_with(arg, ".F") || + ends_with(arg, "f90") || ends_with(arg, ".F90")) + { + file = arg; + f77files.push_back(file); + } + else if (ends_with(arg, ".o") || ends_with(arg, ".obj")) + { + file = arg; + objfiles += (" " + quote_path(arg)); + } + else if (ends_with(arg, ".lib") || ends_with(arg, ".a")) + { + file = arg; + libfiles += (" " + quote_path(arg)); + } + else if (arg == "-d" || arg == "--debug" || arg == "-v" || arg == "--verbose") + { + debug = true; + if (vars["CC"] == "cc-msvc") + vars["CC"] += " -d"; + if (vars["CXX"] == "cc-msvc") + vars["CXX"] += " -d"; + if (vars["DL_LD"] == "cc-msvc") + vars["DL_LD"] += " -d"; + } + else if (arg == "-h" || arg == "-?" || arg == "--help") + { + cout << usage_msg << endl; + cout << help_msg << endl; + return 0; + } + else if (starts_with(arg, "-I")) + { + incflags += (" " + quote_path(arg)); + } + else if (arg == "-idirafter") + { + if (i < argc-1) + { + arg = argv[++i]; + incflags += (" -idirafter " + arg); + } + else + cerr << "mkoctfile: include directory name missing" << endl; + } + else if (starts_with(arg, "-D")) + { + defs += (" " + arg); + } + else if (starts_with(arg, "-Wl,") || starts_with(arg, "-l") || starts_with(arg, "-L") || starts_with(arg, "-R")) + { + ldflags += (" " + arg); + } + else if (arg == "-M" || arg == "--depend") + { + depend = true; + compile = false; + } + else if (arg == "-o" || arg == "--output") + { + if (i < argc-1) + { + arg = argv[++i]; + outputfile = arg; + } + else + cerr << "mkoctfile: output file name missing" << endl; + } + else if (arg == "-p" || arg == "--print") + { + if (i < argc-1) + { + arg = argv[++i]; + cout << vars[arg] << endl; + return 0; + } + else + cerr << "mkoctfile: --print requires argument" << endl; + } + else if (arg == "-s" || arg == "--strip") + { + if (no_oct_file_strip_on_this_platform) + cerr << "mkoctfile: stripping disabled on this platform" << endl; + else + strip = true; + } + else if (arg == "-c" || arg == "--compile") + { + link = false; + } + else if (arg == "-g") + { + vars["ALL_CFLAGS"] += " -g"; + vars["ALL_CXXFLAGS"] += " -g"; + vars["ALL_FFLAGS"] += " -g"; + } + else if (arg == "--link-stand-alone") + { + link_stand_alone = true; + } + else if (arg == "--mex") + { + incflags += " -I."; + ldflags += " -Wl,-export:mexFunction"; + output_ext = ".mex"; + } + else if (starts_with(arg, "-W")) + { + pass_on_options += (" " + arg); + } + else + { + cerr << "mkoctfile: unrecognized argument " << arg; + return 1; + } + + if (!file.empty() && octfile.empty()) + octfile = file; + } + + if (link_stand_alone) + { + if (!outputfile.empty()) + output_option = "-o " + outputfile; + } + else + { + if (!outputfile.empty()) + octfile = outputfile; + else + octfile = basename(octfile, true) + output_ext; + } + + list<string>::const_iterator it; + + if (depend) + { + for (it=cfiles.begin(); it!=cfiles.end(); ++it) + { + string f = *it, dfile = basename(f) + ".d", line; + + unlink(dfile.c_str()); + cmd = vars["CC"] + " " + vars["DEPEND_FLAGS"] + " " + vars["CPPFLAGS"] + " " + + vars["ALL_CFLAGS"] + " " + incflags + " " + defs + " " + quote_path(f); + + FILE *fd = popen(cmd.c_str(), "r"); + ofstream fo(dfile.c_str()); + int pos; + while (!feof(fd)) + { + line = get_line(fd); + if ((pos=line.rfind(".o:")) != string::npos) + { + int spos = line.rfind('/', pos); + string ofile = (spos == string::npos ? line.substr(0, pos+2) : line.substr(spos+1, pos-spos+1)); + fo << "pic/" << ofile << " " << ofile << " " << dfile << line.substr(pos) << endl; + } + else + fo << line << endl; + } + pclose(fd); + fo.close(); + } + + for (it=ccfiles.begin(); it!=ccfiles.end(); ++it) + { + string f = *it, dfile = basename(f) + ".d", line; + + unlink(dfile.c_str()); + cmd = vars["CC"] + " " + vars["DEPEND_FLAGS"] + " " + vars["CPPFLAGS"] + " " + + vars["ALL_CXXFLAGS"] + " " + incflags + " " + defs + " " + quote_path(f); + + FILE *fd = popen(cmd.c_str(), "r"); + ofstream fo(dfile.c_str()); + int pos; + while (!feof(fd)) + { + line = get_line(fd); + if ((pos=line.rfind(".o:")) != string::npos) + { + int spos = line.rfind('/', pos); + string ofile = (spos == string::npos ? line.substr(0, pos+2) : line.substr(spos+1, pos-spos+1)); + fo << "pic/" << ofile << " " << ofile << " " << dfile << line.substr(pos+2) << endl; + } + else + fo << line << endl; + } + pclose(fd); + fo.close(); + } + + return 0; + } + + for (it=f77files.begin(); it!=f77files.end(); ++it) + { + string f = *it, b = basename(f); + if (!vars["F2C"].empty() && vars["F2C"] != "@F2C@") + { + string c = b + ".c"; + cfiles.push_back(c); + cmd = vars["F2C"] + " " + vars["F2CFLAGS"] + " < " + f + " > " + c; + result = run_command(cmd); + } + else if (!vars["F77"].empty()) + { + string o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["F77"] + " -c " + vars["FPICFLAG"] + " " + vars["ALL_FFLAGS"] + " " + incflags + " " + defs + " " + + pass_on_options + " " + f + " -o " + o; + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile Fortran file " << f << endl; + return 1; + } + } + + for (it=cfiles.begin(); it!=cfiles.end(); ++it) + { + string f = *it; + if (!vars["CC"].empty()) + { + string b = basename(f), o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["CC"] + " -c " + vars["CPPFLAGS"] + " " + vars["CPICFLAG"] + " " + vars["ALL_CFLAGS"] + " " + + pass_on_options + " " + incflags + " " + defs + " " + quote_path(f) + " -o " + quote_path(o); + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile C file " << f << endl; + return 1; + } + } + + for (it=ccfiles.begin(); it!=ccfiles.end(); ++it) + { + string f = *it; + if (!vars["CXX"].empty()) + { + string b = basename(f), o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["CXX"] + " -c " + vars["CPPFLAGS"] + " " + vars["CXXPICFLAG"] + " " + vars["ALL_CXXFLAGS"] + " " + + pass_on_options + " " + incflags + " " + defs + " " + quote_path(f) + " -o " + quote_path(o); + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile C++ file " << f << endl; + return 1; + } + } + + if (link && !objfiles.empty()) + { + if (link_stand_alone) + { + if (!vars["LD_CXX"].empty()) + { + cmd= vars["LD_CXX"] + " " + vars["CPPFLAGS"] + " " + vars["ALL_CXXFLAGS"] + " " + vars["RDYNAMIC_FLAG"] + " " + + vars["ALL_LDFLAGS"] + " " + pass_on_options + " " + output_option + " " + objfiles + " " + libfiles + " " + + ldflags + " " + vars["LFLAGS"] + " " + vars["RLD_FLAG"] + " " + vars["OCTAVE_LIBS"] + " " + + vars["BLAS_LIBS"] + " " + vars["FFTW_LIBS"] + " " + vars["LIBREADLINE"] + " " + vars["LIBS"] + " " + + vars["FLIBS"]; + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to link stand-alone executable file" << endl; + return 1; + } + } + else + { + string LINK_DEPS = vars["LFLAGS"] + " " + vars["OCTAVE_LIBS"] + " " + vars["LDFLAGS"] + " " + vars["BLAS_LIBS"] + " " + + vars["FFTW_LIBS"] + " " + vars["LIBS"] + " " + vars["FLIBS"]; + cmd = vars["DL_LD"] + " " + vars["DL_LDFLAGS"] + " " + pass_on_options + " -o " + octfile + " " + objfiles + " " + + libfiles + " " + ldflags + " " + LINK_DEPS; + result = run_command(cmd); + } + + if (strip) + { + cmd = "strip " + octfile; + result = run_command(cmd); + } + } + + return result; +}