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