GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mkoctfile.cc
Go to the documentation of this file.
1 // DO NOT EDIT! Generated automatically by subst-config-vals.
2 
3 ////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2008-2024 The Octave Project Developers
6 //
7 // See the file COPYRIGHT.md in the top-level directory of this
8 // distribution or <https://octave.org/copyright/>.
9 //
10 // This file is part of Octave.
11 //
12 // Octave is free software: you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // Octave is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with Octave; see the file COPYING. If not, see
24 // <https://www.gnu.org/licenses/>.
25 //
26 ////////////////////////////////////////////////////////////////////////
27 
28 #if defined (HAVE_CONFIG_H)
29 # include "config.h"
30 #endif
31 
32 #include <string>
33 #include <cstring>
34 #include <map>
35 #include <list>
36 #include <algorithm>
37 #include <iostream>
38 #include <fstream>
39 #include <sstream>
40 #include <vector>
41 #include <cstdlib>
42 
43 #if defined (OCTAVE_USE_WINDOWS_API)
44 # include <locale>
45 # include <codecvt>
46 #endif
47 
48 // Programming note: The CROSS macro here refers to building a
49 // cross-compiler aware version of mkoctfile that can be used to cross
50 // compile .oct file for Windows builds of Octave, not that mkoctfile
51 // itself is being cross compiled.
52 //
53 // We don't use the wrapper and gnulib functions when we are building
54 // with CROSS defined. This configuration is only expected to work on
55 // modern systems that should not need to have gnulib to fix POSIX
56 // portability problems. So we just assume a working POSIX system when
57 // CROSS is defined.
58 
59 #if defined (CROSS)
60 # include <stdlib.h>
61 # include <sys/types.h>
62 # include <sys/wait.h>
63 # include <unistd.h>
64 # ifndef OCTAVE_UNUSED
65 # define OCTAVE_UNUSED
66 # endif
67 #else
68 // We are linking against static libs so do not decorate with dllimport.
69 // FIXME: This should be done by the build system.
70 # undef OCTAVE_API
71 # define OCTAVE_API
72 # include "mkostemps-wrapper.h"
73 # include "uniconv-wrappers.h"
74 # include "unistd-wrappers.h"
75 # include "wait-wrappers.h"
76 #endif
77 
78 #if ! defined (OCTAVE_VERSION)
79 # define OCTAVE_VERSION "9.1.0"
80 #endif
81 
82 #if ! defined (OCTAVE_PREFIX)
83 # define OCTAVE_PREFIX "/usr/local"
84 #endif
85 
86 #if ! defined (OCTAVE_EXEC_PREFIX)
87 # define OCTAVE_EXEC_PREFIX "/usr/local"
88 #endif
89 
90 #include "shared-fcns.h"
91 
92 #if defined (CROSS)
93 
94 static int
95 octave_mkostemps_wrapper (char *tmpl, int suffixlen)
96 {
97  return mkostemps (tmpl, suffixlen, 0);
98 }
99 
100 static int
101 octave_unlink_wrapper (const char *nm)
102 {
103  return unlink (nm);
104 }
105 
106 static bool
107 octave_wifexited_wrapper (int status)
108 {
109  return WIFEXITED (status);
110 }
111 
112 static int
113 octave_wexitstatus_wrapper (int status)
114 {
115  return WEXITSTATUS (status);
116 }
117 
118 #endif
119 
120 static std::string
121 get_line (FILE *fp)
122 {
123  std::ostringstream buf;
124 
125  while (true)
126  {
127  int c = std::fgetc (fp);
128 
129  if (c == '\n' || c == EOF)
130  break;
131 
132  buf << static_cast<char> (c);
133  }
134 
135  return buf.str ();
136 }
137 
138 static std::string
139 get_variable (const char *name, const std::string& defval)
140 {
141  const char *val = getenv (name);
142 
143  if (val && *val)
144  return std::string (val);
145  else
146  return defval;
147 }
148 
149 static std::string
150 quote_path (const std::string& s)
151 {
152  if (s.find (' ') != std::string::npos && s[0] != '"')
153  return '"' + s + '"';
154  else
155  return s;
156 }
157 
158 static std::string
159 replace_prefix (std::string s)
160 {
161 #if defined (OCTAVE_REPLACE_PREFIX)
162  const std::string match = "${prefix}";
163  const std::string repl = Voctave_exec_home;
164  std::size_t pos = s.find (match);
165  while (pos != std::string::npos )
166  {
167  // Quote replacement path if the input isn't quoted.
168  if (pos > 0 && s[pos-1] != '"' && s[pos-1] != '\'')
169  s.replace (pos, match.length (), quote_path (repl));
170  else
171  s.replace (pos, match.length (), repl);
172  pos = s.find (match);
173  }
174 #endif
175 
176  return s;
177 }
178 
179 static std::map<std::string, std::string>
180 make_vars_map (bool link_stand_alone, bool verbose, bool debug)
181 {
182  set_octave_home ();
183 
184  std::map<std::string, std::string> vars;
185 
186  vars["OCTAVE_HOME"] = Voctave_home;
187  vars["OCTAVE_EXEC_HOME"] = Voctave_exec_home;
188 
189  vars["API_VERSION"] = "api-v59";
190  vars["CANONICAL_HOST_TYPE"] = "x86_64-pc-linux-gnu";
191  vars["DEFAULT_PAGER"] = "less";
192  vars["EXEEXT"] = "";
193  vars["MAN1EXT"] = ".1";
194  vars["OCTAVE_VERSION"] = "9.1.0";
195 
196  vars["ARCHLIBDIR"] = prepend_octave_exec_home ("libexec/octave/9.1.0/exec/x86_64-pc-linux-gnu");
197  vars["BINDIR"] = prepend_octave_exec_home ("bin");
198  vars["DATADIR"] = prepend_octave_home ("share");
199  vars["DATAROOTDIR"] = prepend_octave_home ("share");
200  vars["FCNFILEDIR"] = prepend_octave_home ("share/octave/9.1.0/m");
201  vars["IMAGEDIR"] = prepend_octave_home ("share/octave/9.1.0/imagelib");
202  vars["INFODIR"] = prepend_octave_home ("share/info");
203  vars["INFOFILE"] = prepend_octave_home ("share/info/octave.info");
204  vars["LIBEXECDIR"] = prepend_octave_exec_home ("libexec");
205  vars["LOCALAPIARCHLIBDIR"] = prepend_octave_exec_home ("libexec/octave/api-v59/site/exec/x86_64-pc-linux-gnu");
206  vars["LOCALAPIFCNFILEDIR"] = prepend_octave_home ("share/octave/site/api-v59/m");
207  vars["LOCALAPIOCTFILEDIR"] = prepend_octave_exec_home ("lib/octave/site/oct/api-v59/x86_64-pc-linux-gnu");
208  vars["LOCALARCHLIBDIR"] = prepend_octave_exec_home ("libexec/octave/site/exec/x86_64-pc-linux-gnu");
209  vars["LOCALFCNFILEDIR"] = prepend_octave_home ("share/octave/site/m");
210  vars["LOCALOCTFILEDIR"] = prepend_octave_exec_home ("lib/octave/site/oct/x86_64-pc-linux-gnu");
211  vars["LOCALSTARTUPFILEDIR"] = prepend_octave_home ("share/octave/site/m/startup");
212  vars["LOCALVERARCHLIBDIR"] = prepend_octave_exec_home ("libexec/octave/9.1.0/site/exec/x86_64-pc-linux-gnu");
213  vars["LOCALVERFCNFILEDIR"] = prepend_octave_home ("share/octave/9.1.0/site/m");
214  vars["LOCALVEROCTFILEDIR"] = prepend_octave_exec_home ("lib/octave/9.1.0/site/oct/x86_64-pc-linux-gnu");
215  vars["MAN1DIR"] = prepend_octave_home ("share/man/man1");
216  vars["MANDIR"] = prepend_octave_home ("share/man");
217  vars["OCTDATADIR"] = prepend_octave_home ("share/octave/9.1.0/data");
218  vars["OCTDOCDIR"] = prepend_octave_home ("share/octave/9.1.0/doc");
219  vars["OCTFILEDIR"] = prepend_octave_exec_home ("lib/octave/9.1.0/oct/x86_64-pc-linux-gnu");
220  vars["OCTFONTSDIR"] = prepend_octave_home ("share/octave/9.1.0/fonts");
221  vars["STARTUPFILEDIR"] = prepend_octave_home ("share/octave/9.1.0/m/startup");
222 
223  vars["OCTINCLUDEDIR"]
224  = get_variable ("OCTINCLUDEDIR",
225  prepend_octave_home ("include/octave-9.1.0/octave"));
226 
227  vars["INCLUDEDIR"]
228  = get_variable ("INCLUDEDIR",
229  prepend_octave_home ("include"));
230 
231  vars["LIBDIR"]
232  = get_variable ("LIBDIR", prepend_octave_exec_home ("lib"));
233 
234  vars["OCTLIBDIR"]
235  = get_variable ("OCTLIBDIR",
236  prepend_octave_exec_home ("lib/octave/9.1.0"));
237 
238  std::string DEFAULT_INCFLAGS;
239 
240 #if defined (OCTAVE_USE_WINDOWS_API)
241  DEFAULT_INCFLAGS = "-I" + quote_path (vars["OCTINCLUDEDIR"] + R"(\..)")
242  + " -I" + quote_path (vars["OCTINCLUDEDIR"]);
243 #else
244  DEFAULT_INCFLAGS = "-I" + quote_path (vars["OCTINCLUDEDIR"] + "/..")
245  + " -I" + quote_path (vars["OCTINCLUDEDIR"]);
246 #endif
247 
248  if (vars["INCLUDEDIR"] != "/usr/include")
249  DEFAULT_INCFLAGS += " -I" + quote_path (vars["INCLUDEDIR"]);
250 
251  std::string DEFAULT_LDFLAGS;
252 
253 #if (defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS) || defined (OCTAVE_LINK_ALL_DEPS))
254  // We'll be linking the files we compile with -loctinterp and -loctave,
255  // so we need to know where to find them.
256  DEFAULT_LDFLAGS += "-L" + quote_path (vars["OCTLIBDIR"]);
257 #endif
258 
259  if (vars["LIBDIR"] != "/usr/lib")
260  DEFAULT_LDFLAGS += " -L" + quote_path (vars["LIBDIR"]);
261 
262  vars["CPPFLAGS"] = get_variable ("CPPFLAGS",
263  replace_prefix (" "));
264 
265  vars["INCFLAGS"] = get_variable ("INCFLAGS", DEFAULT_INCFLAGS);
266 
267  vars["F77"] = get_variable ("F77", "gfortran");
268 
269  vars["FFLAGS"] = get_variable ("FFLAGS", "-g -O2 -std=legacy");
270 
271  vars["FPICFLAG"] = get_variable ("FPICFLAG", "-fPIC");
272 
273  vars["CC"] = get_variable ("CC", "gcc");
274  if (verbose && vars["CC"] == "cc-msvc")
275  vars["CC"] += " -d";
276 
277  vars["CFLAGS"] = get_variable ("CFLAGS", "-g -O2");
278 
279  vars["CPICFLAG"] = get_variable ("CPICFLAG", "-fPIC");
280 
281  vars["CXX"] = get_variable ("CXX", "g++");
282  if (verbose && vars["CXX"] == "cc-msvc")
283  vars["CXX"] += " -d";
284 
285  vars["CXXFLAGS"] = get_variable ("CXXFLAGS", "-g -O2");
286 
287  vars["CXXLD"] = get_variable ("CXXLD", vars["CXX"]);
288  if (verbose && vars["CXXLD"] == "cc-msvc")
289  vars["CXXLD"] += " -d";
290 
291  vars["CXXPICFLAG"] = get_variable ("CXXPICFLAG", "-fPIC");
292 
293  vars["XTRA_CFLAGS"] = get_variable ("XTRA_CFLAGS", " -pthread -fopenmp");
294 
295  vars["XTRA_CXXFLAGS"] = get_variable ("XTRA_CXXFLAGS",
296  " -pthread -fopenmp");
297 
298  vars["AR"] = get_variable ("AR", "ar");
299 
300  vars["RANLIB"] = get_variable ("RANLIB", "ranlib");
301 
302  vars["DEPEND_FLAGS"] = get_variable ("DEPEND_FLAGS",
303  "-M");
304 
305  vars["DEPEND_EXTRA_SED_PATTERN"]
306  = get_variable ("DEPEND_EXTRA_SED_PATTERN",
307  "");
308 
309  vars["DL_LDFLAGS"] = get_variable ("DL_LDFLAGS",
310  "-shared -Wl,-Bsymbolic");
311 
312  if (! link_stand_alone)
313  DEFAULT_LDFLAGS += ' ' + vars["DL_LDFLAGS"];
314 
315  vars["RDYNAMIC_FLAG"] = get_variable ("RDYNAMIC_FLAG",
316  "-rdynamic");
317 
318  vars["LIBOCTAVE"] = "-loctave";
319 
320  vars["LIBOCTINTERP"] = "-loctinterp";
321 
322  vars["READLINE_LIBS"] = "-lreadline";
323 
324  vars["LAPACK_LIBS"] = get_variable ("LAPACK_LIBS", "");
325 
326  vars["BLAS_LIBS"] = get_variable ("BLAS_LIBS", "-lopenblas");
327 
328  vars["FFTW3_LDFLAGS"]
329  = get_variable ("FFTW3_LDFLAGS",
330  replace_prefix (""));
331 
332  vars["FFTW3_LIBS"] = get_variable ("FFTW3_LIBS", "-lfftw3_threads -lfftw3");
333 
334  vars["FFTW3F_LDFLAGS"]
335  = get_variable ("FFTW3F_LDFLAGS",
336  replace_prefix (""));
337 
338  vars["FFTW3F_LIBS"] = get_variable ("FFTW3F_LIBS", "-lfftw3f_threads -lfftw3f");
339 
340  vars["LIBS"] = get_variable ("LIBS", "-lsundials_ida -lsundials_nvecserial -lklu -lopenblas -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. -lgfortran -lm -lquadmath -lpthread -lm ");
341 
342  vars["FLIBS"] = get_variable ("FLIBS",
343  replace_prefix (" -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. -lgfortran -lm -lquadmath"));
344 
345  vars["OCTAVE_LINK_DEPS"] = get_variable ("OCTAVE_LINK_DEPS",
346  "");
347 
348  vars["OCTAVE_LINK_OPTS"] = get_variable ("OCTAVE_LINK_OPTS",
349  "");
350 
351  vars["OCT_LINK_DEPS"] = get_variable ("OCT_LINK_DEPS",
352  "");
353 
354  vars["OCT_LINK_OPTS"]
355  = get_variable ("OCT_LINK_OPTS",
356  replace_prefix (" "));
357 
358  vars["LDFLAGS"] = get_variable ("LDFLAGS", DEFAULT_LDFLAGS);
359 
360  vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG",
361  "");
362 
363  vars["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG",
364  "");
365  vars["ALL_FFLAGS"] = vars["FFLAGS"] + ' ' + vars["F77_INTEGER8_FLAG"];
366  if (debug)
367  vars["ALL_FFLAGS"] += " -g";
368 
369  vars["ALL_CFLAGS"]
370  = vars["INCFLAGS"] + ' ' + vars["XTRA_CFLAGS"] + ' ' + vars["CFLAGS"];
371  if (debug)
372  vars["ALL_CFLAGS"] += " -g";
373 
374  vars["ALL_CXXFLAGS"]
375  = vars["INCFLAGS"] + ' ' + vars["XTRA_CXXFLAGS"] + ' ' + vars["CXXFLAGS"];
376  if (debug)
377  vars["ALL_CXXFLAGS"] += " -g";
378 
379  vars["ALL_LDFLAGS"]
380  = vars["LD_STATIC_FLAG"] + ' ' + vars["CPICFLAG"] + ' ' + vars["LDFLAGS"];
381 
382  vars["OCTAVE_LIBS"]
383  = (vars["LIBOCTINTERP"] + ' ' + vars["LIBOCTAVE"] + ' '
384  + vars["SPECIAL_MATH_LIB"]);
385 
386  vars["FFTW_LIBS"] = vars["FFTW3_LDFLAGS"] + ' ' + vars["FFTW3_LIBS"] + ' '
387  + vars["FFTW3F_LDFLAGS"] + ' ' + vars["FFTW3F_LIBS"];
388 
389  return vars;
390 }
391 
392 static std::string usage_msg = "usage: mkoctfile [options] file ...";
393 
394 static std::string version_msg = "mkoctfile, version " OCTAVE_VERSION;
395 
396 static std::string help_msg =
397  "\n"
398  "Options:\n"
399  "\n"
400  " -h, -?, --help Print this message.\n"
401  "\n"
402  " -IDIR Add -IDIR to compile commands.\n"
403  "\n"
404  " -idirafter DIR Add -idirafter DIR to compile commands.\n"
405  "\n"
406  " -DDEF Add -DDEF to compile commands.\n"
407  "\n"
408  " -lLIB Add library LIB to link command.\n"
409  "\n"
410  " -LDIR Add -LDIR to link command.\n"
411  "\n"
412  " -M, --depend Generate dependency files (.d) for C and C++\n"
413  " source files.\n"
414 #if ! defined (OCTAVE_USE_WINDOWS_API)
415  "\n"
416  " -pthread Add -pthread to link command.\n"
417 #endif
418  "\n"
419  " -RDIR Add -RDIR to link command.\n"
420  "\n"
421  " -Wl,... Pass flags though the linker like -Wl,-rpath=...\n"
422  "\n"
423  " -W... Pass flags though the compiler like -Wa,OPTION.\n"
424  "\n"
425  " -c, --compile Compile, but do not link.\n"
426  "\n"
427  " -o FILE, --output FILE Output filename. Default extension is .oct\n"
428  " (or .mex if --mex is specified) unless linking\n"
429  " a stand-alone executable.\n"
430  "\n"
431  " -g Enable debugging options for compilers.\n"
432  "\n"
433  " -p VAR, --print VAR Print configuration variable VAR. There are\n"
434  " three categories of variables:\n"
435  "\n"
436  " Octave configuration variables that users may\n"
437  " override with environment variables. These are\n"
438  " used in commands that mkoctfile executes.\n"
439  "\n"
440  " ALL_CFLAGS INCLUDEDIR\n"
441  " ALL_CXXFLAGS LAPACK_LIBS\n"
442  " ALL_FFLAGS LDFLAGS\n"
443  " ALL_LDFLAGS LD_STATIC_FLAG\n"
444  " BLAS_LIBS LIBDIR\n"
445  " CC LIBOCTAVE\n"
446  " CFLAGS LIBOCTINTERP\n"
447  " CPICFLAG OCTAVE_LINK_OPTS\n"
448  " CPPFLAGS OCTINCLUDEDIR\n"
449  " CXX OCTAVE_LIBS\n"
450  " CXXFLAGS OCTAVE_LINK_DEPS\n"
451  " CXXLD OCTLIBDIR\n"
452  " CXXPICFLAG OCT_LINK_DEPS\n"
453  " DL_LDFLAGS OCT_LINK_OPTS\n"
454  " F77 RDYNAMIC_FLAG\n"
455  " F77_INTEGER8_FLAG SPECIAL_MATH_LIB\n"
456  " FFLAGS XTRA_CFLAGS\n"
457  " FPICFLAG XTRA_CXXFLAGS\n"
458  " INCFLAGS\n"
459  "\n"
460  " Octave configuration variables as above, but\n"
461  " currently unused by mkoctfile.\n"
462  "\n"
463  " AR\n"
464  " DEPEND_EXTRA_SED_PATTERN\n"
465  " DEPEND_FLAGS\n"
466  " FFTW3F_LDFLAGS\n"
467  " FFTW3F_LIBS\n"
468  " FFTW3_LDFLAGS\n"
469  " FFTW3_LIBS\n"
470  " FFTW_LIBS\n"
471  " FLIBS\n"
472  " LIBS\n"
473  " RANLIB\n"
474  " READLINE_LIBS\n"
475  "\n"
476  " Octave configuration variables that are provided\n"
477  " for informational purposes only. Except for\n"
478  " OCTAVE_HOME and OCTAVE_EXEC_HOME, users may not\n"
479  " override these variables.\n"
480  "\n"
481  " If OCTAVE_HOME or OCTAVE_EXEC_HOME are set in\n"
482  " the environment, then other variables are adjusted\n"
483  " accordingly with OCTAVE_HOME or OCTAVE_EXEC_HOME\n"
484  " substituted for the original value of the directory\n"
485  " specified by the --prefix or --exec-prefix options\n"
486  " that were used when Octave was configured.\n"
487  "\n"
488  " API_VERSION LOCALFCNFILEDIR\n"
489  " ARCHLIBDIR LOCALOCTFILEDIR\n"
490  " BINDIR LOCALSTARTUPFILEDIR\n"
491  " CANONICAL_HOST_TYPE LOCALVERARCHLIBDIR\n"
492  " DATADIR LOCALVERFCNFILEDIR\n"
493  " DATAROOTDIR LOCALVEROCTFILEDIR\n"
494  " DEFAULT_PAGER MAN1DIR\n"
495  " EXEC_PREFIX MAN1EXT\n"
496  " EXEEXT MANDIR\n"
497  " FCNFILEDIR OCTAVE_EXEC_HOME\n"
498  " IMAGEDIR OCTAVE_HOME\n"
499  " INFODIR OCTAVE_VERSION\n"
500  " INFOFILE OCTDATADIR\n"
501  " LIBEXECDIR OCTDOCDIR\n"
502  " LOCALAPIARCHLIBDIR OCTFILEDIR\n"
503  " LOCALAPIFCNFILEDIR OCTFONTSDIR\n"
504  " LOCALAPIOCTFILEDIR STARTUPFILEDIR\n"
505  " LOCALARCHLIBDIR\n"
506  "\n"
507  " --link-stand-alone Link a stand-alone executable file.\n"
508  "\n"
509  " --mex Assume we are creating a MEX file. Set the\n"
510  " default output extension to \".mex\".\n"
511  "\n"
512  " -s, --strip Strip output file.\n"
513  "\n"
514  " -n, --just-print, --dry-run\n"
515  " Print commands, but do not execute them.\n"
516  "\n"
517  " -v, --verbose Echo commands as they are executed.\n"
518  "\n"
519  " --silent Ignored. Intended to suppress output from\n"
520  " compiler steps.\n"
521  "\n"
522  " FILE Compile or link FILE. Recognized file types are:\n"
523  "\n"
524  " .c C source\n"
525  " .cc C++ source\n"
526  " .cp C++ source\n"
527  " .cpp C++ source\n"
528  " .CPP C++ source\n"
529  " .cxx C++ source\n"
530  " .c++ C++ source\n"
531  " .C C++ source\n"
532  " .f Fortran source (fixed form)\n"
533  " .F Fortran source (fixed form)\n"
534  " .f90 Fortran source (free form)\n"
535  " .F90 Fortran source (free form)\n"
536  " .o object file\n"
537  " .a library file\n"
538 #if defined (_MSC_VER)
539  " .lib library file\n"
540 #endif
541  "\n";
542 
543 static std::string
544 basename (const std::string& s, bool strip_path = false)
545 {
546  std::string retval;
547 
548  std::size_t pos = s.rfind ('.');
549 
550  if (pos == std::string::npos)
551  retval = s;
552  else
553  retval = s.substr (0, pos);
554 
555  if (strip_path)
556  {
557  std::size_t p1 = retval.rfind ('/'), p2 = retval.rfind ('\\');
558 
559  pos = (p1 != std::string::npos && p2 != std::string::npos
560  ? std::max (p1, p2) : (p2 != std::string::npos ? p2 : p1));
561 
562  if (pos != std::string::npos)
563  retval = retval.substr (++pos, std::string::npos);
564  }
565 
566  return retval;
567 }
568 
569 inline bool
570 starts_with (const std::string& s, const std::string& prefix)
571 {
572  return (s.length () >= prefix.length () && s.find (prefix) == 0);
573 }
574 
575 inline bool
576 ends_with (const std::string& s, const std::string& suffix)
577 {
578  return (s.length () >= suffix.length ()
579  && s.rfind (suffix) == s.length () - suffix.length ());
580 }
581 
582 static int
583 run_command (const std::string& cmd, bool verbose, bool printonly = false)
584 {
585  if (printonly)
586  {
587  std::cout << cmd << std::endl;
588  return 0;
589  }
590 
591  if (verbose)
592  std::cout << cmd << std::endl;
593 
594  // FIXME: Call _wsystem on Windows or octave::sys::system.
595  int result = system (cmd.c_str ());
596 
597  if (octave_wifexited_wrapper (result))
598  result = octave_wexitstatus_wrapper (result);
599 
600  return result;
601 }
602 
603 bool
604 is_true (const std::string& s)
605 {
606  return (s == "yes" || s == "true");
607 }
608 
609 static std::string
610 get_temp_directory ()
611 {
612  std::string tempd;
613 
614  tempd = octave_getenv ("TMPDIR");
615 
616 #if defined (__MINGW32__) || defined (_MSC_VER)
617 
618  if (tempd.empty ())
619  tempd = octave_getenv ("TEMP");
620 
621  if (tempd.empty ())
622  tempd = octave_getenv ("TMP");
623 
624 #if defined (P_tmpdir)
625  if (tempd.empty ())
626  tempd = P_tmpdir;
627 #endif
628 
629  // Some versions of MinGW and MSVC either don't define P_tmpdir, or
630  // define it to a single backslash. In such cases just use C:\temp.
631  if (tempd.empty () || tempd == R"(\)")
632  tempd = R"(c:\temp)";
633 
634 #else
635 
636 #if defined (P_tmpdir)
637  if (tempd.empty ())
638  tempd = P_tmpdir;
639 #else
640  if (tempd.empty ())
641  tempd = "/tmp";
642 #endif
643 
644 #endif
645 
646  return tempd;
647 }
648 
649 static std::string
650 create_interleaved_complex_file ()
651 {
652  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.c";
653 
654  char *ctmpl = new char [tmpl.length () + 1];
655 
656  ctmpl = strcpy (ctmpl, tmpl.c_str ());
657 
658  // mkostemps will open the file and return a file descriptor. We
659  // won't worry about closing it because we will need the file until we
660  // are done and then the file will be closed when mkoctfile exits.
661  int fd = octave_mkostemps_wrapper (ctmpl, 2);
662 
663  // Make C++ string from filled-in template.
664  std::string retval (ctmpl);
665  delete [] ctmpl;
666 
667  // Write symbol definition to file.
668  FILE *fid = fdopen (fd, "w");
669  fputs ("const int __mx_has_interleaved_complex__ = 1;\n", fid);
670  fclose (fid);
671 
672  return retval;
673 }
674 
675 static std::string
676 tmp_objfile_name ()
677 {
678  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";
679 
680  char *ctmpl = new char [tmpl.length () + 1];
681 
682  ctmpl = strcpy (ctmpl, tmpl.c_str ());
683 
684  // mkostemps will open the file and return a file descriptor. We
685  // won't worry about closing it because we will need the file until we
686  // are done and then the file will be closed when mkoctfile exits.
687  octave_mkostemps_wrapper (ctmpl, 2);
688 
689  std::string retval (ctmpl); // make C++ string from filled-in template
690  delete [] ctmpl;
691 
692  return retval;
693 }
694 
695 static void
696 clean_up_tmp_files (const std::list<std::string>& tmp_files)
697 {
698  for (const auto& file : tmp_files)
699  octave_unlink_wrapper (file.c_str ());
700 }
701 
702 #if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)
703 extern "C"
704 int
705 wmain (int argc, wchar_t **sys_argv)
706 {
707  std::vector<std::string> argv;
708 
709  // Convert wide character strings to multibyte UTF-8 strings and save
710  // them in a vector of std::string objects for later processing.
711 
712  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
713  for (int i_arg = 0; i_arg < argc; i_arg++)
714  argv.push_back (wchar_conv.to_bytes (sys_argv[i_arg]));
715 #else
716 int
717 main (int argc, char **sys_argv)
718 {
719  std::vector<std::string> argv;
720 
721  // Save args as vector of std::string objects for later processing.
722  for (int i_arg = 0; i_arg < argc; i_arg++)
723  argv.push_back (sys_argv[i_arg]);
724 #endif
725 
726  if (argc == 1)
727  {
728  std::cout << usage_msg << std::endl;
729  return 1;
730  }
731 
732  if (argc == 2 && (argv[1] == "-v" || argv[1] == "-version"
733  || argv[1] == "--version"))
734  {
735  std::cout << version_msg << std::endl;
736  return 0;
737  }
738 
739  std::list<std::string> cfiles, ccfiles, f77files, tmp_objfiles;
740  std::string output_ext = ".oct";
741  std::string objfiles, libfiles, octfile, outputfile;
742  std::string incflags, defs, ldflags, pass_on_options;
743  std::string var_to_print;
744  bool debug = false;
745  bool verbose = false;
746  bool strip = false;
747  bool no_oct_file_strip_on_this_platform = is_true ("false");
748  bool compile_only = false;
749  bool link_stand_alone = false;
750  bool depend = false;
751  bool printonly = false;
752  bool output_file_option = false;
753  bool creating_mex_file = false;
754  bool r2017b_option = false;
755  bool r2018a_option = false;
756  // The default for this may change in the future.
757  bool mx_has_interleaved_complex = false;
758  bool pass_on_followup = false;
759 
760  for (int i = 1; i < argc; i++)
761  {
762  std::string arg = argv[i];
763 
764  std::string file;
765 
766  bool found_unknown_dash_arg = false;
767 
768  if (ends_with (arg, ".c"))
769  {
770  file = arg;
771  cfiles.push_back (file);
772  }
773  else if (ends_with (arg, ".cc") || ends_with (arg, ".cp")
774  || ends_with (arg, ".cpp") || ends_with (arg, ".CPP")
775  || ends_with (arg, ".cxx") || ends_with (arg, ".c++")
776  || ends_with (arg, ".C"))
777  {
778  file = arg;
779  ccfiles.push_back (file);
780  }
781  else if (ends_with (arg, ".f") || ends_with (arg, ".F")
782  || ends_with (arg, "f90") || ends_with (arg, ".F90"))
783  {
784  file = arg;
785  f77files.push_back (file);
786  }
787  else if (ends_with (arg, ".o") || ends_with (arg, ".obj"))
788  {
789  file = arg;
790  objfiles += (' ' + quote_path (arg));
791  }
792  else if (ends_with (arg, ".lib") || ends_with (arg, ".a"))
793  {
794  file = arg;
795  libfiles += (' ' + quote_path (arg));
796  }
797  else if (arg == "-d" || arg == "-debug" || arg == "--debug"
798  || arg == "-v" || arg == "-verbose" || arg == "--verbose")
799  {
800  verbose = true;
801  }
802  else if (arg == "-silent" || arg == "--silent")
803  {
804  // Ignored for now.
805  }
806  else if (arg == "-h" || arg == "-?" || arg == "-help" || arg == "--help")
807  {
808  std::cout << usage_msg << std::endl;
809  std::cout << help_msg << std::endl;
810  return 0;
811  }
812  else if (starts_with (arg, "-I"))
813  {
814  incflags += (' ' + quote_path (arg));
815  }
816  else if (arg == "-idirafter")
817  {
818  if (i < argc-1)
819  {
820  arg = argv[++i];
821  incflags += (" -idirafter " + arg);
822  }
823  else
824  std::cerr << "mkoctfile: include directory name missing"
825  << std::endl;
826  }
827  else if (starts_with (arg, "-D"))
828  {
829  defs += (' ' + arg);
830  }
831  else if (arg == "-largeArrayDims" || arg == "-compatibleArrayDims")
832  {
833  std::cerr << "mkoctfile: warning: -largeArrayDims and -compatibleArrayDims are accepted for compatibility, but ignored" << std::endl;
834  }
835  else if (arg == "-R2017b")
836  {
837  if (r2018a_option)
838  {
839  std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
840  return 1;
841  }
842 
843  r2017b_option = true;
844  }
845  else if (arg == "-R2018a")
846  {
847  if (r2017b_option)
848  {
849  std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
850  return 1;
851  }
852 
853  r2018a_option = true;
854  mx_has_interleaved_complex = true;
855  }
856  else if (starts_with (arg, "-Wl,") || starts_with (arg, "-l")
857  || starts_with (arg, "-L") || starts_with (arg, "-R"))
858  {
859  ldflags += (' ' + quote_path (arg));
860  }
861 #if ! defined (OCTAVE_USE_WINDOWS_API)
862  else if (arg == "-pthread")
863  {
864  ldflags += (' ' + arg);
865  }
866 #endif
867  else if (arg == "-M" || arg == "-depend" || arg == "--depend")
868  {
869  depend = true;
870  }
871  else if (arg == "-o" || arg == "-output" || arg == "--output")
872  {
873  output_file_option = true;
874 
875  if (i < argc-1)
876  {
877  arg = argv[++i];
878  outputfile = arg;
879  }
880  else
881  std::cerr << "mkoctfile: output filename missing" << std::endl;
882  }
883  else if (arg == "-n" || arg == "--dry-run" || arg == "--just-print")
884  {
885  printonly = true;
886  }
887  else if (arg == "-p" || arg == "-print" || arg == "--print")
888  {
889  if (i < argc-1)
890  {
891  ++i;
892 
893  if (! var_to_print.empty ())
894  std::cerr << "mkoctfile: warning: only one '" << arg
895  << "' option will be processed" << std::endl;
896  else
897  var_to_print = argv[i];
898  }
899  else
900  std::cerr << "mkoctfile: --print requires argument" << std::endl;
901  }
902  else if (arg == "-s" || arg == "-strip" || arg == "--strip")
903  {
904  if (no_oct_file_strip_on_this_platform)
905  std::cerr << "mkoctfile: stripping disabled on this platform"
906  << std::endl;
907  else
908  strip = true;
909  }
910  else if (arg == "-c" || arg == "-compile" || arg == "--compile")
911  {
912  compile_only = true;
913  }
914  else if (arg == "-g")
915  {
916  debug = true;
917  }
918  else if (arg == "-link-stand-alone" || arg == "--link-stand-alone")
919  {
920  link_stand_alone = true;
921  }
922  else if (arg == "-mex" || arg == "--mex")
923  {
924  creating_mex_file = true;
925 
926  incflags += " -I.";
927 #if defined (_MSC_VER)
928  ldflags += " -Wl,-export:mexFunction";
929 #endif
930  output_ext = ".mex";
931  }
932  else if (starts_with (arg, "-W"))
933  {
934  pass_on_options += (' ' + arg);
935  }
936  else if (starts_with (arg, "-O"))
937  {
938  pass_on_options += (' ' + arg);
939  }
940  else if (starts_with (arg, "-"))
941  {
942  found_unknown_dash_arg = true;
943 
944  // Pass through any unrecognized options.
945  pass_on_options += (' ' + arg);
946 
947  // Don't pass on the final position which is typically a file.
948  // FIXME: Does it make sense to have that exception for the last
949  // argument?
950  if (i < argc-2)
951  pass_on_followup = true;
952  }
953  else if (pass_on_followup)
954  {
955  // Pass through a followup argument.
956  pass_on_options += (' ' + arg);
957  }
958  else
959  {
960  std::cerr << "mkoctfile: unrecognized argument " << arg << std::endl;
961  return 1;
962  }
963 
964  // reset pass_on_followup if anything but an unknown argument was found
965  if (! found_unknown_dash_arg)
966  pass_on_followup = false;
967 
968  if (! file.empty () && octfile.empty ())
969  octfile = file;
970  }
971 
972  std::map<std::string, std::string> vars
973  = make_vars_map (link_stand_alone, verbose, debug);
974 
975  if (! var_to_print.empty ())
976  {
977  if (vars.find (var_to_print) == vars.end ())
978  {
979  std::cerr << "mkoctfile: unknown variable '" << var_to_print << "'"
980  << std::endl;
981  return 1;
982  }
983 
984  std::cout << vars[var_to_print] << std::endl;
985 
986  return 0;
987  }
988 
989  if (creating_mex_file)
990  {
991  if (vars["ALL_CFLAGS"].find ("-g") != std::string::npos)
992  defs += " -DMEX_DEBUG";
993 
994  if (mx_has_interleaved_complex)
995  {
996  defs += " -DMX_HAS_INTERLEAVED_COMPLEX=1";
997 
998  if (! compile_only)
999  {
1000  // Create tmp C source file that defines an extern symbol
1001  // that can be checked when loading the mex file to
1002  // determine that the file was compiled expecting
1003  // interleaved complex values.
1004 
1005  std::string tmp_file = create_interleaved_complex_file ();
1006 
1007  cfiles.push_back (tmp_file);
1008  }
1009  }
1010  }
1011  else
1012  {
1013  if (r2017b_option)
1014  std::cerr << "mkoctfile: warning: -R2017b option ignored unless creating mex file"
1015  << std::endl;
1016 
1017  if (r2018a_option)
1018  std::cerr << "mkoctfile: warning: -R2018a option ignored unless creating mex file"
1019  << std::endl;
1020  }
1021 
1022  if (compile_only && output_file_option
1023  && (cfiles.size () + ccfiles.size () + f77files.size ()) > 1)
1024  {
1025  std::cerr << "mkoctfile: may not use -c and -o with multiple source files"
1026  << std::endl;
1027  return 1;
1028  }
1029 
1030  std::string output_option;
1031 
1032  if (link_stand_alone)
1033  {
1034  if (! outputfile.empty ())
1035  output_option = "-o " + outputfile;
1036  }
1037  else
1038  {
1039  if (! outputfile.empty ())
1040  {
1041  // FIXME: should probably do a better job of finding the
1042  // filename extension instead of just looking at the filename
1043  // length.
1044 
1045  octfile = outputfile;
1046  std::size_t len = octfile.length ();
1047  std::size_t len_ext = output_ext.length ();
1048  if (len <= len_ext || octfile.substr (len-len_ext) != output_ext)
1049  octfile += output_ext;
1050  }
1051  else
1052  octfile = basename (octfile, true) + output_ext;
1053  }
1054 
1055  if (depend)
1056  {
1057 #if defined (OCTAVE_USE_WINDOWS_API) && ! defined (_UNICODE)
1058  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
1059 #endif
1060 
1061  for (const auto& f : cfiles)
1062  {
1063  std::string dfile = basename (f, true) + ".d", line;
1064 
1065  octave_unlink_wrapper (dfile.c_str ());
1066 
1067  std::string cmd
1068  = (vars["CC"] + ' ' + vars["DEPEND_FLAGS"] + ' '
1069  + vars["CPPFLAGS"] + ' ' + vars["ALL_CFLAGS"] + ' '
1070  + incflags + ' ' + defs + ' ' + quote_path (f));
1071 
1072 #if defined (OCTAVE_USE_WINDOWS_API)
1073  FILE *fd;
1074  try
1075  {
1076  std::wstring wcmd = wchar_conv.from_bytes (cmd);
1077  fd = ::_wpopen (wcmd.c_str (), L"r");
1078  }
1079  catch (const std::range_error& e)
1080  {
1081  fd = ::popen (cmd.c_str (), "r");
1082  }
1083 
1084  std::ofstream fo;
1085  try
1086  {
1087  std::wstring wfile = wchar_conv.from_bytes (dfile);
1088  fo.open (wfile.c_str ());
1089  }
1090  catch (const std::range_error& e)
1091  {
1092  fo.open (dfile.c_str ());
1093  }
1094 #else
1095  FILE *fd = popen (cmd.c_str (), "r");
1096 
1097  std::ofstream fo (dfile.c_str ());
1098 #endif
1099 
1100  std::size_t pos;
1101  while (! feof (fd))
1102  {
1103  line = get_line (fd);
1104  if ((pos = line.rfind (".o:")) != std::string::npos)
1105  {
1106  std::size_t spos = line.rfind ('/', pos);
1107  std::string ofile
1108  = (spos == std::string::npos
1109  ? line.substr (0, pos+2)
1110  : line.substr (spos+1, pos-spos+1));
1111  fo << "pic/" << ofile << ' ' << ofile << ' '
1112  << dfile << line.substr (pos) << std::endl;
1113  }
1114  else
1115  fo << line << std::endl;
1116  }
1117  pclose (fd);
1118  fo.close ();
1119  }
1120 
1121  for (const auto& f : ccfiles)
1122  {
1123  std::string dfile = basename (f, true) + ".d", line;
1124 
1125  octave_unlink_wrapper (dfile.c_str ());
1126 
1127  std::string cmd
1128  = (vars["CXX"] + ' ' + vars["DEPEND_FLAGS"] + ' '
1129  + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1130  + incflags + ' ' + defs + ' ' + quote_path (f));
1131 
1132 #if defined (OCTAVE_USE_WINDOWS_API)
1133  FILE *fd;
1134  try
1135  {
1136  std::wstring wcmd = wchar_conv.from_bytes (cmd);
1137  fd = ::_wpopen (wcmd.c_str (), L"r");
1138  }
1139  catch (const std::range_error& e)
1140  {
1141  fd = ::popen (cmd.c_str (), "r");
1142  }
1143 
1144  std::ofstream fo;
1145  try
1146  {
1147  std::wstring wfile = wchar_conv.from_bytes (dfile);
1148  fo.open (wfile.c_str ());
1149  }
1150  catch (const std::range_error& e)
1151  {
1152  fo.open (dfile.c_str ());
1153  }
1154 #else
1155  FILE *fd = popen (cmd.c_str (), "r");
1156 
1157  std::ofstream fo (dfile.c_str ());
1158 #endif
1159 
1160  std::size_t pos;
1161  while (! feof (fd))
1162  {
1163  line = get_line (fd);
1164  if ((pos = line.rfind (".o:")) != std::string::npos)
1165  {
1166  std::size_t spos = line.rfind ('/', pos);
1167  std::string ofile
1168  = (spos == std::string::npos
1169  ? line.substr (0, pos+2)
1170  : line.substr (spos+1, pos-spos+1));
1171  fo << "pic/" << ofile << ' ' << ofile << ' '
1172  << dfile << line.substr (pos+2) << std::endl;
1173  }
1174  else
1175  fo << line << std::endl;
1176  }
1177  pclose (fd);
1178  fo.close ();
1179  }
1180 
1181  return 0;
1182  }
1183 
1184  for (const auto& f : f77files)
1185  {
1186  if (! vars["F77"].empty ())
1187  {
1188  std::string o;
1189  if (compile_only)
1190  {
1191  if (! outputfile.empty ())
1192  o = outputfile;
1193  else
1194  o = basename (f, true) + ".o";
1195  }
1196  else
1197  {
1198  o = tmp_objfile_name ();
1199 
1200  tmp_objfiles.push_back (o);
1201 
1202  objfiles += (' ' + o);
1203  }
1204 
1205  std::string cmd
1206  = (vars["F77"] + " -c " + vars["FPICFLAG"] + ' '
1207  + vars["ALL_FFLAGS"] + ' ' + incflags + ' ' + defs + ' '
1208  + pass_on_options + ' ' + quote_path (f)
1209  + " -o " + quote_path (o));
1210 
1211  int status = run_command (cmd, verbose, printonly);
1212 
1213  if (status)
1214  return status;
1215  }
1216  else
1217  {
1218  std::cerr << "mkoctfile: no way to compile Fortran file " << f
1219  << std::endl;
1220  return 1;
1221  }
1222  }
1223 
1224  for (const auto& f : cfiles)
1225  {
1226  if (! vars["CC"].empty ())
1227  {
1228  std::string o;
1229  if (compile_only)
1230  {
1231  if (! outputfile.empty ())
1232  o = outputfile;
1233  else
1234  o = basename (f, true) + ".o";
1235  }
1236  else
1237  {
1238  o = tmp_objfile_name ();
1239 
1240  tmp_objfiles.push_back (o);
1241 
1242  objfiles += (' ' + o);
1243  }
1244 
1245  std::string cmd
1246  = (vars["CC"] + " -c " + vars["CPPFLAGS"] + ' '
1247  + vars["CPICFLAG"] + ' ' + vars["ALL_CFLAGS"] + ' '
1248  + pass_on_options + ' ' + incflags + ' ' + defs + ' '
1249  + quote_path (f) + " -o " + quote_path (o));
1250 
1251  int status = run_command (cmd, verbose, printonly);
1252 
1253  if (status)
1254  return status;
1255  }
1256  else
1257  {
1258  std::cerr << "mkoctfile: no way to compile C file " << f
1259  << std::endl;
1260  return 1;
1261  }
1262  }
1263 
1264  for (const auto& f : ccfiles)
1265  {
1266  if (! vars["CXX"].empty ())
1267  {
1268  std::string o;
1269  if (compile_only)
1270  {
1271  if (! outputfile.empty ())
1272  o = outputfile;
1273  else
1274  o = basename (f, true) + ".o";
1275  }
1276  else
1277  {
1278  o = tmp_objfile_name ();
1279 
1280  tmp_objfiles.push_back (o);
1281 
1282  objfiles += (' ' + o);
1283  }
1284 
1285  std::string cmd
1286  = (vars["CXX"] + " -c " + vars["CPPFLAGS"] + ' '
1287  + vars["CXXPICFLAG"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1288  + pass_on_options + ' ' + incflags + ' ' + defs + ' '
1289  + quote_path (f) + " -o " + quote_path (o));
1290 
1291  int status = run_command (cmd, verbose, printonly);
1292 
1293  if (status)
1294  return status;
1295  }
1296  else
1297  {
1298  std::cerr << "mkoctfile: no way to compile C++ file " << f
1299  << std::endl;
1300  return 1;
1301  }
1302  }
1303 
1304  // If we are only compiling, we are done.
1305 
1306  if (compile_only)
1307  return 0;
1308 
1309  if (objfiles.empty ())
1310  {
1311  std::cerr << "mkoctfile: no objects to link" << std::endl;
1312  return 1;
1313  }
1314 
1315  std::string octave_libs;
1316 
1317  if (link_stand_alone)
1318  {
1319  if (! vars["CXXLD"].empty ())
1320  {
1321  octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
1322  + ' ' + vars["OCTAVE_LIBS"];
1323 
1324  std::string cmd
1325  = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' '
1326  + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
1327  + pass_on_options + ' ' + output_option + ' ' + objfiles + ' '
1328  + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' '
1329  + octave_libs + ' '
1330  + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);
1331 
1332  int status = run_command (cmd, verbose, printonly);
1333 
1334  clean_up_tmp_files (tmp_objfiles);
1335 
1336  if (status)
1337  return status;
1338  }
1339  else
1340  {
1341  std::cerr
1342  << "mkoctfile: no way to link stand-alone executable file"
1343  << std::endl;
1344  return 1;
1345  }
1346  }
1347  else
1348  {
1349 #if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
1350  octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
1351  + ' ' + vars["OCTAVE_LIBS"];
1352 #endif
1353 
1354  std::string cmd
1355  = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1356  + pass_on_options + " -o " + octfile + ' ' + objfiles + ' '
1357  + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' '
1358  + vars["LDFLAGS"] + ' ' + octave_libs + ' '
1359  + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);
1360 
1361 #if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
1362  if (! f77files.empty () && ! vars["FLIBS"].empty ())
1363  cmd += ' ' + vars["FLIBS"];
1364 #endif
1365 
1366  int status = run_command (cmd, verbose, printonly);
1367 
1368  clean_up_tmp_files (tmp_objfiles);
1369 
1370  if (status)
1371  return status;
1372  }
1373 
1374  if (strip)
1375  {
1376  std::string cmd = "strip " + octfile;
1377 
1378  int status = run_command (cmd, verbose, printonly);
1379 
1380  if (status)
1381  return status;
1382  }
1383 
1384  return 0;
1385 }
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
std::string prepend_octave_home(const std::string &s)
std::string prepend_octave_exec_home(const std::string &s)
F77_RET_T const F77_DBLE const F77_DBLE * f
int system(const std::string &cmd_str)
Definition: lo-sysdep.cc:60
std::ofstream ofstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:635
#define OCTAVE_VERSION
Definition: mkoctfile.cc:79
bool is_true(const std::string &s)
Definition: mkoctfile.cc:604
bool ends_with(const std::string &s, const std::string &suffix)
Definition: mkoctfile.cc:576
int main(int argc, char **sys_argv)
Definition: mkoctfile.cc:717
bool starts_with(const std::string &s, const std::string &prefix)
Definition: mkoctfile.cc:570
int octave_mkostemps_wrapper(char *tmpl, int suffixlen)
int unlink(const std::string &name)
Definition: file-ops.cc:727
int pclose(FILE *f)
FILE * popen(const char *command, const char *mode)
int octave_unlink_wrapper(const char *nm)
int octave_wexitstatus_wrapper(int status)
bool octave_wifexited_wrapper(int status)
F77_RET_T len
Definition: xerbla.cc:61