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 <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #ifdef __EMX__
29 # define SHELL_CMD "sh"
30 # define GEN_EXPORTS "emxexp"
31 # define DEF2IMPLIB_CMD "emximp"
32 # define SHARE_SW "-Zdll -Zmtd"
33 # define USE_OMF 1
34 # define TRUNCATE_DLL_NAME
35 # define DYNAMIC_LIB_EXT "dll"
36 # define EXE_EXT ".exe"
37
38 # if USE_OMF
39 /* OMF is the native format under OS/2 */
40 # define STATIC_LIB_EXT "lib"
41 # define OBJECT_EXT "obj"
42 # define LIBRARIAN "emxomfar"
43 # define LIBRARIAN_OPTS "cr"
44 # else
45 /* but the alternative, a.out, can fork() which is sometimes necessary */
46 # define STATIC_LIB_EXT "a"
47 # define OBJECT_EXT "o"
48 # define LIBRARIAN "ar"
49 # define LIBRARIAN_OPTS "cr"
50 # endif
51 #endif
52
53 #if defined(__APPLE__)
54 # define SHELL_CMD "/bin/sh"
55 # define DYNAMIC_LIB_EXT "dylib"
56 # define MODULE_LIB_EXT "so"
57 # define STATIC_LIB_EXT "a"
58 # define OBJECT_EXT "o"
59 # define LIBRARIAN "ar"
60 # define LIBRARIAN_OPTS "cr"
61 /* man libtool(1) documents ranlib option of -c. */
62 # define RANLIB "ranlib"
63 # define PIC_FLAG "-fPIC -fno-common"
64 # define SHARED_OPTS "-dynamiclib"
65 # define MODULE_OPTS "-bundle"
66 # define DYNAMIC_LINK_OPTS "-flat_namespace -undefined suppress"
67 # define dynamic_link_version_func darwin_dynamic_link_function
68 # define DYNAMIC_INSTALL_NAME "-install_name"
69 # define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
70 # define HAS_REALPATH
71 /*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
72 # define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
73 #endif
74
75 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
76 # define SHELL_CMD "/bin/sh"
77 # define DYNAMIC_LIB_EXT "so"
78 # define MODULE_LIB_EXT "so"
79 # define STATIC_LIB_EXT "a"
80 # define OBJECT_EXT "o"
81 # define LIBRARIAN "ar"
82 # define LIBRARIAN_OPTS "cr"
83 # define RANLIB "ranlib"
84 # define PIC_FLAG "-fPIC"
85 # define RPATH "-rpath"
86 # define SHARED_OPTS "-shared"
87 # define MODULE_OPTS "-shared"
88 # define DYNAMIC_LINK_OPTS "-export-dynamic"
89 # define LINKER_FLAG_PREFIX "-Wl,"
90 # define ADD_MINUS_L
91 # define LD_RUN_PATH "LD_RUN_PATH"
92 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
93 #endif
94
95 #if defined(sun)
96 # define SHELL_CMD "/bin/sh"
97 # define DYNAMIC_LIB_EXT "so"
98 # define MODULE_LIB_EXT "so"
99 # define STATIC_LIB_EXT "a"
100 # define OBJECT_EXT "o"
101 # define LIBRARIAN "ar"
102 # define LIBRARIAN_OPTS "cr"
103 # define RANLIB "ranlib"
104 # define PIC_FLAG "-KPIC"
105 # define RPATH "-R"
106 # define SHARED_OPTS "-G"
107 # define MODULE_OPTS "-G"
108 # define DYNAMIC_LINK_OPTS ""
109 # define LINKER_FLAG_NO_EQUALS
110 # define ADD_MINUS_L
111 # define HAS_REALPATH
112 # define LD_RUN_PATH "LD_RUN_PATH"
113 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
114 #endif
115
116 #if defined(_OSD_POSIX)
117 # define SHELL_CMD "/usr/bin/sh"
118 # define DYNAMIC_LIB_EXT "so"
119 # define MODULE_LIB_EXT "so"
120 # define STATIC_LIB_EXT "a"
121 # define OBJECT_EXT "o"
122 # define LIBRARIAN "ar"
123 # define LIBRARIAN_OPTS "cr"
124 # define SHARED_OPTS "-G"
125 # define MODULE_OPTS "-G"
126 # define LINKER_FLAG_PREFIX "-Wl,"
127 # define NEED_SNPRINTF
128 #endif
129
130 #if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
131 # define SHELL_CMD "/usr/bin/sh"
132 # define DYNAMIC_LIB_EXT "so"
133 # define MODULE_LIB_EXT "so"
134 # define STATIC_LIB_EXT "a"
135 # define OBJECT_EXT "o"
136 # define LIBRARIAN "ar"
137 # define LIBRARIAN_OPTS "cr"
138 # define RPATH "-Brpath"
139 # define SHARED_OPTS "-G"
140 # define MODULE_OPTS "-G"
141 # define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
142 # define LINKER_FLAG_PREFIX "-Wl,"
143 # define NEED_SNPRINTF
144 # define LD_RUN_PATH "LD_RUN_PATH"
145 # define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
146 #endif
147
148 #ifndef SHELL_CMD
149 #error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
150 #endif
151
152 #ifdef NEED_SNPRINTF
153 #include <stdarg.h>
154 #endif
155
156 #ifdef __EMX__
157 #include <process.h>
158 #endif
159
160 #ifndef PATH_MAX
161 #define PATH_MAX 1024
162 #endif
163
164
165 /* We want to say we are libtool 1.4 for shlibtool compatibility. */
166 #define VERSION "1.4"
167
168 enum tool_mode_t {
169 mUnknown,
170 mCompile,
171 mLink,
172 mInstall,
173 };
174
175 enum output_t {
176 otGeneral,
177 otObject,
178 otProgram,
179 otLibrary,
180 otStaticLibraryOnly,
181 otDynamicLibraryOnly,
182 otModule,
183 };
184
185 enum pic_mode_e {
186 pic_UNKNOWN,
187 pic_PREFER,
188 pic_AVOID,
189 };
190
191 enum lib_type {
192 type_UNKNOWN,
193 type_DYNAMIC_LIB,
194 type_STATIC_LIB,
195 type_MODULE_LIB,
196 type_OBJECT,
197 };
198
199 typedef struct {
200 const char **vals;
201 int num;
202 } count_chars;
203
204 typedef struct {
205 const char *normal;
206 const char *install;
207 } library_name;
208
209 typedef struct {
210 count_chars *normal;
211 count_chars *install;
212 count_chars *dependencies;
213 } library_opts;
214
215 typedef struct {
216 int silent;
217 int shared;
218 int export_all;
219 int dry_run;
220 enum pic_mode_e pic_mode;
221 int export_dynamic;
222 int no_install;
223 } options_t;
224
225 typedef struct {
226 enum tool_mode_t mode;
227 enum output_t output;
228 options_t options;
229
230 char *output_name;
231 char *fake_output_name;
232 char *basename;
233
234 const char *install_path;
235 const char *compiler;
236 const char *program;
237 count_chars *program_opts;
238
239 count_chars *arglist;
240 count_chars *tmp_dirs;
241 count_chars *obj_files;
242 count_chars *dep_rpaths;
243 count_chars *rpaths;
244
245 library_name static_name;
246 library_name shared_name;
247 library_name module_name;
248
249 library_opts static_opts;
250 library_opts shared_opts;
251
252 const char *version_info;
253 } command_t;
254
255 #ifdef RPATH
256 void add_rpath(count_chars *cc, const char *path);
257 #endif
258
259 #if defined(NEED_SNPRINTF)
260 /* Write at most n characters to the buffer in str, return the
261 * number of chars written or -1 if the buffer would have been
262 * overflowed.
263 *
264 * This is portable to any POSIX-compliant system has /dev/null
265 */
266 static FILE *f=NULL;
vsnprintf(char * str,size_t n,const char * fmt,va_list ap)267 static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
268 {
269 int res;
270
271 if (f == NULL)
272 f = fopen("/dev/null","w");
273 if (f == NULL)
274 return -1;
275
276 setvbuf( f, str, _IOFBF, n );
277
278 res = vfprintf( f, fmt, ap );
279
280 if ( res > 0 && res < n ) {
281 res = vsprintf( str, fmt, ap );
282 }
283 return res;
284 }
snprintf(char * str,size_t n,const char * fmt,...)285 static int snprintf( char *str, size_t n, const char *fmt, ... )
286 {
287 va_list ap;
288 int res;
289
290 va_start( ap, fmt );
291 res = vsnprintf( str, n, fmt, ap );
292 va_end( ap );
293 return res;
294 }
295 #endif
296
init_count_chars(count_chars * cc)297 void init_count_chars(count_chars *cc)
298 {
299 cc->vals = (const char**)malloc(PATH_MAX);
300 cc->num = 0;
301 }
302
clear_count_chars(count_chars * cc)303 void clear_count_chars(count_chars *cc)
304 {
305 int i;
306 for (i = 0; i < cc->num; i++) {
307 cc->vals[i] = 0;
308 }
309
310 cc->num = 0;
311 }
312
push_count_chars(count_chars * cc,const char * newval)313 void push_count_chars(count_chars *cc, const char *newval)
314 {
315 cc->vals[cc->num++] = newval;
316 }
317
insert_count_chars(count_chars * cc,const char * newval,int position)318 void insert_count_chars(count_chars *cc, const char *newval, int position)
319 {
320 int i;
321
322 for (i = cc->num; i > position; i--) {
323 cc->vals[i] = cc->vals[i-1];
324 }
325
326 cc->vals[position] = newval;
327 cc->num++;
328 }
329
append_count_chars(count_chars * cc,count_chars * cctoadd)330 void append_count_chars(count_chars *cc, count_chars *cctoadd)
331 {
332 int i;
333 for (i = 0; i < cctoadd->num; i++) {
334 if (cctoadd->vals[i]) {
335 push_count_chars(cc, cctoadd->vals[i]);
336 }
337 }
338 }
339
flatten_count_chars(count_chars * cc)340 const char *flatten_count_chars(count_chars *cc)
341 {
342 int i, size;
343 char *newval;
344
345 size = 0;
346 for (i = 0; i < cc->num; i++) {
347 if (cc->vals[i]) {
348 size += strlen(cc->vals[i]) + 1;
349 }
350 }
351
352 newval = (char*)malloc(size + 1);
353 newval[0] = 0;
354
355 for (i = 0; i < cc->num; i++) {
356 if (cc->vals[i]) {
357 strcat(newval, cc->vals[i]);
358 strcat(newval, " ");
359 }
360 }
361
362 return newval;
363 }
364
shell_esc(const char * str)365 char *shell_esc(const char *str)
366 {
367 int in_quote = 0;
368 char *cmd;
369 unsigned char *d;
370 const unsigned char *s;
371
372 cmd = (char *)malloc(2 * strlen(str) + 1);
373 d = (unsigned char *)cmd;
374 s = (const unsigned char *)str;
375
376 for (; *s; ++s) {
377 if (*s == '"') {
378 *d++ = '\\';
379 in_quote++;
380 }
381 else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
382 *d++ = '\\';
383 }
384 *d++ = *s;
385 }
386
387 *d = '\0';
388 return cmd;
389 }
390
external_spawn(command_t * cmd,const char * file,const char ** argv)391 int external_spawn(command_t *cmd, const char *file, const char **argv)
392 {
393 if (!cmd->options.silent) {
394 const char **argument = argv;
395 printf("Executing: ");
396 while (*argument) {
397 printf("%s ", *argument);
398 argument++;
399 }
400 puts("");
401 }
402
403 if (cmd->options.dry_run) {
404 return 0;
405 }
406 #ifdef __EMX__
407 return spawnvp(P_WAIT, file, argv);
408 #else
409 {
410 pid_t pid;
411 pid = fork();
412 if (pid == 0) {
413 return execvp(argv[0], (char**)argv);
414 }
415 else {
416 int statuscode;
417 waitpid(pid, &statuscode, 0);
418 if (WIFEXITED(statuscode)) {
419 return WEXITSTATUS(statuscode);
420 }
421 return 0;
422 }
423 }
424 #endif
425 }
426
run_command(command_t * cmd_data,count_chars * cc)427 int run_command(command_t *cmd_data, count_chars *cc)
428 {
429 char *command;
430 const char *spawn_args[4];
431 count_chars tmpcc;
432
433 init_count_chars(&tmpcc);
434
435 if (cmd_data->program) {
436 push_count_chars(&tmpcc, cmd_data->program);
437 }
438
439 append_count_chars(&tmpcc, cmd_data->program_opts);
440
441 append_count_chars(&tmpcc, cc);
442
443 command = shell_esc(flatten_count_chars(&tmpcc));
444
445 spawn_args[0] = SHELL_CMD;
446 spawn_args[1] = "-c";
447 spawn_args[2] = command;
448 spawn_args[3] = NULL;
449 return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
450 }
451
452 /*
453 * print configuration
454 * shlibpath_var is used in configure.
455 */
print_config()456 void print_config()
457 {
458 #ifdef LD_RUN_PATH
459 printf("runpath_var=%s\n", LD_RUN_PATH);
460 #endif
461 #ifdef LD_LIBRARY_PATH
462 printf("shlibpath_var=%s\n", LD_LIBRARY_PATH);
463 #endif
464 #ifdef SHELL_CMD
465 printf("SHELL=\"%s\"\n", SHELL_CMD);
466 #endif
467 }
468 /*
469 * Add a directory to the runtime library search path.
470 */
add_runtimedirlib(char * arg,command_t * cmd_data)471 void add_runtimedirlib(char *arg, command_t *cmd_data)
472 {
473 #ifdef RPATH
474 add_rpath(cmd_data->shared_opts.dependencies, arg);
475 #else
476 #endif
477 }
478
parse_long_opt(char * arg,command_t * cmd_data)479 int parse_long_opt(char *arg, command_t *cmd_data)
480 {
481 char *equal_pos = strchr(arg, '=');
482 char var[50];
483 char value[500];
484
485 if (equal_pos) {
486 strncpy(var, arg, equal_pos - arg);
487 var[equal_pos - arg] = 0;
488 strcpy(value, equal_pos + 1);
489 } else {
490 strcpy(var, arg);
491 }
492
493 if (strcmp(var, "silent") == 0) {
494 cmd_data->options.silent = 1;
495 } else if (strcmp(var, "mode") == 0) {
496 if (strcmp(value, "compile") == 0) {
497 cmd_data->mode = mCompile;
498 cmd_data->output = otObject;
499 }
500
501 if (strcmp(value, "link") == 0) {
502 cmd_data->mode = mLink;
503 cmd_data->output = otLibrary;
504 }
505
506 if (strcmp(value, "install") == 0) {
507 cmd_data->mode = mInstall;
508 }
509 } else if (strcmp(var, "shared") == 0) {
510 if (cmd_data->mode == mLink) {
511 cmd_data->output = otDynamicLibraryOnly;
512 }
513 cmd_data->options.shared = 1;
514 } else if (strcmp(var, "export-all") == 0) {
515 cmd_data->options.export_all = 1;
516 } else if (strcmp(var, "dry-run") == 0) {
517 printf("Dry-run mode on!\n");
518 cmd_data->options.dry_run = 1;
519 } else if (strcmp(var, "version") == 0) {
520 printf("Version " VERSION "\n");
521 } else if (strcmp(var, "help") == 0) {
522 printf("Sorry. No help available.\n");
523 } else if (strcmp(var, "config") == 0) {
524 print_config();
525 } else if (strcmp(var, "tag") == 0) {
526 if (strcmp(value, "CC") == 0) {
527 /* Do nothing. */
528 }
529 if (strcmp(value, "CXX") == 0) {
530 /* Do nothing. */
531 }
532 } else {
533 return 0;
534 }
535
536 return 1;
537 }
538
539 /* Return 1 if we eat it. */
parse_short_opt(char * arg,command_t * cmd_data)540 int parse_short_opt(char *arg, command_t *cmd_data)
541 {
542 if (strcmp(arg, "export-dynamic") == 0) {
543 cmd_data->options.export_dynamic = 1;
544 return 1;
545 }
546
547 if (strcmp(arg, "module") == 0) {
548 cmd_data->output = otModule;
549 return 1;
550 }
551
552 if (strcmp(arg, "Zexe") == 0) {
553 return 1;
554 }
555
556 if (strcmp(arg, "avoid-version") == 0) {
557 return 1;
558 }
559
560 if (strcmp(arg, "prefer-pic") == 0) {
561 cmd_data->options.pic_mode = pic_PREFER;
562 return 1;
563 }
564
565 if (strcmp(arg, "prefer-non-pic") == 0) {
566 cmd_data->options.pic_mode = pic_AVOID;
567 return 1;
568 }
569
570 if (strcmp(arg, "static") == 0) {
571 /* Don't respect it for now. */
572 return 1;
573 }
574
575 if (cmd_data->mode == mLink) {
576 if (strcmp(arg, "no-install") == 0) {
577 cmd_data->options.no_install = 1;
578 return 1;
579 }
580 if (arg[0] == 'L' || arg[0] == 'l') {
581 /* Hack... */
582 arg--;
583 push_count_chars(cmd_data->shared_opts.dependencies, arg);
584 return 1;
585 } else if (arg[0] == 'R' && arg[1]) {
586 /* -Rdir Add dir to runtime library search path. */
587 add_runtimedirlib(&arg[1], cmd_data);
588 return 1;
589 }
590 }
591 return 0;
592 }
593
truncate_dll_name(char * path)594 char *truncate_dll_name(char *path)
595 {
596 /* Cut DLL name down to 8 characters after removing any mod_ prefix */
597 char *tmppath = strdup(path);
598 char *newname = strrchr(tmppath, '/') + 1;
599 char *ext = strrchr(tmppath, '.');
600 int len;
601
602 if (ext == NULL)
603 return tmppath;
604
605 len = ext - newname;
606
607 if (strncmp(newname, "mod_", 4) == 0) {
608 strcpy(newname, newname + 4);
609 len -= 4;
610 }
611
612 if (len > 8) {
613 strcpy(newname + 8, strchr(newname, '.'));
614 }
615
616 return tmppath;
617 }
618
safe_strtol(const char * nptr,const char ** endptr,int base)619 long safe_strtol(const char *nptr, const char **endptr, int base)
620 {
621 long rv;
622
623 errno = 0;
624
625 rv = strtol(nptr, (char**)endptr, 10);
626
627 if (errno == ERANGE) {
628 return 0;
629 }
630
631 return rv;
632 }
633
634 /* version_info is in the form of MAJOR:MINOR:PATCH */
darwin_dynamic_link_function(const char * version_info)635 const char *darwin_dynamic_link_function(const char *version_info)
636 {
637 char *newarg;
638 long major, minor, patch;
639
640 major = 0;
641 minor = 0;
642 patch = 0;
643
644 if (version_info) {
645 major = safe_strtol(version_info, &version_info, 10);
646
647 if (version_info) {
648 if (version_info[0] == ':') {
649 version_info++;
650 }
651
652 minor = safe_strtol(version_info, &version_info, 10);
653
654 if (version_info) {
655 if (version_info[0] == ':') {
656 version_info++;
657 }
658
659 patch = safe_strtol(version_info, &version_info, 10);
660
661 }
662 }
663 }
664
665 /* Avoid -dylib_compatibility_version must be greater than zero errors. */
666 if (major == 0) {
667 major = 1;
668 }
669 newarg = (char*)malloc(100);
670 snprintf(newarg, 99,
671 "-compatibility_version %ld -current_version %ld.%ld",
672 major, major, minor);
673
674 return newarg;
675 }
676
677 /* genlib values
678 * 0 - static
679 * 1 - dynamic
680 * 2 - module
681 */
gen_library_name(const char * name,int genlib)682 char *gen_library_name(const char *name, int genlib)
683 {
684 char *newarg, *newext;
685
686 newarg = (char *)malloc(strlen(name) + 10);
687 strcpy(newarg, ".libs/");
688
689 if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
690 name += 3;
691 }
692
693 strcat(newarg, name);
694
695 newext = strrchr(newarg, '.') + 1;
696
697 switch (genlib) {
698 case 0:
699 strcpy(newext, STATIC_LIB_EXT);
700 break;
701 case 1:
702 strcpy(newext, DYNAMIC_LIB_EXT);
703 break;
704 case 2:
705 strcpy(newext, MODULE_LIB_EXT);
706 break;
707 }
708
709 return newarg;
710 }
711
712 /* genlib values
713 * 0 - static
714 * 1 - dynamic
715 * 2 - module
716 */
gen_install_name(const char * name,int genlib)717 char *gen_install_name(const char *name, int genlib)
718 {
719 struct stat sb;
720 char *newname;
721 int rv;
722
723 newname = gen_library_name(name, genlib);
724
725 /* Check if it exists. If not, return NULL. */
726 rv = stat(newname, &sb);
727
728 if (rv) {
729 return NULL;
730 }
731
732 return newname;
733 }
734
check_object_exists(command_t * cmd,const char * arg,int arglen)735 char *check_object_exists(command_t *cmd, const char *arg, int arglen)
736 {
737 char *newarg, *ext;
738 int pass, rv;
739
740 newarg = (char *)malloc(arglen + 10);
741 memcpy(newarg, arg, arglen);
742 newarg[arglen] = 0;
743 ext = newarg + arglen;
744
745 pass = 0;
746
747 do {
748 struct stat sb;
749
750 switch (pass) {
751 case 0:
752 strcpy(ext, OBJECT_EXT);
753 break;
754 /*
755 case 1:
756 strcpy(ext, NO_PIC_EXT);
757 break;
758 */
759 default:
760 break;
761 }
762
763 if (!cmd->options.silent) {
764 printf("Checking (obj): %s\n", newarg);
765 }
766 rv = stat(newarg, &sb);
767 }
768 while (rv != 0 && ++pass < 1);
769
770 if (rv == 0) {
771 if (pass == 1) {
772 cmd->options.pic_mode = pic_AVOID;
773 }
774 return newarg;
775 }
776
777 return NULL;
778 }
779
780 /* libdircheck values:
781 * 0 - no .libs suffix
782 * 1 - .libs suffix
783 */
check_library_exists(command_t * cmd,const char * arg,int pathlen,int libdircheck,enum lib_type * libtype)784 char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
785 int libdircheck, enum lib_type *libtype)
786 {
787 char *newarg, *ext;
788 int pass, rv, newpathlen;
789
790 newarg = (char *)malloc(strlen(arg) + 10);
791 strcpy(newarg, arg);
792 newarg[pathlen] = 0;
793
794 newpathlen = pathlen;
795 if (libdircheck) {
796 strcat(newarg, ".libs/");
797 newpathlen += sizeof(".libs/") - 1;
798 }
799
800 strcpy(newarg+newpathlen, arg+pathlen);
801 ext = strrchr(newarg, '.') + 1;
802
803 pass = 0;
804
805 do {
806 struct stat sb;
807
808 switch (pass) {
809 case 0:
810 if (cmd->options.pic_mode != pic_AVOID || cmd->options.shared) {
811 strcpy(ext, DYNAMIC_LIB_EXT);
812 *libtype = type_DYNAMIC_LIB;
813 break;
814 }
815 pass = 1;
816 case 1:
817 strcpy(ext, STATIC_LIB_EXT);
818 *libtype = type_STATIC_LIB;
819 break;
820 case 2:
821 strcpy(ext, MODULE_LIB_EXT);
822 *libtype = type_MODULE_LIB;
823 break;
824 case 3:
825 strcpy(ext, OBJECT_EXT);
826 *libtype = type_OBJECT;
827 break;
828 default:
829 *libtype = type_UNKNOWN;
830 break;
831 }
832
833 if (!cmd->options.silent) {
834 printf("Checking (lib): %s\n", newarg);
835 }
836 rv = stat(newarg, &sb);
837 }
838 while (rv != 0 && ++pass < 4);
839
840 if (rv == 0) {
841 return newarg;
842 }
843
844 return NULL;
845 }
846
load_install_path(const char * arg)847 char * load_install_path(const char *arg)
848 {
849 FILE *f;
850 char *path;
851
852 path = malloc(PATH_MAX);
853
854 f = fopen(arg,"r");
855 if (f == NULL) {
856 return NULL;
857 }
858 fgets(path, PATH_MAX, f);
859 fclose(f);
860 if (path[strlen(path)-1] == '\n') {
861 path[strlen(path)-1] = '\0';
862 }
863 /* Check that we have an absolute path.
864 * Otherwise the file could be a GNU libtool file.
865 */
866 if (path[0] != '/') {
867 return NULL;
868 }
869 return path;
870 }
871
load_noinstall_path(const char * arg,int pathlen)872 char * load_noinstall_path(const char *arg, int pathlen)
873 {
874 char *newarg, *expanded_path;
875 int newpathlen;
876
877 newarg = (char *)malloc(strlen(arg) + 10);
878 strcpy(newarg, arg);
879 newarg[pathlen] = 0;
880
881 newpathlen = pathlen;
882 strcat(newarg, ".libs");
883 newpathlen += sizeof(".libs") - 1;
884 newarg[newpathlen] = 0;
885
886 #ifdef HAS_REALPATH
887 expanded_path = malloc(PATH_MAX);
888 expanded_path = realpath(newarg, expanded_path);
889 /* Uh, oh. There was an error. Fall back on our first guess. */
890 if (!expanded_path) {
891 expanded_path = newarg;
892 }
893 #else
894 /* We might get ../ or something goofy. Oh, well. */
895 expanded_path = newarg;
896 #endif
897
898 return expanded_path;
899 }
900
901 /* Read the final install location and add it to runtime library search path. */
902 #ifdef RPATH
add_rpath(count_chars * cc,const char * path)903 void add_rpath(count_chars *cc, const char *path)
904 {
905 int size = 0;
906 char *tmp;
907
908 #ifdef LINKER_FLAG_PREFIX
909 size = strlen(LINKER_FLAG_PREFIX);
910 #endif
911 size = size + strlen(path) + strlen(RPATH) + 2;
912 tmp = malloc(size);
913 if (tmp == NULL) {
914 return;
915 }
916 #ifdef LINKER_FLAG_PREFIX
917 strcpy(tmp, LINKER_FLAG_PREFIX);
918 strcat(tmp, RPATH);
919 #else
920 strcpy(tmp, RPATH);
921 #endif
922 #ifndef LINKER_FLAG_NO_EQUALS
923 strcat(tmp, "=");
924 #endif
925 strcat(tmp, path);
926
927 push_count_chars(cc, tmp);
928 }
929
add_rpath_file(count_chars * cc,const char * arg)930 void add_rpath_file(count_chars *cc, const char *arg)
931 {
932 const char *path;
933
934 path = load_install_path(arg);
935 if (path) {
936 add_rpath(cc, path);
937 }
938 }
939
add_rpath_noinstall(count_chars * cc,const char * arg,int pathlen)940 void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
941 {
942 const char *path;
943
944 path = load_noinstall_path(arg, pathlen);
945 if (path) {
946 add_rpath(cc, path);
947 }
948 }
949 #endif
950
951 #ifdef DYNAMIC_LINK_NO_INSTALL
add_dylink_noinstall(count_chars * cc,const char * arg,int pathlen,int extlen)952 void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
953 int extlen)
954 {
955 const char *install_path, *current_path, *name;
956 char *exp_argument;
957 int i_p_len, c_p_len, name_len, dyext_len, cur_len;
958
959 install_path = load_install_path(arg);
960 current_path = load_noinstall_path(arg, pathlen);
961
962 if (!install_path || !current_path) {
963 return;
964 }
965
966 push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
967
968 i_p_len = strlen(install_path);
969 c_p_len = strlen(current_path);
970
971 name = arg+pathlen;
972 name_len = extlen-pathlen;
973 dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
974
975 /* No, we need to replace the extension. */
976 exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
977 (dyext_len*2) + 2);
978
979 cur_len = 0;
980 strcpy(exp_argument, install_path);
981 cur_len += i_p_len;
982 exp_argument[cur_len++] = '/';
983 strncpy(exp_argument+cur_len, name, extlen-pathlen);
984 cur_len += name_len;
985 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
986 cur_len += dyext_len;
987 exp_argument[cur_len++] = ':';
988 strcpy(exp_argument+cur_len, current_path);
989 cur_len += c_p_len;
990 exp_argument[cur_len++] = '/';
991 strncpy(exp_argument+cur_len, name, extlen-pathlen);
992 cur_len += name_len;
993 strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
994 cur_len += dyext_len;
995
996 push_count_chars(cc, exp_argument);
997 }
998 #endif
999
1000 /* use -L -llibname to allow to use installed libraries */
add_minus_l(count_chars * cc,const char * arg)1001 void add_minus_l(count_chars *cc, const char *arg)
1002 {
1003 char *newarg;
1004 char *name = strrchr(arg, '/');
1005 char *file = strrchr(arg, '.');
1006 char *lib = strstr(name, "lib");
1007
1008 if (name !=NULL && file != NULL && lib == name+1) {
1009 *name = '\0';
1010 *file = '\0';
1011 file = name;
1012 file = file+4;
1013 push_count_chars(cc, "-L");
1014 push_count_chars(cc, arg);
1015 /* we need one argument like -lapr-1 */
1016 newarg = malloc(strlen(file) + 3);
1017 strcpy(newarg, "-l");
1018 strcat(newarg, file);
1019 push_count_chars(cc, newarg);
1020 } else {
1021 push_count_chars(cc, arg);
1022 }
1023 }
1024
add_linker_flag_prefix(count_chars * cc,const char * arg)1025 void add_linker_flag_prefix(count_chars *cc, const char *arg)
1026 {
1027 #ifndef LINKER_FLAG_PREFIX
1028 push_count_chars(cc, arg);
1029 #else
1030 char *newarg;
1031 newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
1032 strcpy(newarg, LINKER_FLAG_PREFIX);
1033 strcat(newarg, arg);
1034 push_count_chars(cc, newarg);
1035 #endif
1036 }
1037
parse_input_file_name(char * arg,command_t * cmd_data)1038 int parse_input_file_name(char *arg, command_t *cmd_data)
1039 {
1040 char *ext = strrchr(arg, '.');
1041 char *name = strrchr(arg, '/');
1042 int pathlen;
1043 enum lib_type libtype;
1044 char *newarg;
1045
1046 if (!ext) {
1047 return 0;
1048 }
1049
1050 ext++;
1051
1052 if (name == NULL) {
1053 name = strrchr(arg, '\\');
1054
1055 if (name == NULL) {
1056 name = arg;
1057 } else {
1058 name++;
1059 }
1060 } else {
1061 name++;
1062 }
1063
1064 pathlen = name - arg;
1065
1066 if (strcmp(ext, "lo") == 0) {
1067 newarg = check_object_exists(cmd_data, arg, ext - arg);
1068 if (!newarg) {
1069 printf("Can not find suitable object file for %s\n", arg);
1070 exit(1);
1071 }
1072 if (cmd_data->mode != mLink) {
1073 push_count_chars(cmd_data->arglist, newarg);
1074 }
1075 else {
1076 push_count_chars(cmd_data->obj_files, newarg);
1077 }
1078 return 1;
1079 }
1080
1081 if (strcmp(ext, "la") == 0) {
1082 switch (cmd_data->mode) {
1083 case mLink:
1084 /* Try the .libs dir first! */
1085 newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
1086 if (!newarg) {
1087 /* Try the normal dir next. */
1088 newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
1089 if (!newarg) {
1090 printf("Can not find suitable library for %s\n", arg);
1091 exit(1);
1092 }
1093 }
1094
1095 /* It is not ok to just add the file: a library may added with:
1096 1 - -L path library_name. (For *.so in Linux).
1097 2 - library_name.
1098 */
1099 #ifdef ADD_MINUS_L
1100 if (libtype == type_DYNAMIC_LIB) {
1101 add_minus_l(cmd_data->shared_opts.dependencies, newarg);
1102 } else {
1103 push_count_chars(cmd_data->shared_opts.dependencies, newarg);
1104 }
1105 #else
1106 push_count_chars(cmd_data->shared_opts.dependencies, newarg);
1107 #endif
1108 if (libtype == type_DYNAMIC_LIB) {
1109 if (cmd_data->options.no_install) {
1110 #ifdef RPATH
1111 add_rpath_noinstall(cmd_data->shared_opts.dependencies,
1112 arg, pathlen);
1113 #endif
1114 #ifdef DYNAMIC_LINK_NO_INSTALL
1115 /*
1116 * This doesn't work as Darwin's linker has no way to
1117 * override at link-time the search paths for a
1118 * non-installed library.
1119 */
1120 /*
1121 add_dylink_noinstall(cmd_data->shared_opts.dependencies,
1122 arg, pathlen, ext - arg);
1123 */
1124 #endif
1125 }
1126 else {
1127 #ifdef RPATH
1128 add_rpath_file(cmd_data->shared_opts.dependencies, arg);
1129 #endif
1130 }
1131 }
1132 break;
1133 case mInstall:
1134 /* If we've already recorded a library to install, we're most
1135 * likely getting the .la file that we want to install as.
1136 * The problem is that we need to add it as the directory,
1137 * not the .la file itself. Otherwise, we'll do odd things.
1138 */
1139 if (cmd_data->output == otLibrary) {
1140 arg[pathlen] = '\0';
1141 push_count_chars(cmd_data->arglist, arg);
1142 }
1143 else {
1144 cmd_data->output = otLibrary;
1145 cmd_data->output_name = arg;
1146 cmd_data->static_name.install = gen_install_name(arg, 0);
1147 cmd_data->shared_name.install = gen_install_name(arg, 1);
1148 cmd_data->module_name.install = gen_install_name(arg, 2);
1149 }
1150 break;
1151 default:
1152 break;
1153 }
1154 return 1;
1155 }
1156
1157 if (strcmp(ext, "c") == 0) {
1158 /* If we don't already have an idea what our output name will be. */
1159 if (cmd_data->basename == NULL) {
1160 cmd_data->basename = (char *)malloc(strlen(arg) + 4);
1161 strcpy(cmd_data->basename, arg);
1162 strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
1163
1164 cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
1165 if (cmd_data->fake_output_name) {
1166 cmd_data->fake_output_name++;
1167 }
1168 else {
1169 cmd_data->fake_output_name = cmd_data->basename;
1170 }
1171 }
1172 }
1173
1174 return 0;
1175 }
1176
parse_output_file_name(char * arg,command_t * cmd_data)1177 int parse_output_file_name(char *arg, command_t *cmd_data)
1178 {
1179 char *name = strrchr(arg, '/');
1180 char *ext = strrchr(arg, '.');
1181 char *newarg = NULL;
1182 int pathlen;
1183
1184 cmd_data->fake_output_name = arg;
1185
1186 if (name) {
1187 name++;
1188 }
1189 else {
1190 name = strrchr(arg, '\\');
1191
1192 if (name == NULL) {
1193 name = arg;
1194 }
1195 else {
1196 name++;
1197 }
1198 }
1199
1200 if (!ext) {
1201 cmd_data->basename = arg;
1202 cmd_data->output = otProgram;
1203 #if defined(_OSD_POSIX)
1204 cmd_data->options.pic_mode = pic_AVOID;
1205 #endif
1206 newarg = (char *)malloc(strlen(arg) + 5);
1207 strcpy(newarg, arg);
1208 #ifdef EXE_EXT
1209 strcat(newarg, EXE_EXT);
1210 #endif
1211 cmd_data->output_name = newarg;
1212 return 1;
1213 }
1214
1215 ext++;
1216 pathlen = name - arg;
1217
1218 if (strcmp(ext, "la") == 0) {
1219 assert(cmd_data->mode == mLink);
1220
1221 cmd_data->basename = arg;
1222 cmd_data->static_name.normal = gen_library_name(arg, 0);
1223 cmd_data->shared_name.normal = gen_library_name(arg, 1);
1224 cmd_data->module_name.normal = gen_library_name(arg, 2);
1225 cmd_data->static_name.install = gen_install_name(arg, 0);
1226 cmd_data->shared_name.install = gen_install_name(arg, 1);
1227 cmd_data->module_name.install = gen_install_name(arg, 2);
1228
1229 #ifdef TRUNCATE_DLL_NAME
1230 if (shared) {
1231 arg = truncate_dll_name(arg);
1232 }
1233 #endif
1234
1235 cmd_data->output_name = arg;
1236 return 1;
1237 }
1238
1239 if (strcmp(ext, "lo") == 0) {
1240 cmd_data->basename = arg;
1241 cmd_data->output = otObject;
1242 newarg = (char *)malloc(strlen(arg) + 2);
1243 strcpy(newarg, arg);
1244 ext = strrchr(newarg, '.') + 1;
1245 strcpy(ext, OBJECT_EXT);
1246 cmd_data->output_name = newarg;
1247 return 1;
1248 }
1249
1250 return 0;
1251 }
1252
1253 /* returns just a file's name without path or extension */
nameof(char * fullpath)1254 char *nameof(char *fullpath)
1255 {
1256 char buffer[1024];
1257 char *ext;
1258 char *name = strrchr(fullpath, '/');
1259
1260 if (name == NULL) {
1261 name = strrchr(fullpath, '\\');
1262 }
1263
1264 if (name == NULL) {
1265 name = fullpath;
1266 } else {
1267 name++;
1268 }
1269
1270 strcpy(buffer, name);
1271 ext = strrchr(buffer, '.');
1272
1273 if (ext) {
1274 *ext = 0;
1275 return strdup(buffer);
1276 }
1277
1278 return name;
1279 }
1280
parse_args(int argc,char * argv[],command_t * cmd_data)1281 void parse_args(int argc, char *argv[], command_t *cmd_data)
1282 {
1283 int a;
1284 char *arg;
1285 int argused;
1286
1287 for (a = 1; a < argc; a++) {
1288 arg = argv[a];
1289 argused = 1;
1290
1291 if (arg[0] == '-') {
1292 if (arg[1] == '-') {
1293 argused = parse_long_opt(arg + 2, cmd_data);
1294 }
1295 else {
1296 argused = parse_short_opt(arg + 1, cmd_data);
1297 }
1298
1299 /* We haven't done anything with it yet, try some of the
1300 * more complicated short opts... */
1301 if (argused == 0 && a + 1 < argc) {
1302 if (arg[1] == 'o' && !arg[2]) {
1303 arg = argv[++a];
1304 argused = parse_output_file_name(arg, cmd_data);
1305 } else if (strcmp(arg+1, "MT") == 0) {
1306 if (!cmd_data->options.silent) {
1307 printf("Adding: %s", arg);
1308 }
1309 push_count_chars(cmd_data->arglist, arg);
1310 arg = argv[++a];
1311 if (!cmd_data->options.silent) {
1312 printf(" %s\n", arg);
1313 }
1314 push_count_chars(cmd_data->arglist, arg);
1315 argused = 1;
1316 } else if (strcmp(arg+1, "rpath") == 0) {
1317 /* Aha, we should try to link both! */
1318 cmd_data->install_path = argv[++a];
1319 argused = 1;
1320 } else if (strcmp(arg+1, "version-info") == 0) {
1321 /* Store for later deciphering */
1322 cmd_data->version_info = argv[++a];
1323 argused = 1;
1324 } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
1325 /* Skip the argument. */
1326 ++a;
1327 argused = 1;
1328 } else if (arg[1] == 'R' && !arg[2]) {
1329 /* -R dir Add dir to runtime library search path. */
1330 add_runtimedirlib(argv[++a], cmd_data);
1331 argused = 1;
1332 }
1333 }
1334 } else {
1335 argused = parse_input_file_name(arg, cmd_data);
1336 }
1337
1338 if (!argused) {
1339 if (!cmd_data->options.silent) {
1340 printf("Adding: %s\n", arg);
1341 }
1342 push_count_chars(cmd_data->arglist, arg);
1343 }
1344 }
1345
1346 }
1347
explode_static_lib(const char * lib,command_t * cmd_data)1348 int explode_static_lib(const char *lib, command_t *cmd_data)
1349 {
1350 char tmpdir[1024];
1351 char savewd[1024];
1352 char cmd[1024];
1353 const char *name;
1354 DIR *dir;
1355 struct dirent *entry;
1356
1357 /* Bah! */
1358 if (cmd_data->options.dry_run) {
1359 return 0;
1360 }
1361
1362 strcpy(tmpdir, lib);
1363 strcat(tmpdir, ".exploded");
1364
1365 mkdir(tmpdir, 0);
1366 push_count_chars(cmd_data->tmp_dirs, strdup(tmpdir));
1367 getcwd(savewd, sizeof(savewd));
1368
1369 if (chdir(tmpdir) != 0)
1370 return 1;
1371
1372 strcpy(cmd, LIBRARIAN " x ");
1373 name = strrchr(lib, '/');
1374
1375 if (name) {
1376 name++;
1377 } else {
1378 name = lib;
1379 }
1380
1381 strcat(cmd, "../");
1382 strcat(cmd, name);
1383 system(cmd);
1384 chdir(savewd);
1385 dir = opendir(tmpdir);
1386
1387 while ((entry = readdir(dir)) != NULL) {
1388 if (entry->d_name[0] != '.') {
1389 strcpy(cmd, tmpdir);
1390 strcat(cmd, "/");
1391 strcat(cmd, entry->d_name);
1392 push_count_chars(cmd_data->arglist, strdup(cmd));
1393 }
1394 }
1395
1396 closedir(dir);
1397 return 0;
1398 }
1399
1400 #ifdef GEN_EXPORTS
generate_def_file(command_t * cmd_data)1401 void generate_def_file(command_t *cmd_data)
1402 {
1403 char def_file[1024];
1404 char implib_file[1024];
1405 char *ext;
1406 FILE *hDef;
1407 char *export_args[1024];
1408 int num_export_args = 0;
1409 char *cmd;
1410 int cmd_size = 0;
1411 int a;
1412
1413 if (cmd_data->output_name) {
1414 strcpy(def_file, cmd_data->output_name);
1415 strcat(def_file, ".def");
1416 hDef = fopen(def_file, "w");
1417
1418 if (hDef != NULL) {
1419 fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
1420 fprintf(hDef, "DATA NONSHARED\n");
1421 fprintf(hDef, "EXPORTS\n");
1422 fclose(hDef);
1423
1424 for (a = 0; a < cmd_data->num_obj_files; a++) {
1425 cmd_size += strlen(cmd_data->obj_files[a]) + 1;
1426 }
1427
1428 cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
1429 cmd = (char *)malloc(cmd_size);
1430 strcpy(cmd, GEN_EXPORTS);
1431
1432 for (a=0; a < cmd_data->num_obj_files; a++) {
1433 strcat(cmd, " ");
1434 strcat(cmd, cmd_data->obj_files[a] );
1435 }
1436
1437 strcat(cmd, ">>");
1438 strcat(cmd, def_file);
1439 puts(cmd);
1440 export_args[num_export_args++] = SHELL_CMD;
1441 export_args[num_export_args++] = "-c";
1442 export_args[num_export_args++] = cmd;
1443 export_args[num_export_args++] = NULL;
1444 external_spawn(cmd_data, export_args[0], (const char**)export_args);
1445 cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
1446
1447 /* Now make an import library for the dll */
1448 num_export_args = 0;
1449 export_args[num_export_args++] = DEF2IMPLIB_CMD;
1450 export_args[num_export_args++] = "-o";
1451
1452 strcpy(implib_file, ".libs/");
1453 strcat(implib_file, cmd_data->basename);
1454 ext = strrchr(implib_file, '.');
1455
1456 if (ext)
1457 *ext = 0;
1458
1459 strcat(implib_file, ".");
1460 strcat(implib_file, STATIC_LIB_EXT);
1461
1462 export_args[num_export_args++] = implib_file;
1463 export_args[num_export_args++] = def_file;
1464 export_args[num_export_args++] = NULL;
1465 external_spawn(cmd_data, export_args[0], (const char**)export_args);
1466
1467 }
1468 }
1469 }
1470 #endif
1471
expand_path(const char * relpath)1472 const char* expand_path(const char *relpath)
1473 {
1474 char foo[PATH_MAX], *newpath;
1475
1476 getcwd(foo, PATH_MAX-1);
1477 newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
1478 strcat(newpath, foo);
1479 strcat(newpath, "/");
1480 strcat(newpath, relpath);
1481 return newpath;
1482 }
1483
link_fixup(command_t * c)1484 void link_fixup(command_t *c)
1485 {
1486 /* If we were passed an -rpath directive, we need to build
1487 * shared objects too. Otherwise, we should only create static
1488 * libraries.
1489 */
1490 if (!c->install_path && (c->output == otDynamicLibraryOnly ||
1491 c->output == otModule || c->output == otLibrary)) {
1492 c->output = otStaticLibraryOnly;
1493 }
1494
1495 if (c->output == otDynamicLibraryOnly ||
1496 c->output == otModule ||
1497 c->output == otLibrary) {
1498
1499 push_count_chars(c->shared_opts.normal, "-o");
1500 if (c->output == otModule) {
1501 push_count_chars(c->shared_opts.normal, c->module_name.normal);
1502 }
1503 else {
1504 char *tmp;
1505 push_count_chars(c->shared_opts.normal, c->shared_name.normal);
1506 #ifdef DYNAMIC_INSTALL_NAME
1507 push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
1508
1509 tmp = (char*)malloc(PATH_MAX);
1510 strcat(tmp, c->install_path);
1511 strcat(tmp, strrchr(c->shared_name.normal, '/'));
1512 push_count_chars(c->shared_opts.normal, tmp);
1513 #endif
1514 }
1515
1516 append_count_chars(c->shared_opts.normal, c->obj_files);
1517 append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
1518
1519 if (c->options.export_all) {
1520 #ifdef GEN_EXPORTS
1521 generate_def_file(c);
1522 #endif
1523 }
1524 }
1525
1526 if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
1527 push_count_chars(c->static_opts.normal, "-o");
1528 push_count_chars(c->static_opts.normal, c->output_name);
1529 }
1530
1531 if (c->output == otProgram) {
1532 if (c->output_name) {
1533 push_count_chars(c->arglist, "-o");
1534 push_count_chars(c->arglist, c->output_name);
1535 append_count_chars(c->arglist, c->obj_files);
1536 append_count_chars(c->arglist, c->shared_opts.dependencies);
1537 #ifdef DYNAMIC_LINK_OPTS
1538 if (c->options.pic_mode != pic_AVOID) {
1539 push_count_chars(c->arglist, DYNAMIC_LINK_OPTS);
1540 }
1541 #endif
1542 }
1543 }
1544 }
1545
post_parse_fixup(command_t * cmd_data)1546 void post_parse_fixup(command_t *cmd_data)
1547 {
1548 switch (cmd_data->mode)
1549 {
1550 case mCompile:
1551 #ifdef PIC_FLAG
1552 if (cmd_data->options.pic_mode != pic_AVOID) {
1553 push_count_chars(cmd_data->arglist, PIC_FLAG);
1554 }
1555 #endif
1556 if (cmd_data->output_name) {
1557 push_count_chars(cmd_data->arglist, "-o");
1558 push_count_chars(cmd_data->arglist, cmd_data->output_name);
1559 }
1560 break;
1561 case mLink:
1562 link_fixup(cmd_data);
1563 break;
1564 case mInstall:
1565 if (cmd_data->output == otLibrary) {
1566 link_fixup(cmd_data);
1567 }
1568 default:
1569 break;
1570 }
1571
1572 #if USE_OMF
1573 if (cmd_data->output == otObject ||
1574 cmd_data->output == otProgram ||
1575 cmd_data->output == otLibrary ||
1576 cmd_data->output == otDynamicLibraryOnly) {
1577 push_count_chars(cmd_data->arglist, "-Zomf");
1578 }
1579 #endif
1580
1581 if (cmd_data->options.shared &&
1582 (cmd_data->output == otObject ||
1583 cmd_data->output == otLibrary ||
1584 cmd_data->output == otDynamicLibraryOnly)) {
1585 #ifdef SHARE_SW
1586 push_count_chars(cmd_data->arglist, SHARE_SW);
1587 #endif
1588 }
1589 }
1590
run_mode(command_t * cmd_data)1591 int run_mode(command_t *cmd_data)
1592 {
1593 int rv;
1594 count_chars *cctemp;
1595
1596 cctemp = (count_chars*)malloc(sizeof(count_chars));
1597 init_count_chars(cctemp);
1598
1599 switch (cmd_data->mode)
1600 {
1601 case mCompile:
1602 rv = run_command(cmd_data, cmd_data->arglist);
1603 if (rv) {
1604 return rv;
1605 }
1606 break;
1607 case mInstall:
1608 /* Well, we'll assume it's a file going to a directory... */
1609 /* For brain-dead install-sh based scripts, we have to repeat
1610 * the command N-times. install-sh should die.
1611 */
1612 if (!cmd_data->output_name) {
1613 rv = run_command(cmd_data, cmd_data->arglist);
1614 if (rv) {
1615 return rv;
1616 }
1617 }
1618 if (cmd_data->output_name) {
1619 append_count_chars(cctemp, cmd_data->arglist);
1620 insert_count_chars(cctemp,
1621 cmd_data->output_name,
1622 cctemp->num - 1);
1623 rv = run_command(cmd_data, cctemp);
1624 if (rv) {
1625 return rv;
1626 }
1627 clear_count_chars(cctemp);
1628 }
1629 if (cmd_data->static_name.install) {
1630 append_count_chars(cctemp, cmd_data->arglist);
1631 insert_count_chars(cctemp,
1632 cmd_data->static_name.install,
1633 cctemp->num - 1);
1634 rv = run_command(cmd_data, cctemp);
1635 if (rv) {
1636 return rv;
1637 }
1638 clear_count_chars(cctemp);
1639 }
1640 if (cmd_data->shared_name.install) {
1641 append_count_chars(cctemp, cmd_data->arglist);
1642 insert_count_chars(cctemp,
1643 cmd_data->shared_name.install,
1644 cctemp->num - 1);
1645 rv = run_command(cmd_data, cctemp);
1646 if (rv) {
1647 return rv;
1648 }
1649 clear_count_chars(cctemp);
1650 }
1651 if (cmd_data->module_name.install) {
1652 append_count_chars(cctemp, cmd_data->arglist);
1653 insert_count_chars(cctemp,
1654 cmd_data->module_name.install,
1655 cctemp->num - 1);
1656 rv = run_command(cmd_data, cctemp);
1657 if (rv) {
1658 return rv;
1659 }
1660 clear_count_chars(cctemp);
1661 }
1662 break;
1663 case mLink:
1664 if (!cmd_data->options.dry_run) {
1665 /* Check first to see if the dir already exists! */
1666 mode_t old_umask;
1667
1668 old_umask = umask(0);
1669 umask(old_umask);
1670
1671 mkdir(".libs", ~old_umask);
1672 }
1673
1674 if (cmd_data->output == otStaticLibraryOnly ||
1675 cmd_data->output == otLibrary) {
1676 #ifdef RANLIB
1677 const char *lib_args[3];
1678 #endif
1679 /* Removes compiler! */
1680 cmd_data->program = LIBRARIAN;
1681 push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
1682 push_count_chars(cmd_data->program_opts,
1683 cmd_data->static_name.normal);
1684
1685 rv = run_command(cmd_data, cmd_data->obj_files);
1686 if (rv) {
1687 return rv;
1688 }
1689
1690 #ifdef RANLIB
1691 lib_args[0] = RANLIB;
1692 lib_args[1] = cmd_data->static_name.normal;
1693 lib_args[2] = NULL;
1694 external_spawn(cmd_data, RANLIB, lib_args);
1695 #endif
1696 }
1697
1698 if (cmd_data->output == otDynamicLibraryOnly ||
1699 cmd_data->output == otModule ||
1700 cmd_data->output == otLibrary) {
1701 cmd_data->program = NULL;
1702 clear_count_chars(cmd_data->program_opts);
1703
1704 append_count_chars(cmd_data->program_opts, cmd_data->arglist);
1705 if (cmd_data->output != otModule) {
1706 #ifdef SHARED_OPTS
1707 push_count_chars(cmd_data->program_opts, SHARED_OPTS);
1708 #endif
1709 #ifdef dynamic_link_version_func
1710 push_count_chars(cmd_data->program_opts,
1711 dynamic_link_version_func(cmd_data->version_info));
1712 #endif
1713 }
1714 if (cmd_data->output == otModule) {
1715 #ifdef MODULE_OPTS
1716 push_count_chars(cmd_data->program_opts, MODULE_OPTS);
1717 #endif
1718 }
1719 #ifdef DYNAMIC_LINK_OPTS
1720 if (cmd_data->options.pic_mode != pic_AVOID) {
1721 push_count_chars(cmd_data->program_opts,
1722 DYNAMIC_LINK_OPTS);
1723 }
1724 #endif
1725 rv = run_command(cmd_data, cmd_data->shared_opts.normal);
1726 if (rv) {
1727 return rv;
1728 }
1729 }
1730 if (cmd_data->output == otProgram) {
1731 rv = run_command(cmd_data, cmd_data->arglist);
1732 if (rv) {
1733 return rv;
1734 }
1735 }
1736 break;
1737 default:
1738 break;
1739 }
1740
1741 return 0;
1742 }
1743
cleanup_tmp_dir(const char * dirname)1744 void cleanup_tmp_dir(const char *dirname)
1745 {
1746 DIR *dir;
1747 struct dirent *entry;
1748 char fullname[1024];
1749
1750 dir = opendir(dirname);
1751
1752 if (dir == NULL)
1753 return;
1754
1755 while ((entry = readdir(dir)) != NULL) {
1756 if (entry->d_name[0] != '.') {
1757 strcpy(fullname, dirname);
1758 strcat(fullname, "/");
1759 strcat(fullname, entry->d_name);
1760 remove(fullname);
1761 }
1762 }
1763
1764 rmdir(dirname);
1765 }
1766
cleanup_tmp_dirs(command_t * cmd_data)1767 void cleanup_tmp_dirs(command_t *cmd_data)
1768 {
1769 int d;
1770
1771 for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
1772 cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
1773 }
1774 }
1775
ensure_fake_uptodate(command_t * cmd_data)1776 int ensure_fake_uptodate(command_t *cmd_data)
1777 {
1778 /* FIXME: could do the stat/touch here, but nah... */
1779 const char *touch_args[3];
1780
1781 if (cmd_data->mode == mInstall) {
1782 return 0;
1783 }
1784
1785 touch_args[0] = "touch";
1786 touch_args[1] = cmd_data->fake_output_name;
1787 touch_args[2] = NULL;
1788 return external_spawn(cmd_data, "touch", touch_args);
1789 }
1790
1791 /* Store the install path in the *.la file */
add_for_runtime(command_t * cmd_data)1792 int add_for_runtime(command_t *cmd_data)
1793 {
1794 if (cmd_data->mode == mInstall) {
1795 return 0;
1796 }
1797 if (cmd_data->output == otDynamicLibraryOnly ||
1798 cmd_data->output == otLibrary) {
1799 FILE *f=fopen(cmd_data->fake_output_name,"w");
1800 if (f == NULL) {
1801 return -1;
1802 }
1803 fprintf(f,"%s\n", cmd_data->install_path);
1804 fclose(f);
1805 return(0);
1806 } else {
1807 return(ensure_fake_uptodate(cmd_data));
1808 }
1809 }
1810
main(int argc,char * argv[])1811 int main(int argc, char *argv[])
1812 {
1813 int rc;
1814 command_t cmd_data;
1815
1816 memset(&cmd_data, 0, sizeof(cmd_data));
1817
1818 cmd_data.options.pic_mode = pic_UNKNOWN;
1819
1820 cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
1821 init_count_chars(cmd_data.program_opts);
1822 cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
1823 init_count_chars(cmd_data.arglist);
1824 cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
1825 init_count_chars(cmd_data.tmp_dirs);
1826 cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
1827 init_count_chars(cmd_data.obj_files);
1828 cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
1829 init_count_chars(cmd_data.dep_rpaths);
1830 cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
1831 init_count_chars(cmd_data.rpaths);
1832 cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
1833 init_count_chars(cmd_data.static_opts.normal);
1834 cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
1835 init_count_chars(cmd_data.shared_opts.normal);
1836 cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
1837 init_count_chars(cmd_data.shared_opts.dependencies);
1838
1839 cmd_data.mode = mUnknown;
1840 cmd_data.output = otGeneral;
1841
1842 parse_args(argc, argv, &cmd_data);
1843 post_parse_fixup(&cmd_data);
1844
1845 if (cmd_data.mode == mUnknown) {
1846 exit(0);
1847 }
1848
1849 rc = run_mode(&cmd_data);
1850
1851 if (!rc) {
1852 add_for_runtime(&cmd_data);
1853 }
1854
1855 cleanup_tmp_dirs(&cmd_data);
1856 return rc;
1857 }
1858