1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
21
#include <sys/types.h>
29
# define SHELL_CMD "sh"
30
# define GEN_EXPORTS "emxexp"
31
# define DEF2IMPLIB_CMD "emximp"
32
# define SHARE_SW "-Zdll -Zmtd"
34
# define TRUNCATE_DLL_NAME
35
# define DYNAMIC_LIB_EXT "dll"
36
# define EXE_EXT ".exe"
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"
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"
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"
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"
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,"
91
# define LD_RUN_PATH "LD_RUN_PATH"
92
# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
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"
106
# define SHARED_OPTS "-G"
107
# define MODULE_OPTS "-G"
108
# define DYNAMIC_LINK_OPTS ""
109
# define LINKER_FLAG_NO_EQUALS
111
# define HAS_REALPATH
112
# define LD_RUN_PATH "LD_RUN_PATH"
113
# define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
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
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"
149
#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
161
#define PATH_MAX 1024
165
/* We want to say we are libtool 1.4 for shlibtool compatibility. */
166
#define VERSION "1.4"
181
otDynamicLibraryOnly,
211
count_chars *install;
212
count_chars *dependencies;
220
enum pic_mode_e pic_mode;
226
enum tool_mode_t mode;
227
enum output_t output;
231
char *fake_output_name;
234
const char *install_path;
235
const char *compiler;
237
count_chars *program_opts;
239
count_chars *arglist;
240
count_chars *tmp_dirs;
241
count_chars *obj_files;
242
count_chars *dep_rpaths;
245
library_name static_name;
246
library_name shared_name;
247
library_name module_name;
249
library_opts static_opts;
250
library_opts shared_opts;
252
const char *version_info;
256
void add_rpath(count_chars *cc, const char *path);
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
264
* This is portable to any POSIX-compliant system has /dev/null
267
static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
272
f = fopen("/dev/null","w");
276
setvbuf( f, str, _IOFBF, n );
278
res = vfprintf( f, fmt, ap );
280
if ( res > 0 && res < n ) {
281
res = vsprintf( str, fmt, ap );
285
static int snprintf( char *str, size_t n, const char *fmt, ... )
291
res = vsnprintf( str, n, fmt, ap );
297
void init_count_chars(count_chars *cc)
299
cc->vals = (const char**)malloc(PATH_MAX);
303
void clear_count_chars(count_chars *cc)
306
for (i = 0; i < cc->num; i++) {
313
void push_count_chars(count_chars *cc, const char *newval)
315
cc->vals[cc->num++] = newval;
318
void insert_count_chars(count_chars *cc, const char *newval, int position)
322
for (i = cc->num; i > position; i--) {
323
cc->vals[i] = cc->vals[i-1];
326
cc->vals[position] = newval;
330
void append_count_chars(count_chars *cc, count_chars *cctoadd)
333
for (i = 0; i < cctoadd->num; i++) {
334
if (cctoadd->vals[i]) {
335
push_count_chars(cc, cctoadd->vals[i]);
340
const char *flatten_count_chars(count_chars *cc)
346
for (i = 0; i < cc->num; i++) {
348
size += strlen(cc->vals[i]) + 1;
352
newval = (char*)malloc(size + 1);
355
for (i = 0; i < cc->num; i++) {
357
strcat(newval, cc->vals[i]);
365
char *shell_esc(const char *str)
370
const unsigned char *s;
372
cmd = (char *)malloc(2 * strlen(str) + 1);
373
d = (unsigned char *)cmd;
374
s = (const unsigned char *)str;
381
else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
391
int external_spawn(command_t *cmd, const char *file, const char **argv)
393
if (!cmd->options.silent) {
394
const char **argument = argv;
395
printf("Executing: ");
397
printf("%s ", *argument);
403
if (cmd->options.dry_run) {
407
return spawnvp(P_WAIT, file, argv);
413
return execvp(argv[0], (char**)argv);
417
waitpid(pid, &statuscode, 0);
418
if (WIFEXITED(statuscode)) {
419
return WEXITSTATUS(statuscode);
427
int run_command(command_t *cmd_data, count_chars *cc)
430
const char *spawn_args[4];
433
init_count_chars(&tmpcc);
435
if (cmd_data->program) {
436
push_count_chars(&tmpcc, cmd_data->program);
439
append_count_chars(&tmpcc, cmd_data->program_opts);
441
append_count_chars(&tmpcc, cc);
443
command = shell_esc(flatten_count_chars(&tmpcc));
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);
453
* print configuration
454
* shlibpath_var is used in configure.
459
printf("runpath_var=%s\n", LD_RUN_PATH);
461
#ifdef LD_LIBRARY_PATH
462
printf("shlibpath_var=%s\n", LD_LIBRARY_PATH);
465
printf("SHELL=\"%s\"\n", SHELL_CMD);
469
* Add a directory to the runtime library search path.
471
void add_runtimedirlib(char *arg, command_t *cmd_data)
474
add_rpath(cmd_data->shared_opts.dependencies, arg);
479
int parse_long_opt(char *arg, command_t *cmd_data)
481
char *equal_pos = strchr(arg, '=');
486
strncpy(var, arg, equal_pos - arg);
487
var[equal_pos - arg] = 0;
488
strcpy(value, equal_pos + 1);
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;
501
if (strcmp(value, "link") == 0) {
502
cmd_data->mode = mLink;
503
cmd_data->output = otLibrary;
506
if (strcmp(value, "install") == 0) {
507
cmd_data->mode = mInstall;
509
} else if (strcmp(var, "shared") == 0) {
510
if (cmd_data->mode == mLink) {
511
cmd_data->output = otDynamicLibraryOnly;
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) {
525
} else if (strcmp(var, "tag") == 0) {
526
if (strcmp(value, "CC") == 0) {
529
if (strcmp(value, "CXX") == 0) {
539
/* Return 1 if we eat it. */
540
int parse_short_opt(char *arg, command_t *cmd_data)
542
if (strcmp(arg, "export-dynamic") == 0) {
543
cmd_data->options.export_dynamic = 1;
547
if (strcmp(arg, "module") == 0) {
548
cmd_data->output = otModule;
552
if (strcmp(arg, "Zexe") == 0) {
556
if (strcmp(arg, "avoid-version") == 0) {
560
if (strcmp(arg, "prefer-pic") == 0) {
561
cmd_data->options.pic_mode = pic_PREFER;
565
if (strcmp(arg, "prefer-non-pic") == 0) {
566
cmd_data->options.pic_mode = pic_AVOID;
570
if (strcmp(arg, "static") == 0) {
571
/* Don't respect it for now. */
575
if (cmd_data->mode == mLink) {
576
if (strcmp(arg, "no-install") == 0) {
577
cmd_data->options.no_install = 1;
580
if (arg[0] == 'L' || arg[0] == 'l') {
583
push_count_chars(cmd_data->shared_opts.dependencies, arg);
585
} else if (arg[0] == 'R' && arg[1]) {
586
/* -Rdir Add dir to runtime library search path. */
587
add_runtimedirlib(&arg[1], cmd_data);
594
char *truncate_dll_name(char *path)
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, '.');
607
if (strncmp(newname, "mod_", 4) == 0) {
608
strcpy(newname, newname + 4);
613
strcpy(newname + 8, strchr(newname, '.'));
619
long safe_strtol(const char *nptr, const char **endptr, int base)
625
rv = strtol(nptr, (char**)endptr, 10);
627
if (errno == ERANGE) {
634
/* version_info is in the form of MAJOR:MINOR:PATCH */
635
const char *darwin_dynamic_link_function(const char *version_info)
638
long major, minor, patch;
645
major = safe_strtol(version_info, &version_info, 10);
648
if (version_info[0] == ':') {
652
minor = safe_strtol(version_info, &version_info, 10);
655
if (version_info[0] == ':') {
659
patch = safe_strtol(version_info, &version_info, 10);
665
/* Avoid -dylib_compatibility_version must be greater than zero errors. */
669
newarg = (char*)malloc(100);
671
"-compatibility_version %ld -current_version %ld.%ld",
672
major, major, minor);
682
char *gen_library_name(const char *name, int genlib)
684
char *newarg, *newext;
686
newarg = (char *)malloc(strlen(name) + 10);
687
strcpy(newarg, ".libs/");
689
if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
693
strcat(newarg, name);
695
newext = strrchr(newarg, '.') + 1;
699
strcpy(newext, STATIC_LIB_EXT);
702
strcpy(newext, DYNAMIC_LIB_EXT);
705
strcpy(newext, MODULE_LIB_EXT);
717
char *gen_install_name(const char *name, int genlib)
723
newname = gen_library_name(name, genlib);
725
/* Check if it exists. If not, return NULL. */
726
rv = stat(newname, &sb);
735
char *check_object_exists(command_t *cmd, const char *arg, int arglen)
740
newarg = (char *)malloc(arglen + 10);
741
memcpy(newarg, arg, arglen);
743
ext = newarg + arglen;
752
strcpy(ext, OBJECT_EXT);
756
strcpy(ext, NO_PIC_EXT);
763
if (!cmd->options.silent) {
764
printf("Checking (obj): %s\n", newarg);
766
rv = stat(newarg, &sb);
768
while (rv != 0 && ++pass < 1);
772
cmd->options.pic_mode = pic_AVOID;
780
/* libdircheck values:
781
* 0 - no .libs suffix
784
char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
785
int libdircheck, enum lib_type *libtype)
788
int pass, rv, newpathlen;
790
newarg = (char *)malloc(strlen(arg) + 10);
794
newpathlen = pathlen;
796
strcat(newarg, ".libs/");
797
newpathlen += sizeof(".libs/") - 1;
800
strcpy(newarg+newpathlen, arg+pathlen);
801
ext = strrchr(newarg, '.') + 1;
810
if (cmd->options.pic_mode != pic_AVOID || cmd->options.shared) {
811
strcpy(ext, DYNAMIC_LIB_EXT);
812
*libtype = type_DYNAMIC_LIB;
817
strcpy(ext, STATIC_LIB_EXT);
818
*libtype = type_STATIC_LIB;
821
strcpy(ext, MODULE_LIB_EXT);
822
*libtype = type_MODULE_LIB;
825
strcpy(ext, OBJECT_EXT);
826
*libtype = type_OBJECT;
829
*libtype = type_UNKNOWN;
833
if (!cmd->options.silent) {
834
printf("Checking (lib): %s\n", newarg);
836
rv = stat(newarg, &sb);
838
while (rv != 0 && ++pass < 4);
847
char * load_install_path(const char *arg)
852
path = malloc(PATH_MAX);
858
fgets(path, PATH_MAX, f);
860
if (path[strlen(path)-1] == '\n') {
861
path[strlen(path)-1] = '\0';
863
/* Check that we have an absolute path.
864
* Otherwise the file could be a GNU libtool file.
866
if (path[0] != '/') {
872
char * load_noinstall_path(const char *arg, int pathlen)
874
char *newarg, *expanded_path;
877
newarg = (char *)malloc(strlen(arg) + 10);
881
newpathlen = pathlen;
882
strcat(newarg, ".libs");
883
newpathlen += sizeof(".libs") - 1;
884
newarg[newpathlen] = 0;
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;
894
/* We might get ../ or something goofy. Oh, well. */
895
expanded_path = newarg;
898
return expanded_path;
901
/* Read the final install location and add it to runtime library search path. */
903
void add_rpath(count_chars *cc, const char *path)
908
#ifdef LINKER_FLAG_PREFIX
909
size = strlen(LINKER_FLAG_PREFIX);
911
size = size + strlen(path) + strlen(RPATH) + 2;
916
#ifdef LINKER_FLAG_PREFIX
917
strcpy(tmp, LINKER_FLAG_PREFIX);
922
#ifndef LINKER_FLAG_NO_EQUALS
927
push_count_chars(cc, tmp);
930
void add_rpath_file(count_chars *cc, const char *arg)
934
path = load_install_path(arg);
940
void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
944
path = load_noinstall_path(arg, pathlen);
951
#ifdef DYNAMIC_LINK_NO_INSTALL
952
void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
955
const char *install_path, *current_path, *name;
957
int i_p_len, c_p_len, name_len, dyext_len, cur_len;
959
install_path = load_install_path(arg);
960
current_path = load_noinstall_path(arg, pathlen);
962
if (!install_path || !current_path) {
966
push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
968
i_p_len = strlen(install_path);
969
c_p_len = strlen(current_path);
972
name_len = extlen-pathlen;
973
dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
975
/* No, we need to replace the extension. */
976
exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
980
strcpy(exp_argument, install_path);
982
exp_argument[cur_len++] = '/';
983
strncpy(exp_argument+cur_len, name, extlen-pathlen);
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);
990
exp_argument[cur_len++] = '/';
991
strncpy(exp_argument+cur_len, name, extlen-pathlen);
993
strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
994
cur_len += dyext_len;
996
push_count_chars(cc, exp_argument);
1000
/* use -L -llibname to allow to use installed libraries */
1001
void add_minus_l(count_chars *cc, const char *arg)
1004
char *name = strrchr(arg, '/');
1005
char *file = strrchr(arg, '.');
1006
char *lib = strstr(name, "lib");
1008
if (name !=NULL && file != NULL && lib == name+1) {
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);
1021
push_count_chars(cc, arg);
1025
void add_linker_flag_prefix(count_chars *cc, const char *arg)
1027
#ifndef LINKER_FLAG_PREFIX
1028
push_count_chars(cc, arg);
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);
1038
int parse_input_file_name(char *arg, command_t *cmd_data)
1040
char *ext = strrchr(arg, '.');
1041
char *name = strrchr(arg, '/');
1043
enum lib_type libtype;
1053
name = strrchr(arg, '\\');
1064
pathlen = name - arg;
1066
if (strcmp(ext, "lo") == 0) {
1067
newarg = check_object_exists(cmd_data, arg, ext - arg);
1069
printf("Can not find suitable object file for %s\n", arg);
1072
if (cmd_data->mode != mLink) {
1073
push_count_chars(cmd_data->arglist, newarg);
1076
push_count_chars(cmd_data->obj_files, newarg);
1081
if (strcmp(ext, "la") == 0) {
1082
switch (cmd_data->mode) {
1084
/* Try the .libs dir first! */
1085
newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
1087
/* Try the normal dir next. */
1088
newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
1090
printf("Can not find suitable library for %s\n", arg);
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).
1100
if (libtype == type_DYNAMIC_LIB) {
1101
add_minus_l(cmd_data->shared_opts.dependencies, newarg);
1103
push_count_chars(cmd_data->shared_opts.dependencies, newarg);
1106
push_count_chars(cmd_data->shared_opts.dependencies, newarg);
1108
if (libtype == type_DYNAMIC_LIB) {
1109
if (cmd_data->options.no_install) {
1111
add_rpath_noinstall(cmd_data->shared_opts.dependencies,
1114
#ifdef DYNAMIC_LINK_NO_INSTALL
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.
1121
add_dylink_noinstall(cmd_data->shared_opts.dependencies,
1122
arg, pathlen, ext - arg);
1128
add_rpath_file(cmd_data->shared_opts.dependencies, arg);
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.
1139
if (cmd_data->output == otLibrary) {
1140
arg[pathlen] = '\0';
1141
push_count_chars(cmd_data->arglist, arg);
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);
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");
1164
cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
1165
if (cmd_data->fake_output_name) {
1166
cmd_data->fake_output_name++;
1169
cmd_data->fake_output_name = cmd_data->basename;
1177
int parse_output_file_name(char *arg, command_t *cmd_data)
1179
char *name = strrchr(arg, '/');
1180
char *ext = strrchr(arg, '.');
1181
char *newarg = NULL;
1184
cmd_data->fake_output_name = arg;
1190
name = strrchr(arg, '\\');
1201
cmd_data->basename = arg;
1202
cmd_data->output = otProgram;
1203
#if defined(_OSD_POSIX)
1204
cmd_data->options.pic_mode = pic_AVOID;
1206
newarg = (char *)malloc(strlen(arg) + 5);
1207
strcpy(newarg, arg);
1209
strcat(newarg, EXE_EXT);
1211
cmd_data->output_name = newarg;
1216
pathlen = name - arg;
1218
if (strcmp(ext, "la") == 0) {
1219
assert(cmd_data->mode == mLink);
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);
1229
#ifdef TRUNCATE_DLL_NAME
1231
arg = truncate_dll_name(arg);
1235
cmd_data->output_name = arg;
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;
1253
/* returns just a file's name without path or extension */
1254
char *nameof(char *fullpath)
1258
char *name = strrchr(fullpath, '/');
1261
name = strrchr(fullpath, '\\');
1270
strcpy(buffer, name);
1271
ext = strrchr(buffer, '.');
1275
return strdup(buffer);
1281
void parse_args(int argc, char *argv[], command_t *cmd_data)
1287
for (a = 1; a < argc; a++) {
1291
if (arg[0] == '-') {
1292
if (arg[1] == '-') {
1293
argused = parse_long_opt(arg + 2, cmd_data);
1296
argused = parse_short_opt(arg + 1, cmd_data);
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]) {
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);
1309
push_count_chars(cmd_data->arglist, arg);
1311
if (!cmd_data->options.silent) {
1312
printf(" %s\n", arg);
1314
push_count_chars(cmd_data->arglist, arg);
1316
} else if (strcmp(arg+1, "rpath") == 0) {
1317
/* Aha, we should try to link both! */
1318
cmd_data->install_path = argv[++a];
1320
} else if (strcmp(arg+1, "version-info") == 0) {
1321
/* Store for later deciphering */
1322
cmd_data->version_info = argv[++a];
1324
} else if (strcmp(arg+1, "export-symbols-regex") == 0) {
1325
/* Skip the argument. */
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);
1335
argused = parse_input_file_name(arg, cmd_data);
1339
if (!cmd_data->options.silent) {
1340
printf("Adding: %s\n", arg);
1342
push_count_chars(cmd_data->arglist, arg);
1348
int explode_static_lib(const char *lib, command_t *cmd_data)
1355
struct dirent *entry;
1358
if (cmd_data->options.dry_run) {
1362
strcpy(tmpdir, lib);
1363
strcat(tmpdir, ".exploded");
1366
push_count_chars(cmd_data->tmp_dirs, strdup(tmpdir));
1367
getcwd(savewd, sizeof(savewd));
1369
if (chdir(tmpdir) != 0)
1372
strcpy(cmd, LIBRARIAN " x ");
1373
name = strrchr(lib, '/');
1385
dir = opendir(tmpdir);
1387
while ((entry = readdir(dir)) != NULL) {
1388
if (entry->d_name[0] != '.') {
1389
strcpy(cmd, tmpdir);
1391
strcat(cmd, entry->d_name);
1392
push_count_chars(cmd_data->arglist, strdup(cmd));
1401
void generate_def_file(command_t *cmd_data)
1403
char def_file[1024];
1404
char implib_file[1024];
1407
char *export_args[1024];
1408
int num_export_args = 0;
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");
1419
fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
1420
fprintf(hDef, "DATA NONSHARED\n");
1421
fprintf(hDef, "EXPORTS\n");
1424
for (a = 0; a < cmd_data->num_obj_files; a++) {
1425
cmd_size += strlen(cmd_data->obj_files[a]) + 1;
1428
cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
1429
cmd = (char *)malloc(cmd_size);
1430
strcpy(cmd, GEN_EXPORTS);
1432
for (a=0; a < cmd_data->num_obj_files; a++) {
1434
strcat(cmd, cmd_data->obj_files[a] );
1438
strcat(cmd, def_file);
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);
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";
1452
strcpy(implib_file, ".libs/");
1453
strcat(implib_file, cmd_data->basename);
1454
ext = strrchr(implib_file, '.');
1459
strcat(implib_file, ".");
1460
strcat(implib_file, STATIC_LIB_EXT);
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);
1472
const char* expand_path(const char *relpath)
1474
char foo[PATH_MAX], *newpath;
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);
1484
void link_fixup(command_t *c)
1486
/* If we were passed an -rpath directive, we need to build
1487
* shared objects too. Otherwise, we should only create static
1490
if (!c->install_path && (c->output == otDynamicLibraryOnly ||
1491
c->output == otModule || c->output == otLibrary)) {
1492
c->output = otStaticLibraryOnly;
1495
if (c->output == otDynamicLibraryOnly ||
1496
c->output == otModule ||
1497
c->output == otLibrary) {
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);
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);
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);
1516
append_count_chars(c->shared_opts.normal, c->obj_files);
1517
append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
1519
if (c->options.export_all) {
1521
generate_def_file(c);
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);
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);
1546
void post_parse_fixup(command_t *cmd_data)
1548
switch (cmd_data->mode)
1552
if (cmd_data->options.pic_mode != pic_AVOID) {
1553
push_count_chars(cmd_data->arglist, PIC_FLAG);
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);
1562
link_fixup(cmd_data);
1565
if (cmd_data->output == otLibrary) {
1566
link_fixup(cmd_data);
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");
1581
if (cmd_data->options.shared &&
1582
(cmd_data->output == otObject ||
1583
cmd_data->output == otLibrary ||
1584
cmd_data->output == otDynamicLibraryOnly)) {
1586
push_count_chars(cmd_data->arglist, SHARE_SW);
1591
int run_mode(command_t *cmd_data)
1594
count_chars *cctemp;
1596
cctemp = (count_chars*)malloc(sizeof(count_chars));
1597
init_count_chars(cctemp);
1599
switch (cmd_data->mode)
1602
rv = run_command(cmd_data, cmd_data->arglist);
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.
1612
if (!cmd_data->output_name) {
1613
rv = run_command(cmd_data, cmd_data->arglist);
1618
if (cmd_data->output_name) {
1619
append_count_chars(cctemp, cmd_data->arglist);
1620
insert_count_chars(cctemp,
1621
cmd_data->output_name,
1623
rv = run_command(cmd_data, cctemp);
1627
clear_count_chars(cctemp);
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,
1634
rv = run_command(cmd_data, cctemp);
1638
clear_count_chars(cctemp);
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,
1645
rv = run_command(cmd_data, cctemp);
1649
clear_count_chars(cctemp);
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,
1656
rv = run_command(cmd_data, cctemp);
1660
clear_count_chars(cctemp);
1664
if (!cmd_data->options.dry_run) {
1665
/* Check first to see if the dir already exists! */
1668
old_umask = umask(0);
1671
mkdir(".libs", ~old_umask);
1674
if (cmd_data->output == otStaticLibraryOnly ||
1675
cmd_data->output == otLibrary) {
1677
const char *lib_args[3];
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);
1685
rv = run_command(cmd_data, cmd_data->obj_files);
1691
lib_args[0] = RANLIB;
1692
lib_args[1] = cmd_data->static_name.normal;
1694
external_spawn(cmd_data, RANLIB, lib_args);
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);
1704
append_count_chars(cmd_data->program_opts, cmd_data->arglist);
1705
if (cmd_data->output != otModule) {
1707
push_count_chars(cmd_data->program_opts, SHARED_OPTS);
1709
#ifdef dynamic_link_version_func
1710
push_count_chars(cmd_data->program_opts,
1711
dynamic_link_version_func(cmd_data->version_info));
1714
if (cmd_data->output == otModule) {
1716
push_count_chars(cmd_data->program_opts, MODULE_OPTS);
1719
#ifdef DYNAMIC_LINK_OPTS
1720
if (cmd_data->options.pic_mode != pic_AVOID) {
1721
push_count_chars(cmd_data->program_opts,
1725
rv = run_command(cmd_data, cmd_data->shared_opts.normal);
1730
if (cmd_data->output == otProgram) {
1731
rv = run_command(cmd_data, cmd_data->arglist);
1744
void cleanup_tmp_dir(const char *dirname)
1747
struct dirent *entry;
1748
char fullname[1024];
1750
dir = opendir(dirname);
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);
1767
void cleanup_tmp_dirs(command_t *cmd_data)
1771
for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
1772
cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
1776
int ensure_fake_uptodate(command_t *cmd_data)
1778
/* FIXME: could do the stat/touch here, but nah... */
1779
const char *touch_args[3];
1781
if (cmd_data->mode == mInstall) {
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);
1791
/* Store the install path in the *.la file */
1792
int add_for_runtime(command_t *cmd_data)
1794
if (cmd_data->mode == mInstall) {
1797
if (cmd_data->output == otDynamicLibraryOnly ||
1798
cmd_data->output == otLibrary) {
1799
FILE *f=fopen(cmd_data->fake_output_name,"w");
1803
fprintf(f,"%s\n", cmd_data->install_path);
1807
return(ensure_fake_uptodate(cmd_data));
1811
int main(int argc, char *argv[])
1816
memset(&cmd_data, 0, sizeof(cmd_data));
1818
cmd_data.options.pic_mode = pic_UNKNOWN;
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);
1839
cmd_data.mode = mUnknown;
1840
cmd_data.output = otGeneral;
1842
parse_args(argc, argv, &cmd_data);
1843
post_parse_fixup(&cmd_data);
1845
if (cmd_data.mode == mUnknown) {
1849
rc = run_mode(&cmd_data);
1852
add_for_runtime(&cmd_data);
1855
cleanup_tmp_dirs(&cmd_data);