From a919a373da07305e763d1cb4ecb3a5a44bdebb2a Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Sun, 20 Jun 2010 19:49:58 +0400 Subject: Add input files/libs and reloc_output switch to TCCState files[0], and reloc_outpu will be needed for (upcoming in the next patch) "compute default outfile name" refactored into libtcc function. Also, since for symmetry and from libification point of view, it makes some sense to also put all information about what was given as input to compilation into TCCState, let's not only put files[0], but all files and all libraries given explicitely by user. One point: I've used bitfield for reloc_output & trimmed down output_type to 8 bits so that TCCState stays the same in size, and also access to output_type is (hopefully) is not slower. By the way -- as of today, sizeof(TCCState) on i686-pc-linux-gnu is 2884 bytes... --- libtcc.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'libtcc.h') diff --git a/libtcc.h b/libtcc.h index 339dec1..13efcd2 100644 --- a/libtcc.h +++ b/libtcc.h @@ -103,6 +103,13 @@ LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); /* set CONFIG_TCCDIR at runtime */ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); + +/*****************************/ +/* Miscellaneous */ + +/* Get default target filename for this compilation */ +LIBTCCAPI const char *tcc_default_target(TCCState *s); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 0c928da96d5fb8fe8f929db40b2d807053113f35 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Sun, 20 Jun 2010 20:08:12 +0400 Subject: tcc: Draft suppoprt for -MD/-MF options In build systems, this is used to automatically collect target dependencies, e.g. ---- 8< (hello.c) ---- #include "hello.h" #include int main() { printf("Hello World!\n"); return 0; } $ tcc -MD -c hello.c # -> hello.o, hello.d $ cat hello.d hello.o : \ hello.c \ hello.h \ /usr/include/stdio.h \ /usr/include/features.h \ /usr/include/bits/predefs.h \ /usr/include/sys/cdefs.h \ /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h \ /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs-32.h \ /home/kirr/local/tcc/lib/tcc/include/stddef.h \ /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ /usr/include/bits/typesizes.h \ /usr/include/libio.h \ /usr/include/_G_config.h \ /usr/include/wchar.h \ /home/kirr/local/tcc/lib/tcc/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ NOTE: gcc supports -MD only for .c -> .o, but in tcc, we generate dependencies for whatever action is being taken. E.g. for .c -> exe, the result will be: $ tcc -MD -o hello hello.c # -> hello, hello.d hello: \ /usr/lib/crt1.o \ /usr/lib/crti.o \ hello.c \ hello.h \ /usr/include/stdio.h \ /usr/include/features.h \ /usr/include/bits/predefs.h \ /usr/include/sys/cdefs.h \ /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h \ /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs-32.h \ /home/kirr/local/tcc/lib/tcc/include/stddef.h \ /usr/include/bits/types.h \ /usr/include/bits/wordsize.h \ /usr/include/bits/typesizes.h \ /usr/include/libio.h \ /usr/include/_G_config.h \ /usr/include/wchar.h \ /home/kirr/local/tcc/lib/tcc/include/stdarg.h \ /usr/include/bits/stdio_lim.h \ /usr/include/bits/sys_errlist.h \ /usr/lib/libc.so \ /lib/libc.so.6 \ /usr/lib/ld-linux.so.2 \ /lib/ld-linux.so.2 \ /usr/lib/libc_nonshared.a \ /lib/libc.so.6 \ /usr/lib/libc_nonshared.a \ /home/kirr/local/tcc/lib/tcc/libtcc1.a \ /usr/lib/crtn.o \ So tcc dependency generator is a bit more clever than one used in gcc :) Also, I've updated TODO and Changelog (in not-yet-released section). v2: (Taking inputs from grischka and me myself) - put code to generate deps file into a function. - used tcc_fileextension() instead of open-coding - generate deps only when compilation/preprocessing was successful v3: - use pstrcpy instead of snprintf(buf, sizeof(buf), "%s", ...) --- Changelog | 4 ++++ TODO | 1 - libtcc.c | 39 +++++++++++++++++++++++++++++++++++++++ libtcc.h | 7 +++++++ tcc.c | 33 +++++++++++++++++++++++++++------ tcc.h | 4 ++++ tccpp.c | 3 +++ 7 files changed, 84 insertions(+), 7 deletions(-) (limited to 'libtcc.h') diff --git a/Changelog b/Changelog index b271054..528d927 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +not released: + +- Add support for -MD/-MF (automatically generate dependencies for make) + version 0.9.25: - first support for x86-64 target (Shinichiro Hamaji) diff --git a/TODO b/TODO index 6f49c5d..9d19153 100644 --- a/TODO +++ b/TODO @@ -46,7 +46,6 @@ Missing features: - disable-asm and disable-bcheck options - __builtin_expect() - improve '-E' option. -- add '-MD' option - atexit (Nigel Horne) - packed attribute - C99: add variable size arrays (gcc 3.2 testsuite issue) diff --git a/libtcc.c b/libtcc.c index 1c963b5..92c7cad 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1041,6 +1041,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) dynarray_reset(&s1->input_files, &s1->nb_input_files); dynarray_reset(&s1->input_libs, &s1->nb_input_libs); + dynarray_reset(&s1->target_deps, &s1->nb_target_deps); #ifdef HAVE_SELINUX munmap (s1->write_mem, s1->mem_size); @@ -1092,6 +1093,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) goto the_end; } + /* update target deps */ + dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, + tcc_strdup(filename)); + if (flags & AFF_PREPROCESS) { ret = tcc_preprocess(s1); goto the_end; @@ -1585,3 +1590,37 @@ LIBTCCAPI const char *tcc_default_target(TCCState *s) return outfile_default; } + + +LIBTCCAPI void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename) +{ + FILE *depout; + char buf[1024], *ext; + int i; + + if (!target) + target = tcc_default_target(s); + + if (!filename) { + /* compute filename automatically + * dir/file.o -> dir/file.d */ + pstrcpy(buf, sizeof(buf), target); + ext = tcc_fileextension(buf); + pstrcpy(ext, sizeof(buf) - (ext-buf), ".d"); + filename = buf; + } + + if (s->verbose) + printf("<- %s\n", filename); + + /* XXX return err codes instead of error() ? */ + depout = fopen(filename, "w"); + if (!depout) + error("could not open '%s'", filename); + + fprintf(depout, "%s : \\\n", target); + for (i=0; inb_target_deps; ++i) + fprintf(depout, "\t%s \\\n", s->target_deps[i]); + fprintf(depout, "\n"); + fclose(depout); +} diff --git a/libtcc.h b/libtcc.h index 13efcd2..bf328d3 100644 --- a/libtcc.h +++ b/libtcc.h @@ -110,6 +110,13 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); /* Get default target filename for this compilation */ LIBTCCAPI const char *tcc_default_target(TCCState *s); +/* Generate make dependencies for target and store them into file + * + * !target - use default target name + * !filename - use (target.o -> target.d) + */ +LIBTCCAPI void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename); + #ifdef __cplusplus } #endif diff --git a/tcc.c b/tcc.c index 705f5e2..b9478d9 100644 --- a/tcc.c +++ b/tcc.c @@ -32,6 +32,8 @@ static int output_type; static int reloc_output; static const char *outfile; static int do_bench = 0; +static int gen_deps; +static const char *deps_outfile; #define TCC_OPTION_HAS_ARG 0x0001 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ @@ -74,6 +76,9 @@ static void help(void) #ifdef CONFIG_TCC_BACKTRACE " -bt N show N callers in stack traces\n" #endif + "Misc options:\n" + " -MD generate target dependencies for make\n" + " -MF depfile put generated dependencies here\n" ); } @@ -115,6 +120,8 @@ enum { TCC_OPTION_w, TCC_OPTION_pipe, TCC_OPTION_E, + TCC_OPTION_MD, + TCC_OPTION_MF, TCC_OPTION_x, }; @@ -154,6 +161,8 @@ static const TCCOption tcc_options[] = { { "w", TCC_OPTION_w, 0 }, { "pipe", TCC_OPTION_pipe, 0}, { "E", TCC_OPTION_E, 0}, + { "MD", TCC_OPTION_MD, 0}, + { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG }, { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG }, { NULL }, }; @@ -374,6 +383,12 @@ static int parse_args(TCCState *s, int argc, char **argv) case TCC_OPTION_E: output_type = TCC_OUTPUT_PREPROCESS; break; + case TCC_OPTION_MD: + gen_deps = 1; + break; + case TCC_OPTION_MF: + deps_outfile = optarg; + break; case TCC_OPTION_x: break; default: @@ -479,14 +494,20 @@ int main(int argc, char **argv) if (do_bench) tcc_print_stats(s, getclock_us() - start_time); - if (s->output_type == TCC_OUTPUT_PREPROCESS) { - if (outfile) - fclose(s->outfile); - } else if (s->output_type == TCC_OUTPUT_MEMORY) + if (s->output_type == TCC_OUTPUT_MEMORY) ret = tcc_run(s, argc - optind, argv + optind); else { - ret = tcc_output_file(s, outfile ? outfile : tcc_default_target(s)); - ret = ret ? 1 : 0; + if (s->output_type == TCC_OUTPUT_PREPROCESS) { + if (outfile) + fclose(s->outfile); + } else { + ret = tcc_output_file(s, outfile ? outfile : tcc_default_target(s)); + ret = ret ? 1 : 0; + } + + /* dump collected dependencies */ + if (gen_deps && !ret) + tcc_gen_makedeps(s, outfile, deps_outfile); } } diff --git a/tcc.h b/tcc.h index 8fd4408..bb3eb9f 100644 --- a/tcc.h +++ b/tcc.h @@ -525,6 +525,10 @@ struct TCCState { char **input_libs; int nb_input_libs; + /* automatically collected dependencies for this compilation */ + char **target_deps; + int nb_target_deps; + /* for tcc_relocate */ int runtime_added; void *runtime_mem; diff --git a/tccpp.c b/tccpp.c index 9a4cbca..2b735d1 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1491,6 +1491,9 @@ ST_FUNC void preprocess(int is_bof) #ifdef INC_DEBUG printf("%s: including %s\n", file->filename, buf1); #endif + /* update target deps */ + dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, + tcc_strdup(buf1)); /* XXX: fix current line init */ /* push current file in stack */ -- cgit v1.3.1