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