From 2d3b9559bf569f137cefb7f8386a0dc58e33c81f Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 18 Feb 2017 09:55:34 +0100 Subject: tcctools.c: integrate tiny_libmaker/_impdef usage: tcc -ar [rcsv] lib files... tcc -impdef lib.dll [-v] [-o lib.def] also: - support more files with -c: tcc -c f1.c f2.c ... - fix a bug which caused tcc f1.c f2.S to produce no asm - allow tcc -ar @listfile too - change prototype: _void_ tcc_set_options(...) - apply -Wl,-whole-archive when a librariy is given as libxxx.a also (not just for -lxxx) --- tcc.c | 339 ++++++++++++++++++++++++------------------------------------------ 1 file changed, 121 insertions(+), 218 deletions(-) (limited to 'tcc.c') diff --git a/tcc.c b/tcc.c index c5a1f0e..2ca3bb8 100644 --- a/tcc.c +++ b/tcc.c @@ -23,69 +23,7 @@ #else #include "tcc.h" #endif - -static void print_paths(const char *msg, char **paths, int nb_paths) -{ - int i; - printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); - for(i = 0; i < nb_paths; i++) - printf(" %s\n", paths[i]); -} - -static void display_info(TCCState *s, int what) -{ - switch (what) { - case 0: - printf("tcc version %s (" -#ifdef TCC_TARGET_I386 - "i386" -#elif defined TCC_TARGET_X86_64 - "x86-64" -#elif defined TCC_TARGET_C67 - "C67" -#elif defined TCC_TARGET_ARM - "ARM" -# ifdef TCC_ARM_HARDFLOAT - " Hard Float" -# endif -#elif defined TCC_TARGET_ARM64 - "AArch64" -# ifdef TCC_ARM_HARDFLOAT - " Hard Float" -# endif -#endif -#ifdef TCC_TARGET_PE - " Windows" -#elif defined(__APPLE__) - /* Current Apple OS name as of 2016 */ - " macOS" -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - " FreeBSD" -#elif defined(__DragonFly__) - " DragonFly BSD" -#elif defined(__NetBSD__) - " NetBSD" -#elif defined(__OpenBSD__) - " OpenBSD" -#elif defined(__linux__) - " Linux" -#else - " Unidentified system" -#endif - ")\n", TCC_VERSION); - break; - case 1: - printf("install: %s\n", s->tcc_lib_path); - /* print_paths("programs", NULL, 0); */ - print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths); - print_paths("libraries", s->library_paths, s->nb_library_paths); -#ifndef TCC_TARGET_PE - print_paths("crt", s->crt_paths, s->nb_crt_paths); - printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); -#endif - break; - } -} +#include "tcctools.c" static void help(void) { @@ -100,7 +38,8 @@ static void help(void) " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" " -w disable all warnings\n" " -v show version\n" - " -vv show included files (as sole argument: show search paths)\n" + " -vv show included files (as sole argument show search paths)\n" + " -h show this help\n" " -bench show compilation statistics\n" "Preprocessor options:\n" " -Idir add include path 'dir'\n" @@ -146,115 +85,75 @@ static void help(void) #endif #ifdef TCC_TARGET_X86_64 " -mno-sse disable floats on x86-64\n" +#endif + "Tools:\n" + " create library : tcc -ar [rcsv] lib.a files\n" +#ifdef TCC_TARGET_PE + " create .def file : tcc -impdef lib.dll [-v] [-o lib.def]\n" #endif ); } -/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */ -#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 -#ifdef _WIN32 -#include - -static char *str_replace(const char *str, const char *p, const char *r) -{ - const char *s, *s0; - char *d, *d0; - int sl, pl, rl; - - sl = strlen(str); - pl = strlen(p); - rl = strlen(r); - for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) { - for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) { - if (d) { - memcpy(d, s0, sl = s - s0), d += sl; - memcpy(d, r, rl), d += rl; - } else - sl += rl - pl; - } - if (d) { - strcpy(d, s0); - return d0; - } - } -} -static int execvp_win32(const char *prog, char **argv) -{ - int ret; char **p; - /* replace all " by \" */ - for (p = argv; *p; ++p) - if (strchr(*p, '"')) - *p = str_replace(*p, "\"", "\\\""); - ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv); - if (-1 == ret) - return ret; - cwait(&ret, ret, WAIT_CHILD); - exit(ret); -} -#define execvp execvp_win32 -#endif -static void exec_other_tcc(TCCState *s, char **argv, int option) +static void version(void) { - char child_path[4096], *a0 = argv[0]; const char *target; - int l; - - switch (option) { - + printf("tcc version %s (" #ifdef TCC_TARGET_I386 - case 32: break; - case 64: target = "x86_64"; -#else - case 64: break; - case 32: target = "i386"; - + "i386" +#elif defined TCC_TARGET_X86_64 + "x86-64" +#elif defined TCC_TARGET_C67 + "C67" +#elif defined TCC_TARGET_ARM + "ARM" +# ifdef TCC_ARM_HARDFLOAT + " Hard Float" +# endif +#elif defined TCC_TARGET_ARM64 + "AArch64" +# ifdef TCC_ARM_HARDFLOAT + " Hard Float" +# endif #endif - l = tcc_basename(a0) - a0; - snprintf(child_path, sizeof child_path, #ifdef TCC_TARGET_PE - "%.*s%s-win32-tcc" + " Windows" +#elif defined(__APPLE__) + /* Current Apple OS name as of 2016 */ + " macOS" +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + " FreeBSD" +#elif defined(__DragonFly__) + " DragonFly BSD" +#elif defined(__NetBSD__) + " NetBSD" +#elif defined(__OpenBSD__) + " OpenBSD" +#elif defined(__linux__) + " Linux" #else - "%.*s%s-tcc" + " Unidentified system" #endif - , l, a0, target); - if (strcmp(a0, child_path)) { - if (s->verbose > 0) - printf("tcc: using '%s'\n", child_path + l), fflush(stdout); - execvp(argv[0] = child_path, argv); - } - tcc_error("'%s' not found", child_path + l); - } + ")\n", TCC_VERSION); } -#else -#define exec_other_tcc(s, argv, option) -#endif -static void gen_makedeps(TCCState *s, const char *target, const char *filename) +static void print_dirs(const char *msg, char **paths, int nb_paths) { - FILE *depout; - char buf[1024]; int i; + printf("%s:\n%s", msg, nb_paths ? "" : " -\n"); + for(i = 0; i < nb_paths; i++) + printf(" %s\n", paths[i]); +} - if (!filename) { - /* compute filename automatically: dir/file.o -> dir/file.d */ - snprintf(buf, sizeof buf, "%.*s.d", - (int)(tcc_fileextension(target) - target), target); - filename = buf; - } - - if (s->verbose) - printf("<- %s\n", filename); - - /* XXX return err codes instead of error() ? */ - depout = fopen(filename, "w"); - if (!depout) - tcc_error("could not open '%s'", filename); - - fprintf(depout, "%s: \\\n", target); - for (i=0; inb_target_deps; ++i) - fprintf(depout, " %s \\\n", s->target_deps[i]); - fprintf(depout, "\n"); - fclose(depout); +static void print_search_dirs(TCCState *s) +{ + printf("install: %s\n", s->tcc_lib_path); + /* print_dirs("programs", NULL, 0); */ + print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); + print_dirs("libraries", s->library_paths, s->nb_library_paths); +#ifndef TCC_TARGET_PE + print_dirs("crt", s->crt_paths, s->nb_crt_paths); + printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); +#endif } static char *default_outputfile(TCCState *s, const char *first_file) @@ -296,109 +195,113 @@ static unsigned getclock_ms(void) int main(int argc, char **argv) { TCCState *s; - int ret, optind, i; + int ret, opt, n = 0; unsigned start_time = 0; - const char *first_file = NULL; + const char *first_file; +redo: s = tcc_new(); + opt = tcc_parse_args(s, &argc, &argv, 1); + + if (n == 0) { + if (opt == OPT_HELP) + return help(), 1; + if (opt == OPT_M32 || opt == OPT_M64) + tcc_tool_cross(s, argv, opt); /* never returns */ + if (s->verbose) + version(); + if (opt == OPT_AR) + return tcc_tool_ar(s, argc, argv); +#ifdef TCC_TARGET_PE + if (opt == OPT_IMPDEF) + return tcc_tool_impdef(s, argc, argv); +#endif + if (opt == OPT_V) + return 0; - optind = tcc_parse_args(s, argc - 1, argv + 1); - - tcc_set_environment(s); - - if (optind == 0) { - help(); - return 1; - } - - if (s->cross_target) - exec_other_tcc(s, argv, s->cross_target); + tcc_set_environment(s); - if (s->verbose) - display_info(s, 0); + if (opt == OPT_PRINT_DIRS) { + /* initialize search dirs */ + tcc_set_output_type(s, TCC_OUTPUT_MEMORY); + print_search_dirs(s); + return 0; + } - if (s->nb_files == 0) { - if (optind == 1) { - if (s->print_search_dirs || s->verbose == 2) { - tcc_set_output_type(s, TCC_OUTPUT_MEMORY); - display_info(s, 1); - return 1; + n = s->nb_files; + if (n == 0) + tcc_error("no input files\n"); + + if (s->output_type == TCC_OUTPUT_PREPROCESS) { + if (!s->outfile) { + s->ppfp = stdout; + } else { + s->ppfp = fopen(s->outfile, "w"); + if (!s->ppfp) + tcc_error("could not write '%s'", s->outfile); } - if (s->verbose) - return 1; + } else if (s->output_type == TCC_OUTPUT_OBJ) { + if (s->nb_libraries != 0 && !s->option_r) + tcc_error("cannot specify libraries with -c"); + if (n > 1 && s->outfile) + tcc_error("cannot specify output file with -c many files"); + } else { + if (s->option_pthread) + tcc_set_options(s, "-lpthread"); } - tcc_error("no input files\n"); - } - /* check -c consistency : only single file handled. XXX: checks file type */ - if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) { - if (s->nb_libraries != 0) - tcc_error("cannot specify libraries with -c"); - /* accepts only a single input file */ - if (s->nb_files != 1) - tcc_error("cannot specify multiple files with -c"); + if (s->do_bench) + start_time = getclock_ms(); } if (s->output_type == 0) s->output_type = TCC_OUTPUT_EXE; tcc_set_output_type(s, s->output_type); - if (s->output_type == TCC_OUTPUT_PREPROCESS) { - if (!s->outfile) { - s->ppfp = stdout; - } else { - s->ppfp = fopen(s->outfile, "w"); - if (!s->ppfp) - tcc_error("could not write '%s'", s->outfile); - } - } else if (s->output_type != TCC_OUTPUT_OBJ) { - if (s->option_pthread) - tcc_set_options(s, "-lpthread"); - } - - if (s->do_bench) - start_time = getclock_ms(); - /* compile or add each files or library */ - for(i = ret = 0; i < s->nb_files && ret == 0; i++) { - struct filespec *f = s->files[i]; - if (f->type >= AFF_TYPE_LIB) { - s->alacarte_link = f->type == AFF_TYPE_LIB; + for (first_file = NULL, ret = 0;;) { + struct filespec *f = s->files[s->nb_files - n]; + s->filetype = f->type; + s->alacarte_link = f->alacarte; + if (f->type == AFF_TYPE_LIB) { if (tcc_add_library_err(s, f->name) < 0) ret = 1; } else { if (1 == s->verbose) printf("-> %s\n", f->name); - s->filetype = f->type; - if (tcc_add_file(s, f->name) < 0) - ret = 1; if (!first_file) first_file = f->name; + if (tcc_add_file(s, f->name) < 0) + ret = 1; } - s->filetype = AFF_TYPE_NONE; + s->filetype = 0; s->alacarte_link = 1; + if (ret || --n == 0 || s->output_type == TCC_OUTPUT_OBJ) + break; } if (s->output_type == TCC_OUTPUT_PREPROCESS) { if (s->outfile) fclose(s->ppfp); - } else if (0 == ret) { if (s->output_type == TCC_OUTPUT_MEMORY) { #ifdef TCC_IS_NATIVE - ret = tcc_run(s, argc - 1 - optind, argv + 1 + optind); + ret = tcc_run(s, argc, argv); #endif } else { if (!s->outfile) s->outfile = default_outputfile(s, first_file); - ret = !!tcc_output_file(s, s->outfile); - if (s->gen_deps && !ret) + if (tcc_output_file(s, s->outfile)) + ret = 1; + else if (s->gen_deps) gen_makedeps(s, s->outfile, s->deps_outfile); } } - if (s->do_bench) + if (s->do_bench && ret == 0 && n == 0) tcc_print_stats(s, getclock_ms() - start_time); tcc_delete(s); + if (ret == 0 && n) + goto redo; /* compile more files with -c */ return ret; } -- cgit v1.3.1