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