Mercurial > hg > octave-nkf
view mkoctfile.cc.in @ 10824:1e6664326d32
rsf2csf: Change first documentation line to active voice.
author | Rik <octave@nomad.inbox5.com> |
---|---|
date | Tue, 27 Jul 2010 10:46:11 -0700 |
parents | 4906ccf5d95e |
children | 77989197a3c7 |
line wrap: on
line source
/* Copyright (C) 2008, 2009 Michael Goffioul This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ #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 (true) { c = static_cast<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 + "\""; else 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"]); #else std::string DEFAULT_INCFLAGS = "-I" + quote_path (vars["OCTINCLUDEDIR"] + "/..") + " -I" + quote_path (vars["OCTINCLUDEDIR"]); #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["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["READLINE_LIBS"] = "-lreadline"; vars["LIBCRUFT"] = "-lcruft"; vars["BLAS_LIBS"] = get_variable ("BLAS_LIBS", %OCTAVE_CONF_BLAS_LIBS%); vars["FFTW3_LDFLAGS"] = get_variable ("FFTW3_LDFLAGS", %OCTAVE_CONF_FFTW3_LDFLAGS%); vars["FFTW3_LIBS"] = get_variable ("FFTW3_LIBS", %OCTAVE_CONF_FFTW3_LIBS%); vars["FFTW3F_LDFLAGS"] = get_variable ("FFTW3F_LDFLAGS", %OCTAVE_CONF_FFTW3F_LDFLAGS%); vars["FFTW3F_LIBS"] = get_variable ("FFTW3F_LIBS", %OCTAVE_CONF_FFTW3F_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["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG", %OCTAVE_CONF_F77_INTEGER8_FLAG%); vars["ALL_FFLAGS"] = vars["FFLAGS"] + " " + vars["F77_INTEGER8_FLAG"]; 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"]; vars["FFTW_LIBS"] = vars["FFTW3_LDFLAGS"] + " " + vars["FFTW3_LIBS"] + " " + vars["FFTW3F_LDFLAGS"] + " " + vars["FFTW3F_LIBS"]; } 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 FLIBS\n" " ALL_CXXFLAGS FPICFLAG\n" " ALL_FFLAGS INCFLAGS\n" " ALL_LDFLAGS LDFLAGS\n" " BLAS_LIBS LD_CXX\n" " CC LD_STATIC_FLAG\n" " CFLAGS LFLAGS\n" " CPICFLAG LIBCRUFT\n" " CPPFLAGS LIBOCTAVE\n" " CXX LIBOCTINTERP\n" " CXXFLAGS LIBS\n" " CXXPICFLAG OCTAVE_LIBS\n" " DEPEND_EXTRA_SED_PATTERN RDYNAMIC_FLAG\n" " DEPEND_FLAGS READLINE_LIBS\n" " DL_LD RLD_FLAG\n" " DL_LDFLAGS SED\n" " F77 XTRA_CFLAGS\n" " FFLAGS XTRA_CXXFLAGS\n" " FFTW_LIBS\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 file, output_option; list<string> cfiles, ccfiles, f77files; int result = 0; string objfiles = ""; string libfiles = ""; string octfile = ""; string outputfile = ""; string incflags = ""; string defs = ""; string ldflags = ""; string pass_on_options = ""; bool strip = false; bool no_oct_file_strip_on_this_platform = %NO_OCT_FILE_STRIP%; bool link = true; bool link_stand_alone = false; string output_ext = ".oct"; bool depend = false; bool compile = true; if (argc == 1) { cout << usage_msg << endl; return 1; } if (argc == 2 && (!strcmp (argv[1], "-v") || !strcmp (argv[1], "-version") || !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 == "--debug" || arg == "-v" || arg == "-verbose" || 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" || 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" || arg == "--depend") { depend = true; compile = false; } else if (arg == "-o" || arg == "-output" || 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" || 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" || 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" || 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" || arg == "--link-stand-alone") { link_stand_alone = true; } else if (arg == "-mex" || arg == "--mex") { incflags += " -I."; #ifdef _MSC_VER ldflags += " -Wl,-export:mexFunction"; #endif 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; size_t len = octfile.length (); size_t len_ext = output_ext.length (); if (octfile.substr (len-len_ext) != output_ext) octfile += output_ext; } 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, true) + ".d", line; unlink (dfile.c_str ()); string 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, true) + ".d", line; unlink (dfile.c_str ()); string 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, true); if (!vars["F77"].empty ()) { string o; if (!outputfile.empty ()) { if (link) o = b + ".o"; else o = outputfile; } else o = b + ".o"; objfiles += (" " + o); string 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, true), o; if (!outputfile.empty ()) { if (link) o = b + ".o"; else o = outputfile; } else o = b + ".o"; objfiles += (" " + o); string 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, true), o; if (!outputfile.empty ()) { if (link) o = b + ".o"; else o = outputfile; } else o = b + ".o"; objfiles += (" " + o); string 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 ()) { string 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["READLINE_LIBS"] + " " + 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"]; string cmd = vars["DL_LD"] + " " + vars["DL_LDFLAGS"] + " " + pass_on_options + " -o " + octfile + " " + objfiles + " " + libfiles + " " + ldflags + " " + LINK_DEPS; result = run_command (cmd); } if (strip) { string cmd = "strip " + octfile; result = run_command (cmd); } } return result; }