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>
30
bool export_all = false;
31
enum mode_t { mCompile, mLink, mInstall };
32
enum output_type_t { otGeneral, otObject, otProgram, otStaticLibrary, otDynamicLibrary };
35
# define SHELL_CMD "sh"
37
# define GEN_EXPORTS "emxexp"
38
# define DEF2IMPLIB_CMD "emximp"
39
# define SHARE_SW "-Zdll -Zmtd"
41
# define TRUNCATE_DLL_NAME
42
# define DYNAMIC_LIB_EXT "dll"
43
# define EXE_EXT ".exe"
46
/* OMF is the native format under OS/2 */
47
# define STATIC_LIB_EXT "lib"
48
# define OBJECT_EXT "obj"
49
# define LIBRARIAN "emxomfar"
51
/* but the alternative, a.out, can fork() which is sometimes necessary */
52
# define STATIC_LIB_EXT "a"
53
# define OBJECT_EXT "o"
54
# define LIBRARIAN "ar"
63
enum output_type_t output_type;
68
char *obj_files[1024];
72
void parse_args(int argc, char *argv[], cmd_data_t *cmd_data);
73
bool parse_long_opt(char *arg, cmd_data_t *cmd_data);
74
int parse_short_opt(char *arg, cmd_data_t *cmd_data);
75
bool parse_input_file_name(char *arg, cmd_data_t *cmd_data);
76
bool parse_output_file_name(char *arg, cmd_data_t *cmd_data);
77
void post_parse_fixup(cmd_data_t *cmd_data);
78
bool explode_static_lib(char *lib, cmd_data_t *cmd_data);
79
int execute_command(cmd_data_t *cmd_data);
80
char *shell_esc(const char *str);
81
void cleanup_tmp_dirs(cmd_data_t *cmd_data);
82
void generate_def_file(cmd_data_t *cmd_data);
83
char *nameof(char *fullpath);
84
char *truncate_dll_name(char *path);
87
int main(int argc, char *argv[])
92
memset(&cmd_data, 0, sizeof(cmd_data));
93
cmd_data.mode = mCompile;
94
cmd_data.output_type = otGeneral;
96
parse_args(argc, argv, &cmd_data);
97
rc = execute_command(&cmd_data);
99
if (rc == 0 && cmd_data.stub_name) {
100
fopen(cmd_data.stub_name, "w");
103
cleanup_tmp_dirs(&cmd_data);
109
void parse_args(int argc, char *argv[], cmd_data_t *cmd_data)
115
for (a=1; a < argc; a++) {
121
argused = parse_long_opt(arg + 2, cmd_data);
122
} else if (arg[1] == 'o' && a+1 < argc) {
123
cmd_data->arglist[cmd_data->num_args++] = arg;
125
argused = parse_output_file_name(arg, cmd_data);
127
int num_used = parse_short_opt(arg + 1, cmd_data);
128
argused = num_used > 0;
135
argused = parse_input_file_name(arg, cmd_data);
139
cmd_data->arglist[cmd_data->num_args++] = arg;
143
post_parse_fixup(cmd_data);
148
bool parse_long_opt(char *arg, cmd_data_t *cmd_data)
150
char *equal_pos = strchr(arg, '=');
155
strncpy(var, arg, equal_pos - arg);
156
var[equal_pos - arg] = 0;
157
strcpy(value, equal_pos + 1);
162
if (strcmp(var, "silent") == 0) {
164
} else if (strcmp(var, "mode") == 0) {
165
if (strcmp(value, "compile") == 0) {
166
cmd_data->mode = mCompile;
167
cmd_data->output_type = otObject;
170
if (strcmp(value, "link") == 0) {
171
cmd_data->mode = mLink;
174
if (strcmp(value, "install") == 0) {
175
cmd_data->mode = mInstall;
177
} else if (strcmp(var, "shared") == 0) {
179
} else if (strcmp(var, "export-all") == 0) {
190
int parse_short_opt(char *arg, cmd_data_t *cmd_data)
192
if (strcmp(arg, "export-dynamic") == 0) {
196
if (strcmp(arg, "module") == 0) {
200
if (strcmp(arg, "Zexe") == 0) {
204
if (strcmp(arg, "avoid-version") == 0) {
208
if (strcmp(arg, "prefer-pic") == 0) {
212
if (strcmp(arg, "prefer-non-pic") == 0) {
216
if (strcmp(arg, "version-info") == 0 ) {
220
if (strcmp(arg, "no-install") == 0) {
229
bool parse_input_file_name(char *arg, cmd_data_t *cmd_data)
231
char *ext = strrchr(arg, '.');
232
char *name = strrchr(arg, '/');
243
name = strrchr(arg, '\\');
254
pathlen = name - arg;
256
if (strcmp(ext, "lo") == 0) {
257
newarg = (char *)malloc(strlen(arg) + 10);
259
strcpy(newarg + (ext - arg), OBJECT_EXT);
260
cmd_data->arglist[cmd_data->num_args++] = newarg;
261
cmd_data->obj_files[cmd_data->num_obj_files++] = newarg;
265
if (strcmp(ext, "la") == 0) {
266
newarg = (char *)malloc(strlen(arg) + 10);
269
strcat(newarg, ".libs/");
271
if (strncmp(name, "lib", 3) == 0) {
275
strcat(newarg, name);
276
ext = strrchr(newarg, '.') + 1;
278
if (shared && cmd_data->mode == mInstall) {
279
strcpy(ext, DYNAMIC_LIB_EXT);
280
newarg = truncate_dll_name(newarg);
282
strcpy(ext, STATIC_LIB_EXT);
285
cmd_data->arglist[cmd_data->num_args++] = newarg;
289
if (strcmp(ext, "c") == 0) {
290
if (cmd_data->stub_name == NULL) {
291
cmd_data->stub_name = (char *)malloc(strlen(arg) + 4);
292
strcpy(cmd_data->stub_name, arg);
293
strcpy(strrchr(cmd_data->stub_name, '.') + 1, "lo");
297
if (strcmp(name, CC) == 0 || strcmp(name, CC EXE_EXT) == 0) {
298
if (cmd_data->output_type == otGeneral) {
299
cmd_data->output_type = otObject;
308
bool parse_output_file_name(char *arg, cmd_data_t *cmd_data)
310
char *name = strrchr(arg, '/');
311
char *ext = strrchr(arg, '.');
312
char *newarg = NULL, *newext;
316
name = strrchr(arg, '\\');
328
cmd_data->stub_name = arg;
329
cmd_data->output_type = otProgram;
330
newarg = (char *)malloc(strlen(arg) + 5);
332
strcat(newarg, EXE_EXT);
333
cmd_data->arglist[cmd_data->num_args++] = newarg;
334
cmd_data->output_name = newarg;
339
pathlen = name - arg;
341
if (strcmp(ext, "la") == 0) {
342
cmd_data->stub_name = arg;
343
cmd_data->output_type = shared ? otDynamicLibrary : otStaticLibrary;
344
newarg = (char *)malloc(strlen(arg) + 10);
346
strcpy(newarg, ".libs/");
348
if (strncmp(arg, "lib", 3) == 0) {
353
newext = strrchr(newarg, '.') + 1;
354
strcpy(newext, shared ? DYNAMIC_LIB_EXT : STATIC_LIB_EXT);
356
#ifdef TRUNCATE_DLL_NAME
358
newarg = truncate_dll_name(newarg);
362
cmd_data->arglist[cmd_data->num_args++] = newarg;
363
cmd_data->output_name = newarg;
367
if (strcmp(ext, "lo") == 0) {
368
cmd_data->stub_name = arg;
369
cmd_data->output_type = otObject;
370
newarg = (char *)malloc(strlen(arg) + 2);
372
ext = strrchr(newarg, '.') + 1;
373
strcpy(ext, OBJECT_EXT);
374
cmd_data->arglist[cmd_data->num_args++] = newarg;
375
cmd_data->output_name = newarg;
384
void post_parse_fixup(cmd_data_t *cmd_data)
390
if (cmd_data->output_type == otStaticLibrary && cmd_data->mode == mLink) {
391
/* We do a real hatchet job on the args when making a static library
392
* removing all compiler switches & any other cruft that ar won't like
393
* We also need to explode any libraries listed
396
for (a=0; a < cmd_data->num_args; a++) {
397
arg = cmd_data->arglist[a];
400
ext = strrchr(arg, '.');
407
cmd_data->arglist[a] = NULL;
409
if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
410
cmd_data->arglist[a+1] = NULL;
413
if (strcmp(arg, "-R") == 0 && a+1 < cmd_data->num_args) {
414
cmd_data->arglist[a+1] = NULL;
417
if (strcmp(arg, "-version-info") == 0 && a+1 < cmd_data->num_args) {
418
cmd_data->arglist[a+1] = NULL;
421
if (strcmp(arg, "-Zstack") == 0 && a+1 < cmd_data->num_args) {
422
cmd_data->arglist[a+1] = NULL;
425
if (strcmp(arg, "-o") == 0) {
430
if (strcmp(arg, CC) == 0 || strcmp(arg, CC EXE_EXT) == 0) {
431
cmd_data->arglist[a] = LIBRARIAN " cr";
435
if (strcmp(ext, "h") == 0 || strcmp(ext, "c") == 0) {
436
/* ignore source files, they don't belong in a library */
437
cmd_data->arglist[a] = NULL;
440
if (strcmp(ext, STATIC_LIB_EXT) == 0) {
441
cmd_data->arglist[a] = NULL;
442
explode_static_lib(arg, cmd_data);
449
if (cmd_data->output_type == otDynamicLibrary) {
450
for (a=0; a < cmd_data->num_args; a++) {
451
arg = cmd_data->arglist[a];
454
if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
455
cmd_data->arglist[a] = NULL;
456
cmd_data->arglist[a+1] = NULL;
462
generate_def_file(cmd_data);
467
if (cmd_data->output_type == otObject ||
468
cmd_data->output_type == otProgram ||
469
cmd_data->output_type == otDynamicLibrary) {
470
cmd_data->arglist[cmd_data->num_args++] = "-Zomf";
474
if (shared && (cmd_data->output_type == otObject || cmd_data->output_type == otDynamicLibrary)) {
475
cmd_data->arglist[cmd_data->num_args++] = SHARE_SW;
481
int execute_command(cmd_data_t *cmd_data)
485
int a, total_len = 0;
488
for (a=0; a < cmd_data->num_args; a++) {
489
if (cmd_data->arglist[a]) {
490
total_len += strlen(cmd_data->arglist[a]) + 1;
494
command = (char *)malloc( total_len );
497
for (a=0; a < cmd_data->num_args; a++) {
498
if (cmd_data->arglist[a]) {
499
strcat(command, cmd_data->arglist[a]);
500
strcat(command, " ");
504
command[strlen(command)-1] = 0;
510
cmd_data->num_args = target;
511
cmd_data->arglist[cmd_data->num_args] = NULL;
512
command = shell_esc(command);
518
return spawnvp(P_WAIT, args[0], args);
523
char *shell_esc(const char *str)
527
const unsigned char *s;
529
cmd = (char *)malloc(2 * strlen(str) + 1);
530
d = (unsigned char *)cmd;
531
s = (const unsigned char *)str;
534
if (*s == '"' || *s == '\\') {
546
bool explode_static_lib(char *lib, cmd_data_t *cmd_data)
553
struct dirent *entry;
556
strcat(tmpdir, ".exploded");
559
cmd_data->tmp_dirs[cmd_data->num_tmp_dirs++] = strdup(tmpdir);
560
getcwd(savewd, sizeof(savewd));
562
if (chdir(tmpdir) != 0)
565
strcpy(cmd, LIBRARIAN " x ");
566
name = strrchr(lib, '/');
578
dir = opendir(tmpdir);
580
while ((entry = readdir(dir)) != NULL) {
581
if (entry->d_name[0] != '.') {
584
strcat(cmd, entry->d_name);
585
cmd_data->arglist[cmd_data->num_args++] = strdup(cmd);
595
void cleanup_tmp_dir(char *dirname)
598
struct dirent *entry;
601
dir = opendir(dirname);
606
while ((entry = readdir(dir)) != NULL) {
607
if (entry->d_name[0] != '.') {
608
strcpy(fullname, dirname);
609
strcat(fullname, "/");
610
strcat(fullname, entry->d_name);
620
void cleanup_tmp_dirs(cmd_data_t *cmd_data)
624
for (d=0; d < cmd_data->num_tmp_dirs; d++) {
625
cleanup_tmp_dir(cmd_data->tmp_dirs[d]);
631
void generate_def_file(cmd_data_t *cmd_data)
634
char implib_file[1024];
637
char *export_args[1024];
638
int num_export_args = 0;
643
if (cmd_data->output_name) {
644
strcpy(def_file, cmd_data->output_name);
645
strcat(def_file, ".def");
646
hDef = fopen(def_file, "w");
649
fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
650
fprintf(hDef, "DATA NONSHARED\n");
651
fprintf(hDef, "EXPORTS\n");
654
for (a=0; a < cmd_data->num_obj_files; a++) {
655
cmd_size += strlen(cmd_data->obj_files[a]) + 1;
658
cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
659
cmd = (char *)malloc(cmd_size);
660
strcpy(cmd, GEN_EXPORTS);
662
for (a=0; a < cmd_data->num_obj_files; a++) {
664
strcat(cmd, cmd_data->obj_files[a] );
668
strcat(cmd, def_file);
670
export_args[num_export_args++] = SHELL_CMD;
671
export_args[num_export_args++] = "-c";
672
export_args[num_export_args++] = cmd;
673
export_args[num_export_args++] = NULL;
674
spawnvp(P_WAIT, export_args[0], export_args);
675
cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
677
/* Now make an import library for the dll */
679
export_args[num_export_args++] = DEF2IMPLIB_CMD;
680
export_args[num_export_args++] = "-o";
682
strcpy(implib_file, ".libs/");
683
strcat(implib_file, cmd_data->stub_name);
684
ext = strrchr(implib_file, '.');
689
strcat(implib_file, ".");
690
strcat(implib_file, STATIC_LIB_EXT);
692
export_args[num_export_args++] = implib_file;
693
export_args[num_export_args++] = def_file;
694
export_args[num_export_args++] = NULL;
695
spawnvp(P_WAIT, export_args[0], export_args);
702
/* returns just a file's name without path or extension */
703
char *nameof(char *fullpath)
707
char *name = strrchr(fullpath, '/');
710
name = strrchr(fullpath, '\\');
719
strcpy(buffer, name);
720
ext = strrchr(buffer, '.');
724
return strdup(buffer);
732
char *truncate_dll_name(char *path)
734
/* Cut DLL name down to 8 characters after removing any mod_ prefix */
735
char *tmppath = strdup(path);
736
char *newname = strrchr(tmppath, '/') + 1;
737
char *ext = strrchr(tmppath, '.');
745
if (strncmp(newname, "mod_", 4) == 0) {
746
strcpy(newname, newname + 4);
751
strcpy(newname + 8, strchr(newname, '.'));