GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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