GNU Octave 10.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-2025 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_interleaved_complex_file ()
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 to file.
667 FILE *fid = fdopen (fd, "w");
668 fputs ("const int __mx_has_interleaved_complex__ = 1;\n", fid);
669 fclose (fid);
670
671 return retval;
672}
673
674static std::string
675create_mex_soversion_file ()
676{
677 std::string tmpl = get_temp_directory () + "/oct-XXXXXX.c";
678
679 char *ctmpl = new char [tmpl.length () + 1];
680
681 ctmpl = strcpy (ctmpl, tmpl.c_str ());
682
683 // mkostemps will open the file and return a file descriptor. We
684 // won't worry about closing it because we will need the file until we
685 // are done and then the file will be closed when mkoctfile exits.
686 int fd = octave_mkostemps_wrapper (ctmpl, 2);
687
688 // Make C++ string from filled-in template.
689 std::string retval (ctmpl);
690 delete [] ctmpl;
691
692 // Write symbol definition to file.
693 FILE *fid = fdopen (fd, "w");
694 fprintf (fid, "const int __octave_mex_soversion__ = %d;\n",
695 OCTAVE_MEX_SOVERSION);
696 fclose (fid);
697
698 return retval;
699}
700
701static std::string
702tmp_objfile_name ()
703{
704 std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";
705
706 char *ctmpl = new char [tmpl.length () + 1];
707
708 ctmpl = strcpy (ctmpl, tmpl.c_str ());
709
710 // mkostemps will open the file and return a file descriptor. We
711 // won't worry about closing it because we will need the file until we
712 // are done and then the file will be closed when mkoctfile exits.
713 octave_mkostemps_wrapper (ctmpl, 2);
714
715 std::string retval (ctmpl); // make C++ string from filled-in template
716 delete [] ctmpl;
717
718 return retval;
719}
720
721static void
722clean_up_tmp_files (const std::list<std::string>& tmp_files)
723{
724 for (const auto& file : tmp_files)
725 octave_unlink_wrapper (file.c_str ());
726}
727
728#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)
729extern "C"
730int
731wmain (int argc, wchar_t **sys_argv)
732{
733 std::vector<std::string> argv;
734
735 // Convert wide character strings to multibyte UTF-8 strings and save
736 // them in a vector of std::string objects for later processing.
737
738 std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
739 for (int i_arg = 0; i_arg < argc; i_arg++)
740 argv.push_back (wchar_conv.to_bytes (sys_argv[i_arg]));
741#else
742int
743main (int argc, char **sys_argv)
744{
745 std::vector<std::string> argv;
746
747 // Save args as vector of std::string objects for later processing.
748 for (int i_arg = 0; i_arg < argc; i_arg++)
749 argv.push_back (sys_argv[i_arg]);
750#endif
751
752 if (argc == 1)
753 {
754 std::cout << usage_msg << std::endl;
755 return 1;
756 }
757
758 if (argc == 2 && (argv[1] == "-v" || argv[1] == "-version"
759 || argv[1] == "--version"))
760 {
761 std::cout << version_msg << std::endl;
762 return 0;
763 }
764
765 std::list<std::string> cfiles, ccfiles, f77files, tmp_objfiles;
766 std::string output_ext = ".oct";
767 std::string objfiles, libfiles, octfile, outputfile;
768 std::string incflags, defs, ldflags, pass_on_options;
769 std::string var_to_print;
770 bool debug = false;
771 bool verbose = false;
772 bool strip = false;
773 bool no_oct_file_strip_on_this_platform = is_true ("%NO_OCT_FILE_STRIP%");
774 bool compile_only = false;
775 bool link_stand_alone = false;
776 bool depend = false;
777 bool printonly = false;
778 bool output_file_option = false;
779 bool creating_mex_file = false;
780 bool r2017b_option = false;
781 bool r2018a_option = false;
782 // The default for this may change in the future.
783 bool mx_has_interleaved_complex = false;
784 bool pass_on_followup = false;
785
786 for (int i = 1; i < argc; i++)
787 {
788 std::string arg = argv[i];
789
790 std::string file;
791
792 bool found_unknown_dash_arg = false;
793
794 if (ends_with (arg, ".c"))
795 {
796 file = arg;
797 cfiles.push_back (file);
798 }
799 else if (ends_with (arg, ".cc") || ends_with (arg, ".cp")
800 || ends_with (arg, ".cpp") || ends_with (arg, ".CPP")
801 || ends_with (arg, ".cxx") || ends_with (arg, ".c++")
802 || ends_with (arg, ".C"))
803 {
804 file = arg;
805 ccfiles.push_back (file);
806 }
807 else if (ends_with (arg, ".f") || ends_with (arg, ".F")
808 || ends_with (arg, "f90") || ends_with (arg, ".F90"))
809 {
810 file = arg;
811 f77files.push_back (file);
812 }
813 else if (ends_with (arg, ".o") || ends_with (arg, ".obj"))
814 {
815 file = arg;
816 objfiles += (' ' + quote_path (arg));
817 }
818 else if (ends_with (arg, ".lib") || ends_with (arg, ".a"))
819 {
820 file = arg;
821 libfiles += (' ' + quote_path (arg));
822 }
823 else if (arg == "-d" || arg == "-debug" || arg == "--debug"
824 || arg == "-v" || arg == "-verbose" || arg == "--verbose")
825 {
826 verbose = true;
827 }
828 else if (arg == "-silent" || arg == "--silent"
829 || arg == "-quiet" || arg == "--quiet")
830 {
831 // Ignored for now.
832 }
833 else if (arg == "-h" || arg == "-?" || arg == "-help" || arg == "--help")
834 {
835 std::cout << usage_msg << std::endl;
836 std::cout << help_msg << std::endl;
837 return 0;
838 }
839 else if (starts_with (arg, "-I"))
840 {
841 incflags += (' ' + quote_path (arg));
842 }
843 else if (arg == "-idirafter")
844 {
845 if (i < argc-1)
846 {
847 arg = argv[++i];
848 incflags += (" -idirafter " + arg);
849 }
850 else
851 std::cerr << "mkoctfile: include directory name missing"
852 << std::endl;
853 }
854 else if (starts_with (arg, "-D"))
855 {
856 defs += (' ' + arg);
857 }
858 else if (arg == "-largeArrayDims" || arg == "-compatibleArrayDims")
859 {
860 std::cerr << "mkoctfile: warning: -largeArrayDims and -compatibleArrayDims are accepted for compatibility, but ignored" << std::endl;
861 }
862 else if (arg == "-R2017b")
863 {
864 if (r2018a_option)
865 {
866 std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
867 return 1;
868 }
869
870 r2017b_option = true;
871 }
872 else if (arg == "-R2018a")
873 {
874 if (r2017b_option)
875 {
876 std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
877 return 1;
878 }
879
880 r2018a_option = true;
881 mx_has_interleaved_complex = true;
882 }
883 else if (starts_with (arg, "-Wl,") || starts_with (arg, "-l")
884 || starts_with (arg, "-L") || starts_with (arg, "-R"))
885 {
886 ldflags += (' ' + quote_path (arg));
887 }
888#if ! defined (OCTAVE_USE_WINDOWS_API)
889 else if (arg == "-pthread")
890 {
891 ldflags += (' ' + arg);
892 }
893#endif
894 else if (arg == "-M" || arg == "-depend" || arg == "--depend")
895 {
896 depend = true;
897 }
898 else if (arg == "-o" || arg == "-output" || arg == "--output")
899 {
900 output_file_option = true;
901
902 if (i < argc-1)
903 {
904 arg = argv[++i];
905 outputfile = arg;
906 }
907 else
908 std::cerr << "mkoctfile: output filename missing" << std::endl;
909 }
910 else if (arg == "-n" || arg == "--dry-run" || arg == "--just-print")
911 {
912 printonly = true;
913 }
914 else if (arg == "-p" || arg == "-print" || arg == "--print")
915 {
916 if (i < argc-1)
917 {
918 ++i;
919
920 if (! var_to_print.empty ())
921 std::cerr << "mkoctfile: warning: only one '" << arg
922 << "' option will be processed" << std::endl;
923 else
924 var_to_print = argv[i];
925 }
926 else
927 std::cerr << "mkoctfile: --print requires argument" << std::endl;
928 }
929 else if (arg == "-s" || arg == "-strip" || arg == "--strip")
930 {
931 if (no_oct_file_strip_on_this_platform)
932 std::cerr << "mkoctfile: stripping disabled on this platform"
933 << std::endl;
934 else
935 strip = true;
936 }
937 else if (arg == "-c" || arg == "-compile" || arg == "--compile")
938 {
939 compile_only = true;
940 }
941 else if (arg == "-g")
942 {
943 debug = true;
944 }
945 else if (arg == "-link-stand-alone" || arg == "--link-stand-alone")
946 {
947 link_stand_alone = true;
948 }
949 else if (arg == "-mex" || arg == "--mex")
950 {
951 creating_mex_file = true;
952
953 incflags += " -I.";
954#if defined (_MSC_VER)
955 ldflags += " -Wl,-export:mexFunction";
956#endif
957 output_ext = ".mex";
958 }
959 else if (starts_with (arg, "-W"))
960 {
961 pass_on_options += (' ' + arg);
962 }
963 else if (starts_with (arg, "-O"))
964 {
965 pass_on_options += (' ' + arg);
966 }
967 else if (starts_with (arg, "-"))
968 {
969 found_unknown_dash_arg = true;
970
971 // Pass through any unrecognized options.
972 pass_on_options += (' ' + arg);
973
974 // Don't pass on the final position which is typically a file.
975 // FIXME: Does it make sense to have that exception for the last
976 // argument?
977 if (i < argc-2)
978 pass_on_followup = true;
979 }
980 else if (pass_on_followup)
981 {
982 // Pass through a followup argument.
983 pass_on_options += (' ' + arg);
984 }
985 else
986 {
987 std::cerr << "mkoctfile: unrecognized argument " << arg << std::endl;
988 return 1;
989 }
990
991 // reset pass_on_followup if anything but an unknown argument was found
992 if (! found_unknown_dash_arg)
993 pass_on_followup = false;
994
995 if (! file.empty () && octfile.empty ())
996 octfile = file;
997 }
998
999 std::map<std::string, std::string> vars
1000 = make_vars_map (link_stand_alone, verbose, debug);
1001
1002 if (! var_to_print.empty ())
1003 {
1004 if (vars.find (var_to_print) == vars.end ())
1005 {
1006 std::cerr << "mkoctfile: unknown variable '" << var_to_print << "'"
1007 << std::endl;
1008 return 1;
1009 }
1010
1011 std::cout << vars[var_to_print] << std::endl;
1012
1013 return 0;
1014 }
1015
1016 if (creating_mex_file)
1017 {
1018 if (vars["ALL_CFLAGS"].find ("-g") != std::string::npos)
1019 defs += " -DMEX_DEBUG";
1020
1021 // Create tmp C source file that defines an extern symbol that can
1022 // be checked when loading the mex file to make sure the SOVERSION
1023 // of liboctmex matches between the .mex file and the Octave version
1024 // attempting to load it.
1025 std::string tmp_file = create_mex_soversion_file ();
1026
1027 cfiles.push_back (tmp_file);
1028
1029 if (mx_has_interleaved_complex)
1030 {
1031 defs += " -DMX_HAS_INTERLEAVED_COMPLEX=1";
1032
1033 if (! compile_only)
1034 {
1035 // Create tmp C source file that defines an extern symbol
1036 // that can be checked when loading the mex file to
1037 // determine that the file was compiled expecting
1038 // interleaved complex values.
1039
1040 tmp_file = create_interleaved_complex_file ();
1041
1042 cfiles.push_back (tmp_file);
1043 }
1044 }
1045 }
1046 else
1047 {
1048 if (r2017b_option)
1049 std::cerr << "mkoctfile: warning: -R2017b option ignored unless creating mex file"
1050 << std::endl;
1051
1052 if (r2018a_option)
1053 std::cerr << "mkoctfile: warning: -R2018a option ignored unless creating mex file"
1054 << std::endl;
1055 }
1056
1057 if (compile_only && output_file_option
1058 && (cfiles.size () + ccfiles.size () + f77files.size ()) > 1)
1059 {
1060 std::cerr << "mkoctfile: may not use -c and -o with multiple source files"
1061 << std::endl;
1062 return 1;
1063 }
1064
1065 std::string output_option;
1066
1067 if (link_stand_alone)
1068 {
1069 if (! outputfile.empty ())
1070 output_option = "-o " + outputfile;
1071 }
1072 else
1073 {
1074 if (! outputfile.empty ())
1075 {
1076 // FIXME: should probably do a better job of finding the
1077 // filename extension instead of just looking at the filename
1078 // length.
1079
1080 octfile = outputfile;
1081 std::size_t len = octfile.length ();
1082 std::size_t len_ext = output_ext.length ();
1083 if (len <= len_ext || octfile.substr (len-len_ext) != output_ext)
1084 octfile += output_ext;
1085 }
1086 else
1087 octfile = basename (octfile, true) + output_ext;
1088 }
1089
1090 if (depend)
1091 {
1092#if defined (OCTAVE_USE_WINDOWS_API) && ! defined (_UNICODE)
1093 std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
1094#endif
1095
1096 for (const auto& f : cfiles)
1097 {
1098 std::string dfile = basename (f, true) + ".d", line;
1099
1100 octave_unlink_wrapper (dfile.c_str ());
1101
1102 std::string cmd
1103 = (vars["CC"] + ' ' + vars["DEPEND_FLAGS"] + ' '
1104 + vars["CPPFLAGS"] + ' ' + vars["ALL_CFLAGS"] + ' '
1105 + incflags + ' ' + defs + ' ' + quote_path (f));
1106
1107#if defined (OCTAVE_USE_WINDOWS_API)
1108 FILE *fd;
1109 try
1110 {
1111 std::wstring wcmd = wchar_conv.from_bytes (cmd);
1112 fd = ::_wpopen (wcmd.c_str (), L"r");
1113 }
1114 catch (const std::range_error& e)
1115 {
1116 fd = ::popen (cmd.c_str (), "r");
1117 }
1118
1119 std::ofstream fo;
1120 try
1121 {
1122 std::wstring wfile = wchar_conv.from_bytes (dfile);
1123 fo.open (wfile.c_str ());
1124 }
1125 catch (const std::range_error& e)
1126 {
1127 fo.open (dfile.c_str ());
1128 }
1129#else
1130 FILE *fd = popen (cmd.c_str (), "r");
1131
1132 std::ofstream fo (dfile.c_str ());
1133#endif
1134
1135 std::size_t pos;
1136 while (! feof (fd))
1137 {
1138 line = get_line (fd);
1139 if ((pos = line.rfind (".o:")) != std::string::npos)
1140 {
1141 std::size_t spos = line.rfind ('/', pos);
1142 std::string ofile
1143 = (spos == std::string::npos
1144 ? line.substr (0, pos+2)
1145 : line.substr (spos+1, pos-spos+1));
1146 fo << "pic/" << ofile << ' ' << ofile << ' '
1147 << dfile << line.substr (pos) << std::endl;
1148 }
1149 else
1150 fo << line << std::endl;
1151 }
1152 pclose (fd);
1153 fo.close ();
1154 }
1155
1156 for (const auto& f : ccfiles)
1157 {
1158 std::string dfile = basename (f, true) + ".d", line;
1159
1160 octave_unlink_wrapper (dfile.c_str ());
1161
1162 std::string cmd
1163 = (vars["CXX"] + ' ' + vars["DEPEND_FLAGS"] + ' '
1164 + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1165 + incflags + ' ' + defs + ' ' + quote_path (f));
1166
1167#if defined (OCTAVE_USE_WINDOWS_API)
1168 FILE *fd;
1169 try
1170 {
1171 std::wstring wcmd = wchar_conv.from_bytes (cmd);
1172 fd = ::_wpopen (wcmd.c_str (), L"r");
1173 }
1174 catch (const std::range_error& e)
1175 {
1176 fd = ::popen (cmd.c_str (), "r");
1177 }
1178
1179 std::ofstream fo;
1180 try
1181 {
1182 std::wstring wfile = wchar_conv.from_bytes (dfile);
1183 fo.open (wfile.c_str ());
1184 }
1185 catch (const std::range_error& e)
1186 {
1187 fo.open (dfile.c_str ());
1188 }
1189#else
1190 FILE *fd = popen (cmd.c_str (), "r");
1191
1192 std::ofstream fo (dfile.c_str ());
1193#endif
1194
1195 std::size_t pos;
1196 while (! feof (fd))
1197 {
1198 line = get_line (fd);
1199 if ((pos = line.rfind (".o:")) != std::string::npos)
1200 {
1201 std::size_t spos = line.rfind ('/', pos);
1202 std::string ofile
1203 = (spos == std::string::npos
1204 ? line.substr (0, pos+2)
1205 : line.substr (spos+1, pos-spos+1));
1206 fo << "pic/" << ofile << ' ' << ofile << ' '
1207 << dfile << line.substr (pos+2) << std::endl;
1208 }
1209 else
1210 fo << line << std::endl;
1211 }
1212 pclose (fd);
1213 fo.close ();
1214 }
1215
1216 return 0;
1217 }
1218
1219 for (const auto& f : f77files)
1220 {
1221 if (! vars["F77"].empty ())
1222 {
1223 std::string o;
1224 if (compile_only)
1225 {
1226 if (! outputfile.empty ())
1227 o = outputfile;
1228 else
1229 o = basename (f, true) + ".o";
1230 }
1231 else
1232 {
1233 o = tmp_objfile_name ();
1234
1235 tmp_objfiles.push_back (o);
1236
1237 objfiles += (' ' + o);
1238 }
1239
1240 std::string cmd
1241 = (vars["F77"] + " -c " + vars["FPICFLAG"] + ' '
1242 + vars["ALL_FFLAGS"] + ' ' + incflags + ' ' + defs + ' '
1243 + pass_on_options + ' ' + quote_path (f)
1244 + " -o " + quote_path (o));
1245
1246 int status = run_command (cmd, verbose, printonly);
1247
1248 if (status)
1249 return status;
1250 }
1251 else
1252 {
1253 std::cerr << "mkoctfile: no way to compile Fortran file " << f
1254 << std::endl;
1255 return 1;
1256 }
1257 }
1258
1259 for (const auto& f : cfiles)
1260 {
1261 if (! vars["CC"].empty ())
1262 {
1263 std::string o;
1264 if (compile_only)
1265 {
1266 if (! outputfile.empty ())
1267 o = outputfile;
1268 else
1269 o = basename (f, true) + ".o";
1270 }
1271 else
1272 {
1273 o = tmp_objfile_name ();
1274
1275 tmp_objfiles.push_back (o);
1276
1277 objfiles += (' ' + o);
1278 }
1279
1280 std::string cmd
1281 = (vars["CC"] + " -c " + vars["CPPFLAGS"] + ' '
1282 + vars["CPICFLAG"] + ' ' + vars["ALL_CFLAGS"] + ' '
1283 + pass_on_options + ' ' + incflags + ' ' + defs + ' '
1284 + quote_path (f) + " -o " + quote_path (o));
1285
1286 int status = run_command (cmd, verbose, printonly);
1287
1288 if (status)
1289 return status;
1290 }
1291 else
1292 {
1293 std::cerr << "mkoctfile: no way to compile C file " << f
1294 << std::endl;
1295 return 1;
1296 }
1297 }
1298
1299 for (const auto& f : ccfiles)
1300 {
1301 if (! vars["CXX"].empty ())
1302 {
1303 std::string o;
1304 if (compile_only)
1305 {
1306 if (! outputfile.empty ())
1307 o = outputfile;
1308 else
1309 o = basename (f, true) + ".o";
1310 }
1311 else
1312 {
1313 o = tmp_objfile_name ();
1314
1315 tmp_objfiles.push_back (o);
1316
1317 objfiles += (' ' + o);
1318 }
1319
1320 std::string cmd
1321 = (vars["CXX"] + " -c " + vars["CPPFLAGS"] + ' '
1322 + vars["CXXPICFLAG"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1323 + pass_on_options + ' ' + incflags + ' ' + defs + ' '
1324 + quote_path (f) + " -o " + quote_path (o));
1325
1326 int status = run_command (cmd, verbose, printonly);
1327
1328 if (status)
1329 return status;
1330 }
1331 else
1332 {
1333 std::cerr << "mkoctfile: no way to compile C++ file " << f
1334 << std::endl;
1335 return 1;
1336 }
1337 }
1338
1339 // If we are only compiling, we are done.
1340
1341 if (compile_only)
1342 return 0;
1343
1344 if (objfiles.empty ())
1345 {
1346 std::cerr << "mkoctfile: no objects to link" << std::endl;
1347 return 1;
1348 }
1349
1350 std::string octave_libs;
1351
1352 if (link_stand_alone)
1353 {
1354 if (! vars["CXXLD"].empty ())
1355 {
1356 octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
1357 + ' ' + vars["OCTAVE_LIBS"];
1358
1359 std::string cmd
1360 = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' '
1361 + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
1362 + pass_on_options + ' ' + output_option + ' ' + objfiles + ' '
1363 + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' '
1364 + octave_libs + ' '
1365 + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);
1366
1367 int status = run_command (cmd, verbose, printonly);
1368
1369 clean_up_tmp_files (tmp_objfiles);
1370
1371 if (status)
1372 return status;
1373 }
1374 else
1375 {
1376 std::cerr
1377 << "mkoctfile: no way to link stand-alone executable file"
1378 << std::endl;
1379 return 1;
1380 }
1381 }
1382 else
1383 {
1384 if (creating_mex_file)
1385 octave_libs = (" -L" + quote_path (vars["OCTLIBDIR"]) + ' '
1386 + vars["LIBOCTMEX"]);
1387
1388 std::string cmd
1389 = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
1390 + pass_on_options + " -o " + octfile + ' ' + objfiles + ' '
1391 + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' '
1392 + vars["LDFLAGS"] + ' ' + octave_libs + ' '
1393 + vars["OCT_LINK_OPTS"]);
1394
1395 if (! creating_mex_file)
1396 cmd += ' ' + vars["OCT_LINK_DEPS"];
1397
1398#if defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS) || defined (OCTAVE_LINK_ALL_DEPS)
1399 if (! f77files.empty () && ! vars["FLIBS"].empty ())
1400 cmd += ' ' + vars["FLIBS"];
1401#endif
1402
1403 int status = run_command (cmd, verbose, printonly);
1404
1405 clean_up_tmp_files (tmp_objfiles);
1406
1407 if (status)
1408 return status;
1409 }
1410
1411 if (strip)
1412 {
1413 std::string cmd = "strip " + octfile;
1414
1415 int status = run_command (cmd, verbose, printonly);
1416
1417 if (status)
1418 return status;
1419 }
1420
1421 return 0;
1422}
program main
std::string prepend_octave_home(const std::string &s)
Definition defaults.cc:130
std::string prepend_octave_exec_home(const std::string &s)
Definition defaults.cc:136
int unlink(const std::string &name)
Definition file-ops.cc:727
F77_RET_T const F77_DBLE const F77_DBLE * f
int system(const std::string &cmd_str)
Definition lo-sysdep.cc:60
#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 pclose(FILE *f)
Definition sysdep.cc:643
FILE * popen(const char *command, const char *mode)
Definition sysdep.cc:626
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