1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #if !defined(__MINGW32__)
25 # include <sys/wait.h>
26 #endif
27
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <assert.h>
32
33 #ifdef __EMX__
34 # define SHELL_CMD "sh"
35 # define GEN_EXPORTS "emxexp"
36 # define DEF2IMPLIB_CMD "emximp"
37 # define SHARE_SW "-Zdll -Zmtd"
38 # define USE_OMF 1
39 # define TRUNCATE_DLL_NAME
40 # define DYNAMIC_LIB_EXT "dll"
41 # define EXE_EX ".exe"
42 /* OMF is the native format under OS/2 */
43 # if USE_OMF
44
45 # define STATIC_LIB_EXT "lib"
46 # define OBJECT_EXT "obj"
47 # define LIBRARIAN "emxomfar"
48 # define LIBRARIAN_OPTS "cr"
49 # else
50 /* but the alternative, a.out, can fork() which is sometimes necessary */
51 # define STATIC_LIB_EXT "a"
52 # define OBJECT_EXT "o"
53 # define LIBRARIAN "ar"
54 # define LIBRARIAN_OPTS "cr"
55 # endif
56 #endif
57
58 #if defined(__APPLE__)
59 # define SHELL_CMD "/bin/sh"
60 # define DYNAMIC_LIB_EXT "dylib"
61 # define MODULE_LIB_EXT "bundle"
62 # define STATIC_LIB_EXT "a"
63 # define OBJECT_EXT "o"
64 # define LIBRARIAN "ar"
65 # define LIBRARIAN_OPTS "cr"
66 /* man libtool(1) documents ranlib option of -c. */
67 # define RANLIB "ranlib"
68 # define PIC_FLAG "-fPIC -fno-common"
69 # define SHARED_OPTS "-dynamiclib"
70 # define MODULE_OPTS "-bundle -dynamic"
71 # define DYNAMIC_LINK_OPTS "-flat_namespace"
72 # define DYNAMIC_LINK_UNDEFINED "-undefined suppress"
73 # define dynamic_link_version_func darwin_dynamic_link_function
74 # define DYNAMIC_INSTALL_NAME "-install_name"
75 # define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
76 # define HAS_REALPATH
77 /*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
78 # define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
79 # define LD_LIBRARY_PATH_LOCAL "DYLD_FALLBACK_LIBRARY_PATH"
80 #endif
81
82 #if defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || (defined(__sun) && defined(__GNUC__))
83 # define SHELL_CMD "/bin/sh"
84 # define DYNAMIC_LIB_EXT "so"
85 # define MODULE_LIB_EXT "so"
86 # define STATIC_LIB_EXT "a"
87 # define OBJECT_EXT "o"
88 # define LIBRARIAN "ar"
89 # define LIBRARIAN_OPTS "cr"
90 # define RANLIB "ranlib"
91 # define PIC_FLAG "-fPIC"
92 # define RPATH "-rpath"
93 # define SHARED_OPTS "-shared"
94 # define MODULE_OPTS "-shared"
95 # define LINKER_FLAG_PREFIX "-Wl,"
96 #if !defined(__sun)
97 # define DYNAMIC_LINK_OPTS LINKER_FLAG_PREFIX "-export-dynamic"
98 #else
99 # define DYNAMIC_LINK_OPTS ""
100 #endif
101 # define ADD_MINUS_L
102 # define LD_RUN_PATH "LD_RUN_PATH"
103 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
104 # define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
105 #endif
106
107 #if defined(__sun) && !defined(__GNUC__)
108 # define SHELL_CMD "/bin/sh"
109 # define DYNAMIC_LIB_EXT "so"
110 # define MODULE_LIB_EXT "so"
111 # define STATIC_LIB_EXT "a"
112 # define OBJECT_EXT "o"
113 # define LIBRARIAN "ar"
114 # define LIBRARIAN_OPTS "cr"
115 # define RANLIB "ranlib"
116 # define PIC_FLAG "-fPIC"
117 # define RPATH "-R"
118 # define SHARED_OPTS "-G"
119 # define MODULE_OPTS "-G"
120 # define DYNAMIC_LINK_OPTS ""
121 # define LINKER_FLAG_NO_EQUALS
122 # define ADD_MINUS_L
123 # define HAS_REALPATH
124 # define LD_RUN_PATH "LD_RUN_PATH"
125 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
126 # define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
127 #endif
128
129 #if defined(_OSD_POSIX)
130 # define SHELL_CMD "/usr/bin/sh"
131 # define DYNAMIC_LIB_EXT "so"
132 # define MODULE_LIB_EXT "so"
133 # define STATIC_LIB_EXT "a"
134 # define OBJECT_EXT "o"
135 # define LIBRARIAN "ar"
136 # define LIBRARIAN_OPTS "cr"
137 # define SHARED_OPTS "-G"
138 # define MODULE_OPTS "-G"
139 # define LINKER_FLAG_PREFIX "-Wl,"
140 # define NEED_SNPRINTF
141 #endif
142
143 #if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
144 # define SHELL_CMD "/usr/bin/sh"
145 # define DYNAMIC_LIB_EXT "so"
146 # define MODULE_LIB_EXT "so"
147 # define STATIC_LIB_EXT "a"
148 # define OBJECT_EXT "o"
149 # define LIBRARIAN "ar"
150 # define LIBRARIAN_OPTS "cr"
151 # define RPATH "-Brpath"
152 # define SHARED_OPTS "-G"
153 # define MODULE_OPTS "-G"
154 # define LINKER_FLAG_PREFIX "-Wl,"
155 # define DYNAMIC_LINK_OPTS LINKER_FLAG_PREFIX "-Blargedynsym"
156
157 # define NEED_SNPRINTF
158 # define LD_RUN_PATH "LD_RUN_PATH"
159 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
160 # define LD_LIBRARY_PATH_LOCAL LD_LIBRARY_PATH
161 #endif
162
163 #if defined(__MINGW32__)
164 # define SHELL_CMD "sh"
165 # define DYNAMIC_LIB_EXT "dll"
166 # define MODULE_LIB_EXT "dll"
167 # define STATIC_LIB_EXT "a"
168 # define OBJECT_EXT "o"
169 # define LIBRARIAN "ar"
170 # define LIBRARIAN_OPTS "cr"
171 # define RANLIB "ranlib"
172 # define LINKER_FLAG_PREFIX "-Wl,"
173 # define SHARED_OPTS "-shared"
174 # define MODULE_OPTS "-shared"
175 # define MKDIR_NO_UMASK
176 # define EXE_EXT ".exe"
177 #endif
178
179 #ifndef CC
180 #define CC "clang"
181 #endif
182
183 #ifndef CXX
184 #define CXX "g++"
185 #endif
186
187 #ifndef LINK_C
188 #define LINK_C "clang"
189 #endif
190
191 #ifndef LINK_CXX
192 #define LINK_CXX "g++"
193 #endif
194
195 #ifndef LIBDIR
196 #define LIBDIR "/usr/local/lib"
197 #endif
198
199 #define OBJDIR ".libs"
200
201 #ifndef SHELL_CMD
202 #error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
203 #endif
204
205 #ifdef NEED_SNPRINTF
206 #include <stdarg.h>
207 #endif
208
209 #ifdef __EMX__
210 #include <process.h>
211 #endif
212
213 #ifndef PATH_MAX
214 #define PATH_MAX 1024
215 #endif
216
217
218 /* We want to say we are libtool 1.4 for shlibtool compatibility. */
219 #define VERSION "1.4"
220
221 #define DEBUG(fmt, ...) if(cmd->options.debug) printf(fmt, ## __VA_ARGS__)
222 #define NOTICE(fmt, ...) if(!cmd->options.silent) printf(fmt, ## __VA_ARGS__)
223 #define ERROR(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
224
225 enum tool_mode {
226 MODE_UNKNOWN,
227 MODE_COMPILE,
228 MODE_LINK,
229 MODE_EXECUTE,
230 MODE_INSTALL,
231 };
232
233 enum output_type {
234 OUT_GENERAL,
235 OUT_OBJECT,
236 OUT_PROGRAM,
237 OUT_LIB,
238 OUT_STATIC_LIB_ONLY,
239 OUT_DYNAMIC_LIB_ONLY,
240 OUT_MODULE,
241 };
242
243 enum pic_mode {
244 PIC_UNKNOWN,
245 PIC_PREFER,
246 PIC_AVOID,
247 };
248
249 enum shared_mode {
250 SHARE_UNSET,
251 SHARE_STATIC,
252 SHARE_SHARED,
253 };
254
255 enum lib_type {
256 TYPE_UKNOWN,
257 TYPE_STATIC_LIB,
258 TYPE_DYNAMIC_LIB,
259 TYPE_MODULE_LIB,
260 TYPE_OBJECT,
261 };
262
263 typedef struct {
264 char const **vals;
265 int num;
266 } count_chars;
267
268 typedef struct {
269 char const *normal;
270 char const *install;
271 } library_name;
272
273 typedef struct {
274 count_chars *normal;
275 count_chars *install;
276 count_chars *dependencies;
277 } library_opts;
278
279 typedef struct {
280 int silent;
281 int debug;
282 enum shared_mode shared;
283 int export_all;
284 int dry_run;
285 enum pic_mode pic_mode;
286 int export_dynamic;
287 int no_install;
288 } options_t;
289
290 typedef struct {
291 enum tool_mode mode;
292 enum output_type output;
293 options_t options;
294
295 char const *output_name;
296 char const *fake_output_name;
297 char const *basename;
298
299 char const *install_path;
300 char const *compiler;
301 char const *program;
302 count_chars *program_opts;
303
304 count_chars *arglist;
305 count_chars *tmp_dirs;
306 count_chars *obj_files;
307 count_chars *dep_rpaths;
308 count_chars *rpaths;
309
310 library_name static_name;
311 library_name shared_name;
312 library_name module_name;
313
314 library_opts static_opts;
315 library_opts shared_opts;
316
317 char const *version_info;
318 char const *undefined_flag;
319 } command_t;
320
321 #ifdef RPATH
322 static void add_rpath(count_chars *cc, char const *path);
323 #endif
324
usage(int code)325 static void usage(int code)
326 {
327 printf("Usage: jlibtool [OPTIONS...] COMMANDS...\n");
328 printf("jlibtool is a replacement for GNU libtool with similar functionality.\n\n");
329
330 printf(" --config show all configuration variables\n");
331 printf(" --debug enable verbose shell tracing\n");
332 printf(" --dry-run display commands without modifying any files\n");
333 printf(" --help display this help message and exit\n");
334 printf(" --mode=MODE use operational mode MODE (you *must* set mode)\n");
335
336 printf(" --silent don't print informational messages\n");
337 printf(" --tag=TAG Ignored for libtool compatibility\n");
338 printf(" --version print version information\n");
339
340
341 printf(" --shared Build shared libraries when using --mode=link\n");
342 printf(" --export-all Try to export 'def' file on some platforms\n");
343
344 printf("\nMODE must be one of the following:\n\n");
345 printf(" compile compile a source file into a jlibtool object\n");
346 printf(" execute automatically set library path, then run a program\n");
347 printf(" install install libraries or executables\n");
348 printf(" link create a library or an executable\n");
349
350 printf("\nMODE-ARGS can be the following:\n\n");
351 printf(" -export-dynamic accepted and ignored\n");
352 printf(" -module create a module when linking\n");
353 printf(" -shared create a shared library when linking\n");
354 printf(" -prefer-pic prefer position-independent-code when compiling\n");
355 printf(" -prefer-non-pic prefer non position-independent-code when compiling\n");
356 printf(" -static create a static library when linking\n");
357 printf(" -no-install link libraries locally\n");
358 printf(" -rpath arg Set install path for shared libraries\n");
359 printf(" -l arg pass '-l arg' to the link stage\n");
360 printf(" -L arg pass '-L arg' to the link stage\n");
361 printf(" -R dir add 'dir' to runtime library search path.\n");
362 printf(" -Zexe accepted and ignored\n");
363 printf(" -avoid-version accepted and ignored\n");
364
365 exit(code);
366 }
367
368 #if defined(NEED_SNPRINTF)
369 /* Write at most n characters to the buffer in str, return the
370 * number of chars written or -1 if the buffer would have been
371 * overflowed.
372 *
373 * This is portable to any POSIX-compliant system has /dev/null
374 */
375 static FILE *f = NULL;
vsnprintf(char * str,size_t n,char const * fmt,va_list ap)376 static int vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
377 {
378 int res;
379
380 if (!f) {
381 f = fopen("/dev/null","w");
382 }
383
384 if (!f) {
385 return -1;
386 }
387
388 setvbuf(f, str, _IOFBF, n);
389
390 res = vfprintf(f, fmt, ap);
391
392 if ((res > 0) && (res < n)) {
393 res = vsprintf( str, fmt, ap );
394 }
395 return res;
396 }
397
snprintf(char * str,size_t n,char const * fmt,...)398 static int snprintf(char *str, size_t n, char const *fmt, ...)
399 {
400 va_list ap;
401 int res;
402
403 va_start(ap, fmt);
404 res = vsnprintf(str, n, fmt, ap);
405 va_end(ap);
406 return res;
407 }
408 #endif
409
lt_malloc(size_t size)410 static void *lt_malloc(size_t size)
411 {
412 void *out;
413
414 out = malloc(size);
415 if (!out) {
416 ERROR("Failed allocating %zu bytes, OOM\n", size);
417 exit(1);
418 }
419
420 return out;
421 }
422
lt_const_free(const void * ptr)423 static void lt_const_free(const void *ptr)
424 {
425 void *tmp;
426
427 memcpy(&tmp, &ptr, sizeof(tmp));
428 free(tmp);
429 }
430
init_count_chars(count_chars * cc)431 static void init_count_chars(count_chars *cc)
432 {
433 cc->vals = (char const**) lt_malloc(PATH_MAX*sizeof(char*));
434 cc->num = 0;
435 }
436
alloc_countchars(void)437 static count_chars *alloc_countchars(void)
438 {
439 count_chars *out;
440 out = lt_malloc(sizeof(count_chars));
441 if (!out) {
442 exit(1);
443 }
444 init_count_chars(out);
445
446 return out;
447 }
448
clear_count_chars(count_chars * cc)449 static void clear_count_chars(count_chars *cc)
450 {
451 int i;
452 for (i = 0; i < cc->num; i++) {
453 cc->vals[i] = NULL;
454 }
455
456 cc->num = 0;
457 }
458
push_count_chars(count_chars * cc,char const * newval)459 static void push_count_chars(count_chars *cc, char const *newval)
460 {
461 cc->vals[cc->num++] = newval;
462 }
463
pop_count_chars(count_chars * cc)464 static char const *pop_count_chars(count_chars *cc)
465 {
466 if (!cc->num) {
467 return NULL;
468 }
469 return cc->vals[--cc->num];
470 }
471
insert_count_chars(count_chars * cc,char const * newval,int position)472 static void insert_count_chars(count_chars *cc, char const *newval, int position)
473 {
474 int i;
475
476 for (i = cc->num; i > position; i--) {
477 cc->vals[i] = cc->vals[i-1];
478 }
479
480 cc->vals[position] = newval;
481 cc->num++;
482 }
483
append_count_chars(count_chars * cc,count_chars * cctoadd)484 static void append_count_chars(count_chars *cc, count_chars *cctoadd)
485 {
486 int i;
487 for (i = 0; i < cctoadd->num; i++) {
488 if (cctoadd->vals[i]) {
489 push_count_chars(cc, cctoadd->vals[i]);
490 }
491 }
492 }
493
flatten_count_chars(count_chars * cc,char delim)494 static char const *flatten_count_chars(count_chars *cc, char delim)
495 {
496 int i, size;
497 char *newval;
498
499 size = 0;
500 for (i = 0; i < cc->num; i++) {
501 if (cc->vals[i]) {
502 size += strlen(cc->vals[i]) + 1;
503 if (delim) {
504 size++;
505 }
506 }
507 }
508
509 newval = (char*)lt_malloc(size + 1);
510 newval[0] = '\0';
511
512 for (i = 0; i < cc->num; i++) {
513 if (cc->vals[i]) {
514 strcat(newval, cc->vals[i]);
515 if (delim) {
516 size_t len = strlen(newval);
517 newval[len] = delim;
518 newval[len + 1] = '\0';
519 }
520 }
521 }
522
523 return newval;
524 }
525
shell_esc(char const * str)526 static char *shell_esc(char const *str)
527 {
528 int in_quote = 0;
529 char *cmd;
530 uint8_t *d;
531 uint8_t const *s;
532
533 cmd = (char *)lt_malloc(2 * strlen(str) + 3);
534 d = (unsigned char *)cmd;
535 s = (const unsigned char *)str;
536
537 #ifdef __MINGW32__
538 *d++ = '\"';
539 #endif
540
541 for (; *s; ++s) {
542 if (*s == '"') {
543 *d++ = '\\';
544 in_quote++;
545 }
546 else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
547 *d++ = '\\';
548 }
549 *d++ = *s;
550 }
551
552 #ifdef __MINGW32__
553 *d++ = '\"';
554 #endif
555
556 *d = '\0';
557 return cmd;
558 }
559
external_spawn(command_t * cmd,char const * file,char const ** argv)560 static int external_spawn(command_t *cmd, char const *file, char const **argv)
561 {
562 file = file; /* -Wunused */
563
564 if (!cmd->options.silent) {
565 char const **argument = argv;
566 NOTICE("Executing: ");
567 while (*argument) {
568 NOTICE("%s ", *argument);
569 argument++;
570 }
571 puts("");
572 }
573
574 if (cmd->options.dry_run) {
575 return 0;
576 }
577 #if defined(__EMX__) || defined(__MINGW32__)
578 return spawnvp(P_WAIT, argv[0], argv);
579 #else
580 {
581 pid_t pid;
582 pid = fork();
583 if (pid == 0) {
584 return execvp(argv[0], (char**)argv);
585 }
586 else {
587 int status;
588 waitpid(pid, &status, 0);
589
590 /*
591 * Exited via exit(status)
592 */
593 if (WIFEXITED(status)) {
594 return WEXITSTATUS(status);
595 }
596
597 #ifdef WTERMSIG
598 if (WIFSIGNALED(status)) {
599 return WTERMSIG(status);
600 }
601 #endif
602
603 /*
604 * Some other failure.
605 */
606 return 1;
607 }
608 }
609 #endif
610 }
611
run_command(command_t * cmd,count_chars * cc)612 static int run_command(command_t *cmd, count_chars *cc)
613 {
614 int ret;
615 char *command;
616 char *tmp;
617 char const *raw;
618 char const *spawn_args[4];
619 count_chars tmpcc;
620
621 init_count_chars(&tmpcc);
622
623 if (cmd->program) {
624 push_count_chars(&tmpcc, cmd->program);
625 }
626
627 append_count_chars(&tmpcc, cmd->program_opts);
628
629 append_count_chars(&tmpcc, cc);
630
631 raw = flatten_count_chars(&tmpcc, ' ');
632 command = shell_esc(raw);
633
634 memcpy(&tmp, &raw, sizeof(tmp));
635 free(tmp);
636
637 spawn_args[0] = SHELL_CMD;
638 spawn_args[1] = "-c";
639 spawn_args[2] = command;
640 spawn_args[3] = NULL;
641 ret = external_spawn(cmd, spawn_args[0], spawn_args);
642
643 free(command);
644
645 return ret;
646 }
647
648 /*
649 * print configuration
650 * shlibpath_var is used in configure.
651 */
652 #define printc(_x,_y) if (!value || !strcmp(value, _x)) printf(_x "=\"%s\"\n", _y)
653
print_config(char const * value)654 static void print_config(char const *value)
655 {
656 #ifdef LD_RUN_PATH
657 printc("runpath_var", LD_RUN_PATH);
658 #endif
659 #ifdef LD_LIBRARY_PATH
660 printc("shlibpath_var", LD_LIBRARY_PATH);
661 #endif
662 #ifdef LD_LIBRARY_PATH_LOCAL
663 printc("shlocallibpath_var", LD_LIBRARY_PATH_LOCAL);
664 #endif
665 #ifdef SHELL_CMD
666 printc("SHELL", SHELL_CMD);
667 #endif
668 #ifdef OBJECT_EXT
669 printc("objext", OBJECT_EXT);
670 #endif
671 #ifdef OBJDIR
672 printc("objdir", OBJDIR);
673 #endif
674 #ifdef DYNAMIC_LIB_EXT
675 /* add a '.' prefix because libtool does that. */
676 printc("shrext_cmds", "echo ." DYNAMIC_LIB_EXT);
677 /* add a '.' prefix because libtool does that. */
678 printc("shrext", "." DYNAMIC_LIB_EXT);
679 #endif
680 #ifdef EXE_EXT
681 printc("exeext", EXE_EXT);
682 #endif
683 #ifdef STATIC_LIB_EXT
684 printc("libext", STATIC_LIB_EXT);
685 #endif
686 #ifdef LIBRARIAN
687 printc("AR", LIBRARIAN);
688 #endif
689 #ifdef LIBRARIAN_OPTS
690 printc("AR_FLAGS", LIBRARIAN_OPTS);
691 #endif
692 #ifdef LINKER_FLAG_PREFIX
693 printc("wl", LINKER_FLAG_PREFIX);
694 #endif
695 #ifdef RANLIB
696 printc("ranlib", RANLIB);
697 #endif
698
699 }
700 /*
701 * Add a directory to the runtime library search path.
702 */
add_runtime_dir_lib(char const * arg,command_t * cmd)703 static void add_runtime_dir_lib(char const *arg, command_t *cmd)
704 {
705 #ifdef RPATH
706 add_rpath(cmd->shared_opts.dependencies, arg);
707 #else
708 (void) arg; /* -Wunused */
709 (void) cmd;
710 #endif
711 }
712
parse_long_opt(char const * arg,command_t * cmd)713 static int parse_long_opt(char const *arg, command_t *cmd)
714 {
715 char *equal_pos = strchr(arg, '=');
716 char var[50];
717 char value[500];
718
719 if (equal_pos) {
720 strncpy(var, arg, equal_pos - arg);
721 var[equal_pos - arg] = 0;
722 if (strlen(equal_pos + 1) >= sizeof(var)) {
723 return 0;
724 }
725 strcpy(value, equal_pos + 1);
726 } else {
727 strncpy(var, arg, sizeof(var) - 1);
728 var[sizeof(var) - 1] = '\0';
729
730 value[0] = '\0';
731 }
732
733 if (strcmp(var, "silent") == 0) {
734 cmd->options.silent = 1;
735 } else if (strcmp(var, "quiet") == 0) {
736 cmd->options.silent = 1;
737 } else if (strcmp(var, "debug") == 0) {
738 cmd->options.debug = 1;
739 } else if (strcmp(var, "mode") == 0) {
740 if (cmd->mode != MODE_UNKNOWN) {
741 ERROR("Cannot set --mode twice\n");
742 exit(1);
743 }
744
745 if (strcmp(value, "compile") == 0) {
746 cmd->mode = MODE_COMPILE;
747 cmd->output = OUT_OBJECT;
748
749 } else if (strcmp(value, "link") == 0) {
750 cmd->mode = MODE_LINK;
751 cmd->output = OUT_LIB;
752
753 } else if (strcmp(value, "install") == 0) {
754 cmd->mode = MODE_INSTALL;
755
756 } else if (strcmp(value, "execute") == 0) {
757 cmd->mode = MODE_EXECUTE;
758
759 } else {
760 ERROR("Unknown mode \"%s\"\n", value);
761 exit(1);
762 }
763
764 } else if (strcmp(var, "shared") == 0) {
765 if ((cmd->mode == MODE_LINK) && (cmd->output == OUT_GENERAL)) {
766 cmd->output = OUT_DYNAMIC_LIB_ONLY;
767 }
768 cmd->options.shared = SHARE_SHARED;
769
770 } else if (strcmp(var, "export-all") == 0) {
771 cmd->options.export_all = 1;
772
773 } else if (strcmp(var, "dry-run") == 0) {
774 NOTICE("Dry-run mode on!\n");
775 cmd->options.dry_run = 1;
776
777 } else if (strcmp(var, "version") == 0) {
778 NOTICE("Version " VERSION "\n");
779
780 } else if (strcmp(var, "help") == 0) {
781 usage(0);
782
783 } else if (strcmp(var, "config") == 0) {
784 print_config(value);
785
786 exit(0);
787 } else {
788 return 0;
789 }
790
791 return 1;
792 }
793
794 /* Return 1 if we eat it. */
parse_short_opt(char const * arg,command_t * cmd)795 static int parse_short_opt(char const *arg, command_t *cmd)
796 {
797 if (strcmp(arg, "export-dynamic") == 0) {
798 cmd->options.export_dynamic = 1;
799 return 1;
800 }
801
802 if (strcmp(arg, "module") == 0) {
803 cmd->output = OUT_MODULE;
804 return 1;
805 }
806
807 if (strcmp(arg, "shared") == 0) {
808 if (cmd->mode == MODE_LINK) {
809 cmd->output = OUT_DYNAMIC_LIB_ONLY;
810 }
811 cmd->options.shared = SHARE_SHARED;
812 return 1;
813 }
814
815 if (strcmp(arg, "Zexe") == 0) {
816 return 1;
817 }
818
819 if (strcmp(arg, "avoid-version") == 0) {
820 return 1;
821 }
822
823 if (strcmp(arg, "prefer-pic") == 0) {
824 cmd->options.pic_mode = PIC_PREFER;
825 return 1;
826 }
827
828 if (strcmp(arg, "prefer-non-pic") == 0) {
829 cmd->options.pic_mode = PIC_AVOID;
830 return 1;
831 }
832
833 if (strcmp(arg, "static") == 0) {
834 if ((cmd->mode == MODE_LINK) && (cmd->output == OUT_LIB)) {
835 cmd->output = OUT_STATIC_LIB_ONLY;
836 }
837 cmd->options.shared = SHARE_STATIC;
838 return 1;
839 }
840
841 if (cmd->mode == MODE_LINK) {
842 if (strcmp(arg, "no-install") == 0) {
843 cmd->options.no_install = 1;
844 return 1;
845 }
846 if (arg[0] == 'L' || arg[0] == 'l') {
847 /* Hack... */
848 arg--;
849 push_count_chars(cmd->shared_opts.dependencies, arg);
850 return 1;
851 } else if (arg[0] == 'R' && arg[1]) {
852 /* -Rdir Add dir to runtime library search path. */
853 add_runtime_dir_lib(&arg[1], cmd);
854 return 1;
855 }
856 }
857 return 0;
858 }
859
860 #ifdef TRUNCATE_DLL_NAME
truncate_dll_name(char * path)861 static char *truncate_dll_name(char *path)
862 {
863 /* Cut DLL name down to 8 characters after removing any mod_ prefix */
864 char *tmppath = strdup(path);
865 char *newname = strrchr(tmppath, '/') + 1;
866 char *ext = strrchr(newname, '.');
867 int len;
868
869 if (ext == NULL) {
870 return tmppath;
871 }
872
873 len = ext - newname;
874
875 if (strncmp(newname, "mod_", 4) == 0) {
876 strcpy(newname, newname + 4);
877 len -= 4;
878 }
879
880 if (len > 8) {
881 strcpy(newname + 8, strchr(newname, '.'));
882 }
883
884 return tmppath;
885 }
886 #endif
887
safe_strtol(char const * nptr,char const ** endptr,int base)888 static long safe_strtol(char const *nptr, char const **endptr, int base)
889 {
890 long rv;
891
892 errno = 0;
893
894 rv = strtol(nptr, (char**)endptr, 10);
895
896 if (errno == ERANGE) {
897 return 0;
898 }
899
900 return rv;
901 }
902
safe_mkdir(command_t * cmd,char const * path)903 static void safe_mkdir(command_t *cmd, char const *path)
904 {
905 int status;
906 mode_t old_umask;
907
908 old_umask = umask(0);
909 umask(old_umask);
910
911 #ifdef MKDIR_NO_UMASK
912 status = mkdir(path);
913 #else
914 status = mkdir(path, ~old_umask);
915 #endif
916 if ((status < 0) && (errno != EEXIST)) {
917 NOTICE("Warning: mkdir of %s failed\n", path);
918 }
919 }
920
921 /** Returns a file's name without the path
922 *
923 * @param path to break apart.
924 * @return pointer in path.
925 */
file_name(char const * path)926 static char const *file_name(char const *path)
927 {
928 char const *name;
929
930 name = strrchr(path, '/');
931 if (!name) {
932 name = strrchr(path, '\\'); /* eww windows? */
933 }
934 if (!name) {
935 name = path;
936 } else {
937 name++;
938 }
939
940 return name;
941 }
942
943 #ifdef GEN_EXPORTS
944
945 /** Returns a file's name without path or extension
946 *
947 * @param path to check
948 * @return pointer in path.
949 */
file_name_stripped(char const * path)950 static char const *file_name_stripped(char const *path)
951 {
952 char const *name;
953 char const *ext;
954
955 name = file_name(path);
956 ext = strrchr(name, '.');
957
958 if (ext) {
959 char *trimmed;
960
961 trimmed = lt_malloc(ext - name + 1);
962 strncpy(trimmed, name, ext - name);
963 trimmed[ext-name] = 0;
964
965 return trimmed;
966 }
967
968 return name;
969 }
970 #endif
971
972 /* version_info is in the form of MAJOR:MINOR:PATCH */
darwin_dynamic_link_function(char const * version_info)973 static char const *darwin_dynamic_link_function(char const *version_info)
974 {
975 char *newarg;
976 long major, minor, patch;
977
978 major = 0;
979 minor = 0;
980 patch = 0;
981
982 if (version_info) {
983 major = safe_strtol(version_info, &version_info, 10);
984
985 if (version_info) {
986 if (version_info[0] == ':') {
987 version_info++;
988 }
989
990 minor = safe_strtol(version_info, &version_info, 10);
991
992 if (version_info) {
993 if (version_info[0] == ':') {
994 version_info++;
995 }
996
997 patch = safe_strtol(version_info, &version_info, 10);
998
999 }
1000 }
1001 }
1002
1003 /* Avoid -dylib_compatibility_version must be greater than zero errors. */
1004 if (major == 0) {
1005 major = 1;
1006 }
1007 newarg = (char*)lt_malloc(100);
1008 snprintf(newarg, 99,
1009 "-compatibility_version %ld -current_version %ld.%ld",
1010 major, major, minor);
1011
1012 return newarg;
1013 }
1014
1015
1016 /*
1017 * Add a '.libs/' to the buffer. The caller ensures that
1018 * The buffer is large enough to handle 6 extra characters.
1019 */
add_dotlibs(char * buffer)1020 static void add_dotlibs(char *buffer)
1021 {
1022 char *name = strrchr(buffer, '/');
1023
1024 if (!name) {
1025 if (!buffer[0]) {
1026 strcpy(buffer, ".libs/");
1027 return;
1028 }
1029 name = buffer;
1030 } else {
1031 name++;
1032 }
1033 memmove(name + 6, name, strlen(name));
1034 memcpy(name, ".libs/", 6);
1035 }
1036
gen_library_name(char const * name,enum lib_type genlib)1037 static char *gen_library_name(char const *name, enum lib_type genlib)
1038 {
1039 char *newarg, *newext;
1040
1041 newarg = (char *)calloc(strlen(name) + 11, 1);
1042
1043 if (genlib == TYPE_MODULE_LIB && strncmp(name, "lib", 3) == 0) {
1044 name += 3;
1045 }
1046
1047 if (genlib == TYPE_MODULE_LIB) {
1048 strcpy(newarg, file_name(name));
1049 }
1050 else {
1051 strcpy(newarg, name);
1052 }
1053
1054 newext = strrchr(newarg, '.');
1055 if (!newext) {
1056 ERROR("Library path does not have an extension\n");
1057 free(newarg);
1058
1059 return NULL;
1060 }
1061 newext++;
1062
1063 switch (genlib) {
1064 case TYPE_STATIC_LIB:
1065 strcpy(newext, STATIC_LIB_EXT);
1066 break;
1067 case TYPE_DYNAMIC_LIB:
1068 strcpy(newext, DYNAMIC_LIB_EXT);
1069 break;
1070 case TYPE_MODULE_LIB:
1071 strcpy(newext, MODULE_LIB_EXT);
1072 break;
1073
1074 default:
1075 break;
1076 }
1077
1078 add_dotlibs(newarg);
1079
1080 return newarg;
1081 }
1082
gen_install_name(char const * name,enum lib_type genlib)1083 static char *gen_install_name(char const *name, enum lib_type genlib)
1084 {
1085 char *newname;
1086 int rv;
1087 struct stat sb;
1088
1089 newname = gen_library_name(name, genlib);
1090 if (!newname) return NULL;
1091
1092 /* Check if it exists. If not, return NULL. */
1093 rv = stat(newname, &sb);
1094
1095 if (rv) {
1096 free(newname);
1097 return NULL;
1098 }
1099
1100 return newname;
1101 }
1102
check_object_exists(command_t * cmd,char const * arg,int arglen)1103 static char const *check_object_exists(command_t *cmd, char const *arg, int arglen)
1104 {
1105 char *newarg, *ext;
1106 struct stat sb;
1107
1108 newarg = (char *)lt_malloc(arglen + 10);
1109 memcpy(newarg, arg, arglen);
1110 newarg[arglen] = 0;
1111 ext = newarg + arglen;
1112
1113 strcpy(ext, OBJECT_EXT);
1114
1115 DEBUG("Checking (obj): %s\n", newarg);
1116 if (stat(newarg, &sb) == 0) {
1117 return newarg;
1118 }
1119
1120 free(newarg);
1121
1122 return NULL;
1123 }
1124
1125 /* libdircheck values:
1126 * 0 - no .libs suffix
1127 * 1 - .libs suffix
1128 */
check_library_exists(command_t * cmd,char const * arg,int pathlen,int libdircheck,enum lib_type * libtype)1129 static char *check_library_exists(command_t *cmd, char const *arg, int pathlen,
1130 int libdircheck, enum lib_type *libtype)
1131 {
1132 char *newarg, *ext;
1133 int pass, rv, newpathlen;
1134
1135 newarg = (char *)lt_malloc(strlen(arg) + 10);
1136 strcpy(newarg, arg);
1137 newarg[pathlen] = '\0';
1138
1139 newpathlen = pathlen;
1140 if (libdircheck) {
1141 add_dotlibs(newarg);
1142 newpathlen += sizeof(".libs/") - 1;
1143 }
1144
1145 strcpy(newarg + newpathlen, arg + pathlen);
1146 ext = strrchr(newarg, '.');
1147 if (!ext) {
1148 ERROR("Error: Library path does not have an extension\n");
1149 free(newarg);
1150
1151 return NULL;
1152 }
1153 ext++;
1154
1155 pass = 0;
1156
1157 do {
1158 struct stat sb;
1159
1160 switch (pass) {
1161 case 0:
1162 if (cmd->options.pic_mode != PIC_AVOID &&
1163 cmd->options.shared != SHARE_STATIC) {
1164 strcpy(ext, DYNAMIC_LIB_EXT);
1165 *libtype = TYPE_DYNAMIC_LIB;
1166 break;
1167 }
1168 pass = 1;
1169 /* Fall through */
1170 case 1:
1171 strcpy(ext, STATIC_LIB_EXT);
1172 *libtype = TYPE_STATIC_LIB;
1173 break;
1174 case 2:
1175 strcpy(ext, MODULE_LIB_EXT);
1176 *libtype = TYPE_MODULE_LIB;
1177 break;
1178 case 3:
1179 strcpy(ext, OBJECT_EXT);
1180 *libtype = TYPE_OBJECT;
1181 break;
1182 default:
1183 *libtype = TYPE_UKNOWN;
1184 break;
1185 }
1186
1187 DEBUG("Checking (lib): %s\n", newarg);
1188 rv = stat(newarg, &sb);
1189 }
1190 while (rv != 0 && ++pass < 4);
1191
1192 if (rv == 0) {
1193 return newarg;
1194 }
1195
1196 free(newarg);
1197
1198 return NULL;
1199 }
1200
load_install_path(char const * arg)1201 static char * load_install_path(char const *arg)
1202 {
1203 FILE *f;
1204 char *path;
1205
1206 f = fopen(arg,"r");
1207 if (f == NULL) {
1208 return NULL;
1209 }
1210
1211 path = lt_malloc(PATH_MAX);
1212
1213 fgets(path, PATH_MAX, f);
1214 fclose(f);
1215
1216 if (path[strlen(path)-1] == '\n') {
1217 path[strlen(path)-1] = '\0';
1218 }
1219
1220 /* Check that we have an absolute path.
1221 * Otherwise the file could be a GNU libtool file.
1222 */
1223 if (path[0] != '/') {
1224 free(path);
1225
1226 return NULL;
1227 }
1228 return path;
1229 }
1230
load_noinstall_path(char const * arg,int pathlen)1231 static char *load_noinstall_path(char const *arg, int pathlen)
1232 {
1233 char *newarg, *expanded_path;
1234 int newpathlen;
1235
1236 newarg = (char *)lt_malloc(strlen(arg) + 10);
1237 strcpy(newarg, arg);
1238 newarg[pathlen] = 0;
1239
1240 newpathlen = pathlen;
1241 strcat(newarg, ".libs");
1242 newpathlen += sizeof(".libs") - 1;
1243 newarg[newpathlen] = 0;
1244
1245 #ifdef HAS_REALPATH
1246 expanded_path = lt_malloc(PATH_MAX);
1247 expanded_path = realpath(newarg, expanded_path);
1248 /* Uh, oh. There was an error. Fall back on our first guess. */
1249 if (!expanded_path) {
1250 expanded_path = newarg;
1251 }
1252 #else
1253 /* We might get ../ or something goofy. Oh, well. */
1254 expanded_path = newarg;
1255 #endif
1256
1257 return expanded_path;
1258 }
1259
add_dynamic_link_opts(command_t * cmd,count_chars * args)1260 static void add_dynamic_link_opts(command_t *cmd, count_chars *args)
1261 {
1262 #ifdef DYNAMIC_LINK_OPTS
1263 if (cmd->options.pic_mode != PIC_AVOID) {
1264 DEBUG("Adding linker opt: %s\n", DYNAMIC_LINK_OPTS);
1265
1266 push_count_chars(args, DYNAMIC_LINK_OPTS);
1267 if (cmd->undefined_flag) {
1268 push_count_chars(args, "-undefined");
1269 #if defined(__APPLE__)
1270 /* -undefined dynamic_lookup is used by the bundled Python in
1271 * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+,
1272 * we'll get a linker error if we pass this flag.
1273 */
1274 if (strcasecmp(cmd->undefined_flag, "dynamic_lookup") == 0) {
1275 insert_count_chars(cmd->program_opts, "MACOSX_DEPLOYMENT_TARGET=10.3", 0);
1276 }
1277 #endif
1278 push_count_chars(args, cmd->undefined_flag);
1279 }
1280 else {
1281 #ifdef DYNAMIC_LINK_UNDEFINED
1282 DEBUG("Adding linker opt: %s\n", DYNAMIC_LINK_UNDEFINED);
1283
1284 push_count_chars(args, DYNAMIC_LINK_UNDEFINED);
1285 #endif
1286 }
1287 }
1288 #endif
1289 }
1290
1291 /* Read the final install location and add it to runtime library search path. */
1292 #ifdef RPATH
add_rpath(count_chars * cc,char const * path)1293 static void add_rpath(count_chars *cc, char const *path)
1294 {
1295 int size = 0;
1296 char *tmp;
1297
1298 #ifdef LINKER_FLAG_PREFIX
1299 size = strlen(LINKER_FLAG_PREFIX);
1300 #endif
1301 size = size + strlen(path) + strlen(RPATH) + 2;
1302 tmp = lt_malloc(size);
1303
1304 #ifdef LINKER_FLAG_PREFIX
1305 strcpy(tmp, LINKER_FLAG_PREFIX);
1306 strcat(tmp, RPATH);
1307 #else
1308 strcpy(tmp, RPATH);
1309 #endif
1310 #ifndef LINKER_FLAG_NO_EQUALS
1311 strcat(tmp, "=");
1312 #endif
1313 strcat(tmp, path);
1314
1315 push_count_chars(cc, tmp);
1316 }
1317
add_rpath_file(count_chars * cc,char const * arg)1318 static void add_rpath_file(count_chars *cc, char const *arg)
1319 {
1320 char const *path;
1321
1322 path = load_install_path(arg);
1323 if (path) {
1324 add_rpath(cc, path);
1325 lt_const_free(path);
1326 }
1327 }
1328
add_rpath_noinstall(count_chars * cc,char const * arg,int pathlen)1329 static void add_rpath_noinstall(count_chars *cc, char const *arg, int pathlen)
1330 {
1331 char const *path;
1332
1333 path = load_noinstall_path(arg, pathlen);
1334 if (path) {
1335 add_rpath(cc, path);
1336 lt_const_free(path);
1337 }
1338 }
1339 #endif
1340
1341 #ifdef DYNAMIC_LINK_NO_INSTALL
add_dylink_noinstall(count_chars * cc,char const * arg,int pathlen,int extlen)1342 static void add_dylink_noinstall(count_chars *cc, char const *arg, int pathlen,
1343 int extlen)
1344 {
1345 char const *install_path, *current_path, *name;
1346 char *exp_argument;
1347 int i_p_len, c_p_len, name_len, dyext_len, cur_len;
1348
1349 install_path = load_install_path(arg);
1350 current_path = load_noinstall_path(arg, pathlen);
1351
1352 if (!install_path || !current_path) {
1353 return;
1354 }
1355
1356 push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
1357
1358 i_p_len = strlen(install_path);
1359 c_p_len = strlen(current_path);
1360
1361 name = arg+pathlen;
1362 name_len = extlen-pathlen;
1363 dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
1364
1365 /* No, we need to replace the extension. */
1366 exp_argument = (char *)lt_malloc(i_p_len + c_p_len + (name_len*2) +
1367 (dyext_len*2) + 2);
1368
1369 cur_len = 0;
1370 strcpy(exp_argument, install_path);
1371 cur_len += i_p_len;
1372 exp_argument[cur_len++] = '/';
1373 strncpy(exp_argument+cur_len, name, extlen-pathlen);
1374 cur_len += name_len;
1375 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
1376 cur_len += dyext_len;
1377 exp_argument[cur_len++] = ':';
1378 strcpy(exp_argument+cur_len, current_path);
1379 cur_len += c_p_len;
1380 exp_argument[cur_len++] = '/';
1381 strncpy(exp_argument+cur_len, name, extlen-pathlen);
1382 cur_len += name_len;
1383 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
1384 cur_len += dyext_len;
1385
1386 push_count_chars(cc, exp_argument);
1387 }
1388 #endif
1389
1390 #ifdef ADD_MINUS_L
1391 /* use -L -llibname to allow to use installed libraries */
add_minus_l(count_chars * cc,char const * arg)1392 static void add_minus_l(count_chars *cc, char const *arg)
1393 {
1394 char *newarg;
1395 char *name = strrchr(arg, '/');
1396 char *file = strrchr(arg, '.');
1397
1398 if ((name != NULL) && (file != NULL) &&
1399 (strstr(name, "lib") == (name + 1))) {
1400 *name = '\0';
1401 *file = '\0';
1402 file = name;
1403 file = file+4;
1404 push_count_chars(cc, "-L");
1405 push_count_chars(cc, arg);
1406 /* we need one argument like -lapr-1 */
1407 newarg = lt_malloc(strlen(file) + 3);
1408 strcpy(newarg, "-l");
1409 strcat(newarg, file);
1410 push_count_chars(cc, newarg);
1411 } else {
1412 push_count_chars(cc, arg);
1413 }
1414 }
1415 #endif
1416
1417 #if 0
1418 static void add_linker_flag_prefix(count_chars *cc, char const *arg)
1419 {
1420 #ifndef LINKER_FLAG_PREFIX
1421 push_count_chars(cc, arg);
1422 #else
1423 char *newarg;
1424 newarg = (char*)lt_malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
1425 strcpy(newarg, LINKER_FLAG_PREFIX);
1426 strcat(newarg, arg);
1427 push_count_chars(cc, newarg);
1428 #endif
1429 }
1430 #endif
1431
explode_static_lib(command_t * cmd,char const * lib)1432 static int explode_static_lib(command_t *cmd, char const *lib)
1433 {
1434 count_chars tmpdir_cc, libname_cc;
1435 char const *tmpdir, *libname;
1436 char savewd[PATH_MAX];
1437 char const *name;
1438 DIR *dir;
1439 struct dirent *entry;
1440 char const *lib_args[4];
1441
1442 /* Bah! */
1443 if (cmd->options.dry_run) {
1444 return 0;
1445 }
1446
1447 name = file_name(lib);
1448
1449 init_count_chars(&tmpdir_cc);
1450 push_count_chars(&tmpdir_cc, ".libs/");
1451 push_count_chars(&tmpdir_cc, name);
1452 push_count_chars(&tmpdir_cc, ".exploded/");
1453 tmpdir = flatten_count_chars(&tmpdir_cc, 0);
1454
1455 NOTICE("Making: %s\n", tmpdir);
1456
1457 safe_mkdir(cmd, tmpdir);
1458
1459 push_count_chars(cmd->tmp_dirs, tmpdir);
1460
1461 getcwd(savewd, sizeof(savewd));
1462
1463 if (chdir(tmpdir) != 0) {
1464 NOTICE("Warning: could not explode %s\n", lib);
1465
1466 return 1;
1467 }
1468
1469 if (lib[0] == '/') {
1470 libname = lib;
1471 }
1472 else {
1473 init_count_chars(&libname_cc);
1474 push_count_chars(&libname_cc, "../../");
1475 push_count_chars(&libname_cc, lib);
1476 libname = flatten_count_chars(&libname_cc, 0);
1477 }
1478
1479 lib_args[0] = LIBRARIAN;
1480 lib_args[1] = "x";
1481 lib_args[2] = libname;
1482 lib_args[3] = NULL;
1483
1484 external_spawn(cmd, LIBRARIAN, lib_args);
1485
1486 chdir(savewd);
1487 dir = opendir(tmpdir);
1488
1489 while ((entry = readdir(dir)) != NULL) {
1490 #if defined(__APPLE__) && defined(RANLIB)
1491 /* Apple inserts __.SYMDEF which isn't needed.
1492 * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't
1493 * much fun either. Just skip them.
1494 */
1495 if (strstr(entry->d_name, "__.SYMDEF") != NULL) {
1496 continue;
1497 }
1498 #endif
1499 if (entry->d_name[0] != '.') {
1500 push_count_chars(&tmpdir_cc, entry->d_name);
1501 name = flatten_count_chars(&tmpdir_cc, 0);
1502
1503 DEBUG("Adding object: %s\n", name);
1504 push_count_chars(cmd->obj_files, name);
1505 pop_count_chars(&tmpdir_cc);
1506 }
1507 }
1508
1509 closedir(dir);
1510 return 0;
1511 }
1512
parse_input_file_name(char const * arg,command_t * cmd)1513 static int parse_input_file_name(char const *arg, command_t *cmd)
1514 {
1515 char const *ext = strrchr(arg, '.');
1516 char const *name;
1517 int pathlen;
1518 enum lib_type libtype;
1519 char const *newarg;
1520
1521 /* Can't guess the extension */
1522 if (!ext) {
1523 return 0;
1524 }
1525
1526 ext++;
1527 name = file_name(arg);
1528 pathlen = name - arg;
1529
1530 /*
1531 * Were linking and have an archived object or object file
1532 * push it onto the list of object files which'll get used
1533 * to create the input files list for the linker.
1534 *
1535 * We assume that these are outside of the project were building,
1536 * as there's no reason to create .a files as part of the build
1537 * process.
1538 */
1539 if (!strcmp(ext, STATIC_LIB_EXT) && (cmd->mode == MODE_LINK)) {
1540 struct stat sb;
1541
1542 if (!stat(arg, &sb)) {
1543 DEBUG("Adding object: %s\n", arg);
1544
1545 push_count_chars(cmd->obj_files, arg);
1546
1547 return 1;
1548 }
1549 }
1550
1551 /*
1552 * More object files, if were linking they get set as input
1553 * files.
1554 */
1555 if (!strcmp(ext, "lo") || !strcmp(ext, OBJECT_EXT)) {
1556 newarg = check_object_exists(cmd, arg, ext - arg);
1557 if (!newarg) {
1558 ERROR("Can not find suitable object file for %s\n", arg);
1559 exit(1);
1560 }
1561
1562 if (cmd->mode == MODE_LINK) {
1563 DEBUG("Adding object: %s\n", newarg);
1564
1565 push_count_chars(cmd->obj_files, newarg);
1566 } else {
1567 push_count_chars(cmd->arglist, newarg);
1568 }
1569
1570 return 1;
1571 }
1572
1573 if (!strcmp(ext, "la")) {
1574 switch (cmd->mode) {
1575 case MODE_LINK:
1576 /* Try the .libs dir first! */
1577 newarg = check_library_exists(cmd, arg, pathlen, 1, &libtype);
1578 if (!newarg) {
1579 /* Try the normal dir next. */
1580 newarg = check_library_exists(cmd, arg, pathlen, 0, &libtype);
1581 if (!newarg) {
1582 ERROR("Can not find suitable library for %s\n", arg);
1583 exit(1);
1584 }
1585 }
1586
1587 /* It is not ok to just add the file: a library may added with:
1588 1 - -L path library_name. (For *.so in Linux).
1589 2 - library_name.
1590 */
1591 #ifdef ADD_MINUS_L
1592 if (libtype == TYPE_DYNAMIC_LIB) {
1593 add_minus_l(cmd->shared_opts.dependencies, newarg);
1594 } else if (cmd->output == OUT_LIB &&
1595 libtype == TYPE_STATIC_LIB) {
1596 explode_static_lib(cmd, newarg);
1597 } else {
1598 push_count_chars(cmd->shared_opts.dependencies, newarg);
1599 }
1600 #else
1601 if (cmd->output == OUT_LIB && libtype == TYPE_STATIC_LIB) {
1602 explode_static_lib(cmd, newarg);
1603 }
1604 else {
1605 push_count_chars(cmd->shared_opts.dependencies, newarg);
1606 }
1607 #endif
1608 if (libtype == TYPE_DYNAMIC_LIB) {
1609 if (cmd->options.no_install) {
1610 #ifdef RPATH
1611 add_rpath_noinstall(cmd->shared_opts.dependencies,
1612 arg, pathlen);
1613 #endif
1614 }
1615 else {
1616 #ifdef RPATH
1617 add_rpath_file(cmd->shared_opts.dependencies, arg);
1618 #endif
1619 }
1620 }
1621 break;
1622 case MODE_INSTALL:
1623 /*
1624 * If we've already recorded a library to
1625 * install, we're most likely getting the .la
1626 * file that we want to install as.
1627 *
1628 * The problem is that we need to add it as the
1629 * directory, not the .la file itself.
1630 * Otherwise, we'll do odd things.
1631 */
1632 if (cmd->output == OUT_LIB) {
1633 char *tmp;
1634
1635 tmp = strdup(arg);
1636 tmp[pathlen] = '\0';
1637 push_count_chars(cmd->arglist, tmp);
1638
1639 } else {
1640 cmd->output = OUT_LIB;
1641 cmd->output_name = arg;
1642 cmd->static_name.install = gen_install_name(arg, 0);
1643 cmd->shared_name.install = gen_install_name(arg, 1);
1644 cmd->module_name.install = gen_install_name(arg, 2);
1645
1646 if (!cmd->static_name.install &&
1647 !cmd->shared_name.install &&
1648 !cmd->module_name.install) {
1649 ERROR("Files to install do not exist\n");
1650 exit(1);
1651 }
1652
1653 }
1654 break;
1655 default:
1656 break;
1657 }
1658
1659 return 1;
1660 }
1661
1662 if (!strcmp(ext, "c")) {
1663 /* If we don't already have an idea what our output name will be. */
1664 if (!cmd->basename) {
1665 char *tmp = lt_malloc(strlen(arg) + 4);
1666 strcpy(tmp, arg);
1667 strcpy(strrchr(tmp, '.') + 1, "lo");
1668
1669 cmd->basename = tmp;
1670
1671 cmd->fake_output_name = strrchr(cmd->basename, '/');
1672 if (cmd->fake_output_name) {
1673 cmd->fake_output_name++;
1674 } else {
1675 cmd->fake_output_name = cmd->basename;
1676 }
1677 }
1678 }
1679
1680 return 0;
1681 }
1682
parse_output_file_name(char const * arg,command_t * cmd)1683 static int parse_output_file_name(char const *arg, command_t *cmd)
1684 {
1685 char const *name;
1686 char const *ext;
1687 char *newarg = NULL;
1688 size_t pathlen;
1689
1690 cmd->fake_output_name = arg;
1691
1692 name = file_name(arg);
1693 ext = strrchr(name, '.');
1694
1695 #ifdef EXE_EXT
1696 if (!ext || strcmp(ext, EXE_EXT) == 0) {
1697 #else
1698 if (!ext) {
1699 #endif
1700 cmd->basename = arg;
1701 cmd->output = OUT_PROGRAM;
1702 #if defined(_OSD_POSIX)
1703 cmd->options.pic_mode = PIC_AVOID;
1704 #endif
1705 newarg = (char *)lt_malloc(strlen(arg) + 5);
1706 strcpy(newarg, arg);
1707 #ifdef EXE_EXT
1708 if (!ext) {
1709 strcat(newarg, EXE_EXT);
1710 }
1711 #endif
1712 cmd->output_name = newarg;
1713 return 1;
1714 }
1715
1716 ext++;
1717 pathlen = name - arg;
1718
1719 if (strcmp(ext, "la") == 0) {
1720 assert(cmd->mode == MODE_LINK);
1721
1722 cmd->basename = arg;
1723 cmd->static_name.normal = gen_library_name(arg, TYPE_STATIC_LIB);
1724 cmd->shared_name.normal = gen_library_name(arg, TYPE_DYNAMIC_LIB);
1725 cmd->module_name.normal = gen_library_name(arg, TYPE_MODULE_LIB);
1726 cmd->static_name.install = gen_install_name(arg, TYPE_STATIC_LIB);
1727 cmd->shared_name.install = gen_install_name(arg, TYPE_DYNAMIC_LIB);
1728 cmd->module_name.install = gen_install_name(arg, TYPE_MODULE_LIB);
1729
1730 if (!cmd->options.dry_run) {
1731 char *newname;
1732 char *newext;
1733 newname = lt_malloc(strlen(cmd->static_name.normal) + 1);
1734
1735 strcpy(newname, cmd->static_name.normal);
1736 newext = strrchr(newname, '/');
1737 if (!newext) {
1738 /* Check first to see if the dir already exists! */
1739 safe_mkdir(cmd, ".libs");
1740 } else {
1741 *newext = '\0';
1742 safe_mkdir(cmd, newname);
1743 }
1744 free(newname);
1745 }
1746
1747 #ifdef TRUNCATE_DLL_NAME
1748 if (shared) {
1749 arg = truncate_dll_name(arg);
1750 }
1751 #endif
1752
1753 cmd->output_name = arg;
1754 return 1;
1755 }
1756
1757 if (strcmp(ext, STATIC_LIB_EXT) == 0) {
1758 assert(cmd->mode == MODE_LINK);
1759
1760 cmd->basename = arg;
1761 cmd->options.shared = SHARE_STATIC;
1762 cmd->output = OUT_STATIC_LIB_ONLY;
1763 cmd->static_name.normal = gen_library_name(arg, TYPE_STATIC_LIB);
1764 cmd->static_name.install = gen_install_name(arg, TYPE_STATIC_LIB);
1765
1766 if (!cmd->options.dry_run) {
1767 char *newname;
1768 char *newext;
1769 newname = lt_malloc(strlen(cmd->static_name.normal) + 1);
1770
1771 strcpy(newname, cmd->static_name.normal);
1772 newext = strrchr(newname, '/');
1773 if (!newext) {
1774 /* Check first to see if the dir already exists! */
1775 safe_mkdir(cmd, ".libs");
1776 } else {
1777 *newext = '\0';
1778 safe_mkdir(cmd, newname);
1779 }
1780 free(newname);
1781 }
1782
1783 cmd->output_name = arg;
1784 return 1;
1785 }
1786
1787 if (strcmp(ext, DYNAMIC_LIB_EXT) == 0) {
1788 assert(cmd->mode == MODE_LINK);
1789
1790 cmd->basename = arg;
1791 cmd->options.shared = SHARE_SHARED;
1792 cmd->output = OUT_DYNAMIC_LIB_ONLY;
1793 cmd->shared_name.normal = gen_library_name(arg, TYPE_DYNAMIC_LIB);
1794 cmd->module_name.normal = gen_library_name(arg, TYPE_MODULE_LIB);
1795 cmd->shared_name.install = gen_install_name(arg, TYPE_DYNAMIC_LIB);
1796 cmd->module_name.install = gen_install_name(arg, TYPE_MODULE_LIB);
1797
1798 if (!cmd->options.dry_run) {
1799 char *newname;
1800 char *newext;
1801 newname = lt_malloc(strlen(cmd->shared_name.normal) + 1);
1802
1803 strcpy(newname, cmd->shared_name.normal);
1804 newext = strrchr(newname, '/');
1805 if (!newext) {
1806 /* Check first to see if the dir already exists! */
1807 safe_mkdir(cmd, ".libs");
1808 } else {
1809 *newext = '\0';
1810 safe_mkdir(cmd, newname);
1811 }
1812 free(newname);
1813 }
1814
1815 cmd->output_name = arg;
1816 return 1;
1817 }
1818
1819 if (strcmp(ext, "lo") == 0) {
1820 char *newext;
1821 cmd->basename = arg;
1822 cmd->output = OUT_OBJECT;
1823 newarg = (char *)lt_malloc(strlen(arg) + 2);
1824 strcpy(newarg, arg);
1825 newext = strrchr(newarg, '.') + 1;
1826 strcpy(newext, OBJECT_EXT);
1827 cmd->output_name = newarg;
1828 return 1;
1829 }
1830
1831 if (strcmp(ext, DYNAMIC_LIB_EXT) == 0) {
1832 ERROR("Please build libraries with .la target, not ."
1833 DYNAMIC_LIB_EXT "\n");
1834
1835 exit(1);
1836 }
1837
1838 if (strcmp(ext, STATIC_LIB_EXT) == 0) {
1839 ERROR("Please build libraries with .la target, not ."
1840 STATIC_LIB_EXT "\n");
1841
1842 exit(1);
1843 }
1844
1845 return 0;
1846 }
1847
1848 static char const *automode(char const *arg, command_t *cmd)
1849 {
1850 if (cmd->mode != MODE_UNKNOWN) return arg;
1851
1852 if (!strcmp(arg, "CC") ||
1853 !strcmp(arg, "CXX")) {
1854 DEBUG("Now in compile mode, guessed from: %s\n", arg);
1855 arg = CC;
1856 cmd->mode = MODE_COMPILE;
1857
1858 } else if (!strcmp(arg, "LINK") ||
1859 !strcmp(arg, "LINK.c") ||
1860 !strcmp(arg, "LINK.cxx")) {
1861 DEBUG("Now in linker mode, guessed from: %s\n", arg);
1862 arg = LINK_C;
1863 cmd->mode = MODE_LINK;
1864 }
1865
1866 return arg;
1867 }
1868
1869
1870 #ifdef GEN_EXPORTS
1871 static void generate_def_file(command_t *cmd)
1872 {
1873 char def_file[1024];
1874 char implib_file[1024];
1875 char *ext;
1876 FILE *hDef;
1877 char *export_args[1024];
1878 int num_export_args = 0;
1879 char *cmd;
1880 int cmd_size = 0;
1881 int a;
1882
1883 if (cmd->output_name) {
1884 strcpy(def_file, cmd->output_name);
1885 strcat(def_file, ".def");
1886 hDef = fopen(def_file, "w");
1887
1888 if (hDef != NULL) {
1889 fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", file_name_stripped(cmd->output_name));
1890 fprintf(hDef, "DATA NONSHARED\n");
1891 fprintf(hDef, "EXPORTS\n");
1892 fclose(hDef);
1893
1894 for (a = 0; a < cmd->num_obj_files; a++) {
1895 cmd_size += strlen(cmd->obj_files[a]) + 1;
1896 }
1897
1898 cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
1899 cmd = (char *)lt_malloc(cmd_size);
1900 strcpy(cmd, GEN_EXPORTS);
1901
1902 for (a=0; a < cmd->num_obj_files; a++) {
1903 strcat(cmd, " ");
1904 strcat(cmd, cmd->obj_files[a] );
1905 }
1906
1907 strcat(cmd, ">>");
1908 strcat(cmd, def_file);
1909 puts(cmd);
1910 export_args[num_export_args++] = SHELL_CMD;
1911 export_args[num_export_args++] = "-c";
1912 export_args[num_export_args++] = cmd;
1913 export_args[num_export_args++] = NULL;
1914 external_spawn(cmd, export_args[0], (char const**)export_args);
1915 cmd->arglist[cmd->num_args++] = strdup(def_file);
1916
1917 /* Now make an import library for the dll */
1918 num_export_args = 0;
1919 export_args[num_export_args++] = DEF2IMPLIB_CMD;
1920 export_args[num_export_args++] = "-o";
1921
1922 strcpy(implib_file, ".libs/");
1923 strcat(implib_file, cmd->basename);
1924 ext = strrchr(implib_file, '.');
1925
1926 if (ext) {
1927 *ext = '\0';
1928 }
1929
1930 strcat(implib_file, ".");
1931 strcat(implib_file, STATIC_LIB_EXT);
1932
1933 export_args[num_export_args++] = implib_file;
1934 export_args[num_export_args++] = def_file;
1935 export_args[num_export_args++] = NULL;
1936 external_spawn(cmd, export_args[0], (char const**)export_args);
1937
1938 }
1939 }
1940 }
1941 #endif
1942
1943 #if 0
1944 static char const* expand_path(char const *relpath)
1945 {
1946 char foo[PATH_MAX], *newpath;
1947
1948 getcwd(foo, PATH_MAX-1);
1949 newpath = (char*)lt_malloc(strlen(foo)+strlen(relpath)+2);
1950 strcpy(newpath, foo);
1951 strcat(newpath, "/");
1952 strcat(newpath, relpath);
1953 return newpath;
1954 }
1955 #endif
1956
1957 static void link_fixup(command_t *cmd)
1958 {
1959 /* If we were passed an -rpath directive, we need to build
1960 * shared objects too. Otherwise, we should only create static
1961 * libraries.
1962 */
1963 if (!cmd->install_path && (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
1964 cmd->output == OUT_MODULE || cmd->output == OUT_LIB)) {
1965 if (cmd->options.shared == SHARE_SHARED) {
1966 cmd->install_path = LIBDIR;
1967 }
1968 }
1969
1970 if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
1971 cmd->output == OUT_MODULE ||
1972 cmd->output == OUT_LIB) {
1973
1974 push_count_chars(cmd->shared_opts.normal, "-o");
1975 if (cmd->output == OUT_MODULE) {
1976 push_count_chars(cmd->shared_opts.normal, cmd->module_name.normal);
1977 } else {
1978 push_count_chars(cmd->shared_opts.normal, cmd->shared_name.normal);
1979 #ifdef DYNAMIC_INSTALL_NAME
1980 push_count_chars(cmd->shared_opts.normal, DYNAMIC_INSTALL_NAME);
1981
1982 if (!cmd->install_path) {
1983 ERROR("Installation mode requires -rpath\n");
1984 exit(1);
1985 }
1986
1987 {
1988 char *tmp = lt_malloc(PATH_MAX);
1989 strcpy(tmp, cmd->install_path);
1990
1991 if (cmd->shared_name.install) {
1992 strcat(tmp, strrchr(cmd->shared_name.install, '/'));
1993 } else {
1994 strcat(tmp, strrchr(cmd->shared_name.normal, '/'));
1995 }
1996
1997 push_count_chars(cmd->shared_opts.normal, tmp);
1998 }
1999 #endif
2000 }
2001
2002 append_count_chars(cmd->shared_opts.normal, cmd->obj_files);
2003 append_count_chars(cmd->shared_opts.normal, cmd->shared_opts.dependencies);
2004
2005 if (cmd->options.export_all) {
2006 #ifdef GEN_EXPORTS
2007 generate_def_file(cmd);
2008 #endif
2009 }
2010 }
2011
2012 if (cmd->output == OUT_LIB || cmd->output == OUT_STATIC_LIB_ONLY) {
2013 push_count_chars(cmd->static_opts.normal, "-o");
2014 push_count_chars(cmd->static_opts.normal, cmd->output_name);
2015 }
2016
2017 if (cmd->output == OUT_PROGRAM) {
2018 if (cmd->output_name) {
2019 push_count_chars(cmd->arglist, "-o");
2020 push_count_chars(cmd->arglist, cmd->output_name);
2021 append_count_chars(cmd->arglist, cmd->obj_files);
2022 append_count_chars(cmd->arglist, cmd->shared_opts.dependencies);
2023 add_dynamic_link_opts(cmd, cmd->arglist);
2024 }
2025 }
2026 }
2027
2028 static void post_parse_fixup(command_t *cmd)
2029 {
2030 switch (cmd->mode) {
2031 case MODE_COMPILE:
2032 #ifdef PIC_FLAG
2033 if (cmd->options.pic_mode != PIC_AVOID) {
2034 push_count_chars(cmd->arglist, PIC_FLAG);
2035 }
2036 #endif
2037 if (cmd->output_name) {
2038 push_count_chars(cmd->arglist, "-o");
2039 push_count_chars(cmd->arglist, cmd->output_name);
2040 }
2041 break;
2042 case MODE_LINK:
2043 link_fixup(cmd);
2044 break;
2045 case MODE_INSTALL:
2046 if (cmd->output == OUT_LIB) {
2047 link_fixup(cmd);
2048 }
2049 default:
2050 break;
2051 }
2052
2053 #ifdef USE_OMF
2054 if (cmd->output == OUT_OBJECT ||
2055 cmd->output == OUT_PROGRAM ||
2056 cmd->output == OUT_LIB ||
2057 cmd->output == OUT_DYNAMIC_LIB_ONLY) {
2058 push_count_chars(cmd->arglist, "-Zomf");
2059 }
2060 #endif
2061
2062 if (cmd->options.shared &&
2063 (cmd->output == OUT_OBJECT ||
2064 cmd->output == OUT_LIB ||
2065 cmd->output == OUT_DYNAMIC_LIB_ONLY)) {
2066 #ifdef SHARE_SW
2067 push_count_chars(cmd->arglist, SHARE_SW);
2068 #endif
2069 }
2070 }
2071
2072 static int run_mode(command_t *cmd)
2073 {
2074 int rv = 0;
2075 count_chars *cctemp;
2076
2077 cctemp = (count_chars*)lt_malloc(sizeof(count_chars));
2078 init_count_chars(cctemp);
2079
2080 switch (cmd->mode) {
2081 case MODE_COMPILE:
2082 rv = run_command(cmd, cmd->arglist);
2083 if (rv) goto finish;
2084 break;
2085 case MODE_INSTALL:
2086 /* Well, we'll assume it's a file going to a directory... */
2087 /* For brain-dead install-sh based scripts, we have to repeat
2088 * the command N-times. install-sh should die.
2089 */
2090 if (!cmd->output_name) {
2091 rv = run_command(cmd, cmd->arglist);
2092 if (rv) goto finish;
2093 }
2094 if (cmd->output_name) {
2095 append_count_chars(cctemp, cmd->arglist);
2096 insert_count_chars(cctemp,
2097 cmd->output_name,
2098 cctemp->num - 1);
2099 rv = run_command(cmd, cctemp);
2100 if (rv) goto finish;
2101 clear_count_chars(cctemp);
2102 }
2103 if (cmd->static_name.install) {
2104 append_count_chars(cctemp, cmd->arglist);
2105 insert_count_chars(cctemp,
2106 cmd->static_name.install,
2107 cctemp->num - 1);
2108 rv = run_command(cmd, cctemp);
2109 if (rv) goto finish;
2110 #if defined(__APPLE__) && defined(RANLIB)
2111 /* From the Apple libtool(1) manpage on Tiger/10.4:
2112 * ----
2113 * With the way libraries used to be created, errors were possible
2114 * if the library was modified with ar(1) and the table of
2115 * contents was not updated by rerunning ranlib(1). Thus the
2116 * link editor, ld, warns when the modification date of a library
2117 * is more recent than the creation date of its table of
2118 * contents. Unfortunately, this means that you get the warning
2119 * even if you only copy the library.
2120 * ----
2121 *
2122 * This means that when we install the static archive, we need to
2123 * rerun ranlib afterwards.
2124 */
2125 char const *lib_args[3], *static_lib_name;
2126
2127 {
2128 char *tmp;
2129 size_t len1, len2;
2130
2131 len1 = strlen(cmd->arglist->vals[cmd->arglist->num - 1]);
2132
2133 static_lib_name = file_name(cmd->static_name.install);
2134 len2 = strlen(static_lib_name);
2135
2136 tmp = lt_malloc(len1 + len2 + 2);
2137
2138 snprintf(tmp, len1 + len2 + 2, "%s/%s",
2139 cmd->arglist->vals[cmd->arglist->num - 1],
2140 static_lib_name);
2141
2142 lib_args[0] = RANLIB;
2143 lib_args[1] = tmp;
2144 lib_args[2] = NULL;
2145
2146 external_spawn(cmd, RANLIB, lib_args);
2147
2148 free(tmp);
2149 }
2150 #endif
2151 clear_count_chars(cctemp);
2152 }
2153 if (cmd->shared_name.install) {
2154 append_count_chars(cctemp, cmd->arglist);
2155 insert_count_chars(cctemp, cmd->shared_name.install,
2156 cctemp->num - 1);
2157 rv = run_command(cmd, cctemp);
2158 if (rv) goto finish;
2159 clear_count_chars(cctemp);
2160 }
2161 if (cmd->module_name.install) {
2162 append_count_chars(cctemp, cmd->arglist);
2163 insert_count_chars(cctemp, cmd->module_name.install,
2164 cctemp->num - 1);
2165 rv = run_command(cmd, cctemp);
2166 if (rv) goto finish;
2167 clear_count_chars(cctemp);
2168 }
2169 break;
2170 case MODE_LINK:
2171 if (cmd->output == OUT_STATIC_LIB_ONLY ||
2172 cmd->output == OUT_LIB) {
2173 #ifdef RANLIB
2174 char const *lib_args[3];
2175 #endif
2176 /* Removes compiler! */
2177 cmd->program = LIBRARIAN;
2178 push_count_chars(cmd->program_opts, LIBRARIAN_OPTS);
2179 push_count_chars(cmd->program_opts, cmd->static_name.normal);
2180
2181 rv = run_command(cmd, cmd->obj_files);
2182 if (rv) goto finish;
2183
2184 #ifdef RANLIB
2185 lib_args[0] = RANLIB;
2186 lib_args[1] = cmd->static_name.normal;
2187 lib_args[2] = NULL;
2188 external_spawn(cmd, RANLIB, lib_args);
2189 #endif
2190 }
2191
2192 if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
2193 cmd->output == OUT_MODULE ||
2194 cmd->output == OUT_LIB) {
2195 cmd->program = NULL;
2196 clear_count_chars(cmd->program_opts);
2197
2198 append_count_chars(cmd->program_opts, cmd->arglist);
2199 if (cmd->output == OUT_MODULE) {
2200 #ifdef MODULE_OPTS
2201 push_count_chars(cmd->program_opts, MODULE_OPTS);
2202 #endif
2203 } else {
2204 #ifdef SHARED_OPTS
2205 push_count_chars(cmd->program_opts, SHARED_OPTS);
2206 #endif
2207 #ifdef dynamic_link_version_func
2208 push_count_chars(cmd->program_opts,
2209 dynamic_link_version_func(cmd->version_info));
2210 #endif
2211 }
2212 add_dynamic_link_opts(cmd, cmd->program_opts);
2213
2214 rv = run_command(cmd, cmd->shared_opts.normal);
2215 if (rv) goto finish;
2216 }
2217 if (cmd->output == OUT_PROGRAM) {
2218 rv = run_command(cmd, cmd->arglist);
2219 if (rv) goto finish;
2220 }
2221 break;
2222 case MODE_EXECUTE:
2223 {
2224 char *l, libpath[PATH_MAX];
2225
2226 if (!cmd->arglist->num) {
2227 ERROR("No command to execute.\n");
2228 rv = 1;
2229
2230 goto finish;
2231 }
2232
2233 if (strlen(cmd->arglist->vals[0]) >= PATH_MAX) {
2234 ERROR("Libpath too long no buffer space\n");
2235 rv = 1;
2236
2237 goto finish;
2238 }
2239
2240 strcpy(libpath, cmd->arglist->vals[0]);
2241 add_dotlibs(libpath);
2242 l = strrchr(libpath, '/');
2243 if (!l) l = strrchr(libpath, '\\');
2244 if (l) {
2245 *l = '\0';
2246 l = libpath;
2247 } else {
2248 l = ".libs/";
2249 }
2250
2251 l = "./build/lib/.libs";
2252 setenv(LD_LIBRARY_PATH_LOCAL, l, 1);
2253 #ifdef __APPLE__
2254 setenv("DYLD_FALLBACK_LIBRARY_PATH", l, 1);
2255 #endif
2256 setenv("FR_LIBRARY_PATH", "./build/lib/local/.libs", 1);
2257 rv = run_command(cmd, cmd->arglist);
2258 if (rv) goto finish;
2259 }
2260 break;
2261
2262 default:
2263 break;
2264 }
2265
2266 finish:
2267
2268 free(cctemp);
2269 return rv;
2270 }
2271
2272 static void cleanup_tmp_dir(char const *dirname)
2273 {
2274 DIR *dir;
2275 struct dirent *entry;
2276 char fullname[1024];
2277
2278 dir = opendir(dirname);
2279 if (!dir) {
2280 return;
2281 }
2282
2283 if ((strlen(dirname) + 1 + sizeof(entry->d_name)) >= sizeof(fullname)) {
2284 ERROR("Dirname too long, out of buffer space\n");
2285
2286 (void) closedir(dir);
2287 return;
2288 }
2289
2290 while ((entry = readdir(dir)) != NULL) {
2291 if (entry->d_name[0] != '.') {
2292 strcpy(fullname, dirname);
2293 strcat(fullname, "/");
2294 strcat(fullname, entry->d_name);
2295 (void) remove(fullname);
2296 }
2297 }
2298
2299 rmdir(dirname);
2300
2301 (void) closedir(dir);
2302 }
2303
2304 static void cleanup_tmp_dirs(command_t *cmd)
2305 {
2306 int d;
2307
2308 for (d = 0; d < cmd->tmp_dirs->num; d++) {
2309 cleanup_tmp_dir(cmd->tmp_dirs->vals[d]);
2310 }
2311 }
2312
2313 static int ensure_fake_uptodate(command_t *cmd)
2314 {
2315 /* FIXME: could do the stat/touch here, but nah... */
2316 char const *touch_args[3];
2317
2318 if (cmd->mode == MODE_INSTALL) {
2319 return 0;
2320 }
2321 if (!cmd->fake_output_name) {
2322 return 0;
2323 }
2324
2325 touch_args[0] = "touch";
2326 touch_args[1] = cmd->fake_output_name;
2327 touch_args[2] = NULL;
2328 return external_spawn(cmd, "touch", touch_args);
2329 }
2330
2331 /* Store the install path in the *.la file */
2332 static int add_for_runtime(command_t *cmd)
2333 {
2334 if (cmd->mode == MODE_INSTALL) {
2335 return 0;
2336 }
2337 if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
2338 cmd->output == OUT_LIB) {
2339 FILE *f=fopen(cmd->fake_output_name,"w");
2340 if (f == NULL) {
2341 return -1;
2342 }
2343 fprintf(f,"%s\n", cmd->install_path);
2344 fclose(f);
2345 return(0);
2346 } else {
2347 return(ensure_fake_uptodate(cmd));
2348 }
2349 }
2350
2351 static void parse_args(int argc, char *argv[], command_t *cmd)
2352 {
2353 int a;
2354 char const *arg, *base;
2355 int arg_used;
2356
2357 /*
2358 * We now take a major step past libtool.
2359 *
2360 * IF there's no "--mode=...", AND we recognise
2361 * the binary as a "special" name, THEN replace it
2362 * with the correct one, and set the correct mode.
2363 *
2364 * For example if were called 'CC' then we know we should
2365 * probably be compiling stuff.
2366 */
2367 base = file_name(argv[0]);
2368 arg = automode(base, cmd);
2369 if (arg != base) {
2370 push_count_chars(cmd->arglist, arg);
2371
2372 assert(cmd->mode != MODE_UNKNOWN);
2373 }
2374
2375 /*
2376 * We first pass over the command-line arguments looking for
2377 * "--mode", etc. If so, then use the libtool compatibility
2378 * method for building the software. Otherwise, auto-detect it
2379 * via "-o" and the extensions.
2380 */
2381 base = NULL;
2382 if (cmd->mode == MODE_UNKNOWN) for (a = 1; a < argc; a++) {
2383 arg = argv[a];
2384
2385 if (strncmp(arg, "--mode=", 7) == 0) {
2386 base = NULL;
2387 break;
2388 }
2389
2390 /*
2391 * Stop if we get another magic method
2392 */
2393 if ((a == 1) &&
2394 ((strncmp(arg, "LINK", 4) == 0) ||
2395 (strcmp(arg, "CC") == 0) ||
2396 (strcmp(arg, "CXX") == 0))) {
2397 base = NULL;
2398 break;
2399 }
2400
2401 if (strncmp(arg, "-o", 2) == 0) {
2402 base = argv[++a];
2403 }
2404 }
2405
2406 /*
2407 * There were no magic args or an explicit --mode= but we did
2408 * find an output file, so guess what mode were meant to be in
2409 * from its extension.
2410 */
2411 if (base) {
2412 arg = strrchr(base, '.');
2413 if (!arg) {
2414 cmd->mode = MODE_LINK;
2415 push_count_chars(cmd->arglist, LINK_C);
2416 }
2417 #ifdef EXE_EXT
2418 else if (strcmp(arg, EXE_EXT) == 0) {
2419 cmd->mode = MODE_LINK;
2420 push_count_chars(cmd->arglist, LINK_C);
2421 }
2422 #endif
2423 else if (strcmp(arg + 1, DYNAMIC_LIB_EXT) == 0) {
2424 cmd->mode = MODE_LINK;
2425 push_count_chars(cmd->arglist, LINK_C);
2426 }
2427 else if (strcmp(arg + 1, STATIC_LIB_EXT) == 0) {
2428 cmd->mode = MODE_LINK;
2429 push_count_chars(cmd->arglist, LINK_C);
2430 }
2431 else if (strcmp(arg + 1, "la") == 0) {
2432 cmd->mode = MODE_LINK;
2433 push_count_chars(cmd->arglist, LINK_C);
2434 }
2435 else if ((strcmp(arg + 1, "lo") == 0) ||
2436 (strcmp(arg + 1, "o") == 0)) {
2437 cmd->mode = MODE_COMPILE;
2438 push_count_chars(cmd->arglist, CC);
2439 }
2440 }
2441
2442 for (a = 1; a < argc; a++) {
2443 arg = argv[a];
2444 arg_used = 1;
2445
2446 if (cmd->mode == MODE_EXECUTE) {
2447 push_count_chars(cmd->arglist, arg);
2448 continue;
2449 }
2450
2451 if (arg[0] == '-') {
2452 /*
2453 * Double dashed (long) single dash (short)
2454 */
2455 arg_used = (arg[1] == '-') ?
2456 parse_long_opt(arg + 2, cmd) :
2457 parse_short_opt(arg + 1, cmd);
2458
2459 if (arg_used) continue;
2460
2461 /*
2462 * Ignore all options after the '--execute'
2463 */
2464 if (cmd->mode == MODE_EXECUTE) continue;
2465
2466 /*
2467 * We haven't done anything with it yet, but
2468 * there are still some arg/value pairs.
2469 *
2470 * Try some of the more complicated short opts...
2471 */
2472 if (a + 1 < argc) {
2473 /*
2474 * We found an output file!
2475 */
2476 if ((arg[1] == 'o') && (arg[2] == '\0')) {
2477 arg = argv[++a];
2478 arg_used = parse_output_file_name(arg,
2479 cmd);
2480 /*
2481 * -MT literal dependency
2482 */
2483 } else if (!strcmp(arg + 1, "MT")) {
2484 DEBUG("Adding: %s\n", arg);
2485
2486 push_count_chars(cmd->arglist, arg);
2487 arg = argv[++a];
2488
2489 NOTICE(" %s\n", arg);
2490
2491 push_count_chars(cmd->arglist, arg);
2492 arg_used = 1;
2493 /*
2494 * Runtime library search path
2495 */
2496 } else if (!strcmp(arg + 1, "rpath")) {
2497 /* Aha, we should try to link both! */
2498 cmd->install_path = argv[++a];
2499 arg_used = 1;
2500
2501 } else if (!strcmp(arg + 1, "release")) {
2502 /* Store for later deciphering */
2503 cmd->version_info = argv[++a];
2504 arg_used = 1;
2505
2506 } else if (!strcmp(arg + 1, "version-info")) {
2507 /* Store for later deciphering */
2508 cmd->version_info = argv[++a];
2509 arg_used = 1;
2510
2511 } else if (!strcmp(arg + 1,
2512 "export-symbols-regex")) {
2513 /* Skip the argument. */
2514 ++a;
2515 arg_used = 1;
2516
2517 } else if (!strcmp(arg + 1, "undefined")) {
2518 cmd->undefined_flag = argv[++a];
2519 arg_used = 1;
2520 /*
2521 * Add dir to runtime library search path.
2522 */
2523 } else if ((arg[1] == 'R') && !arg[2]) {
2524
2525 add_runtime_dir_lib(argv[++a], cmd);
2526 arg_used = 1;
2527 }
2528 }
2529 /*
2530 * Ok.. the argument doesn't begin with a dash
2531 * maybe it's an input file.
2532 *
2533 * Check its extension to see if it's a known input
2534 * file and verify it exists.
2535 */
2536 } else {
2537 arg_used = parse_input_file_name(arg, cmd);
2538 }
2539
2540 /*
2541 * If we still don't have a run mode, look for a magic
2542 * program name CC, LINK, or whatever. Then replace that
2543 * with the name of the real program we want to run.
2544 */
2545 if (!arg_used) {
2546 if ((cmd->arglist->num == 0) &&
2547 (cmd->mode == MODE_UNKNOWN)) {
2548 arg = automode(arg, cmd);
2549 }
2550
2551 DEBUG("Adding: %s\n", arg);
2552
2553 push_count_chars(cmd->arglist, arg);
2554 }
2555 }
2556
2557 }
2558
2559 int main(int argc, char *argv[])
2560 {
2561 int rc;
2562 command_t cmd;
2563
2564 memset(&cmd, 0, sizeof(cmd));
2565
2566 cmd.options.pic_mode = PIC_UNKNOWN;
2567 cmd.mode = MODE_UNKNOWN;
2568 cmd.output = OUT_GENERAL;
2569
2570 /*
2571 * Initialise the various argument lists
2572 */
2573 cmd.program_opts = alloc_countchars();
2574 cmd.arglist = alloc_countchars();
2575 cmd.tmp_dirs = alloc_countchars();
2576 cmd.obj_files = alloc_countchars();
2577 cmd.dep_rpaths = alloc_countchars();
2578 cmd.rpaths = alloc_countchars();
2579 cmd.static_opts.normal = alloc_countchars();
2580 cmd.shared_opts.normal = alloc_countchars();
2581 cmd.shared_opts.dependencies = alloc_countchars();
2582
2583 /*
2584 * Fill up the various argument lists
2585 */
2586 parse_args(argc, argv, &cmd);
2587 post_parse_fixup(&cmd);
2588
2589 /*
2590 * We couldn't figure out which mode to operate in
2591 */
2592 if (cmd.mode == MODE_UNKNOWN) {
2593 usage(1);
2594 }
2595
2596 rc = run_mode(&cmd);
2597 if (!rc) {
2598 add_for_runtime(&cmd);
2599 }
2600
2601 cleanup_tmp_dirs(&cmd);
2602
2603 return rc;
2604 }
2605