view mkoctfile.cc.in @ 8968:91d53dc37f79

Add perm * sparse, perm \ sparse, sparse * perm, and sparse / perm operations. Nothing terribly fancy in any of this. There probably is some mechanism for using the permutation vectors and some assign or index method in the sparse classes, but I've never understood all the intricacies. I'm opting for a simple implementation at the cost of possibly duplicating some functionality.
author Jason Riedy <jason@acm.org>
date Tue, 10 Mar 2009 21:54:44 -0400
parents eb63fbe60fab
children a3237ae32c0d
line wrap: on
line source

/*

Copyright (C) 2008 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"] + "\\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 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")))
    {
      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 ());
	  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) + ".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);
      if (!vars["F2C"].empty () && vars["F2C"] != "@F2C@")
	{
	  string c = b + ".c";
	  cfiles.push_back (c);
	  string 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);
	  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), 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), 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["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"];
	  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;
}