History

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 <stdio.h> 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", ...)

Kirill Smelkov committed 16 years ago

Commit 0c928da1 parent bdae4a57 files · +84 −7Browse files

Unified · Split

7 files
  1. Changelog +4 −0
  2. TODO +0 −1
  3. libtcc.c +39 −0
  4. libtcc.h +7 −0
  5. tcc.c +27 −6
  6. tcc.h +4 −0
  7. tccpp.c +3 −0
Changelog+4−0
@@ -1,3 +1,7 @@
1+not released:
2+
3+- Add support for -MD/-MF (automatically generate dependencies for make)
4+
15 version 0.9.25:
26
37 - first support for x86-64 target (Shinichiro Hamaji)
TODO+0−1
@@ -46,7 +46,6 @@ Missing features: · 45 unmodified lines
4646 - disable-asm and disable-bcheck options
4747 - __builtin_expect()
4848 - improve '-E' option.
49−- add '-MD' option
5049 - atexit (Nigel Horne)
5150 - packed attribute
5251 - C99: add variable size arrays (gcc 3.2 testsuite issue)
libtcc.c+39−0
@@ -1041,6 +1041,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 1040 unmodified lines
10411041
10421042 dynarray_reset(&s1->input_files, &s1->nb_input_files);
10431043 dynarray_reset(&s1->input_libs, &s1->nb_input_libs);
1044+ dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
10441045
10451046 #ifdef HAVE_SELINUX
10461047 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) · 45 unmodified lines
10921093 goto the_end;
10931094 }
10941095
1096+ /* update target deps */
1097+ dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
1098+ tcc_strdup(filename));
1099+
10951100 if (flags & AFF_PREPROCESS) {
10961101 ret = tcc_preprocess(s1);
10971102 goto the_end;
@@ -1585,3 +1590,37 @@ LIBTCCAPI const char *tcc_default_target(TCCState *s) · 487 unmodified lines
15851590
15861591 return outfile_default;
15871592 }
1593+
1594+
1595+LIBTCCAPI void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename)
1596+{
1597+ FILE *depout;
1598+ char buf[1024], *ext;
1599+ int i;
1600+
1601+ if (!target)
1602+ target = tcc_default_target(s);
1603+
1604+ if (!filename) {
1605+ /* compute filename automatically
1606+ * dir/file.o -> dir/file.d */
1607+ pstrcpy(buf, sizeof(buf), target);
1608+ ext = tcc_fileextension(buf);
1609+ pstrcpy(ext, sizeof(buf) - (ext-buf), ".d");
1610+ filename = buf;
1611+ }
1612+
1613+ if (s->verbose)
1614+ printf("<- %s\n", filename);
1615+
1616+ /* XXX return err codes instead of error() ? */
1617+ depout = fopen(filename, "w");
1618+ if (!depout)
1619+ error("could not open '%s'", filename);
1620+
1621+ fprintf(depout, "%s : \\\n", target);
1622+ for (i=0; i<s->nb_target_deps; ++i)
1623+ fprintf(depout, "\t%s \\\n", s->target_deps[i]);
1624+ fprintf(depout, "\n");
1625+ fclose(depout);
1626+}
libtcc.h+7−0
@@ -110,6 +110,13 @@ LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); · 109 unmodified lines
110110 /* Get default target filename for this compilation */
111111 LIBTCCAPI const char *tcc_default_target(TCCState *s);
112112
113+/* Generate make dependencies for target and store them into file
114+ *
115+ * !target - use default target name
116+ * !filename - use (target.o -> target.d)
117+ */
118+LIBTCCAPI void tcc_gen_makedeps(TCCState *s, const char *target, const char *filename);
119+
113120 #ifdef __cplusplus
114121 }
115122 #endif
tcc.c+27−6
@@ -32,6 +32,8 @@ static int output_type; · 31 unmodified lines
3232 static int reloc_output;
3333 static const char *outfile;
3434 static int do_bench = 0;
35+static int gen_deps;
36+static const char *deps_outfile;
3537
3638 #define TCC_OPTION_HAS_ARG 0x0001
3739 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
@@ -74,6 +76,9 @@ static void help(void) · 36 unmodified lines
7476 #ifdef CONFIG_TCC_BACKTRACE
7577 " -bt N show N callers in stack traces\n"
7678 #endif
79+ "Misc options:\n"
80+ " -MD generate target dependencies for make\n"
81+ " -MF depfile put generated dependencies here\n"
7782 );
7883 }
7984
@@ -115,6 +120,8 @@ enum { · 35 unmodified lines
115120 TCC_OPTION_w,
116121 TCC_OPTION_pipe,
117122 TCC_OPTION_E,
123+ TCC_OPTION_MD,
124+ TCC_OPTION_MF,
118125 TCC_OPTION_x,
119126 };
120127
@@ -154,6 +161,8 @@ static const TCCOption tcc_options[] = { · 33 unmodified lines
154161 { "w", TCC_OPTION_w, 0 },
155162 { "pipe", TCC_OPTION_pipe, 0},
156163 { "E", TCC_OPTION_E, 0},
164+ { "MD", TCC_OPTION_MD, 0},
165+ { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
157166 { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
158167 { NULL },
159168 };
@@ -374,6 +383,12 @@ static int parse_args(TCCState *s, int argc, char **argv) · 214 unmodified lines
374383 case TCC_OPTION_E:
375384 output_type = TCC_OUTPUT_PREPROCESS;
376385 break;
386+ case TCC_OPTION_MD:
387+ gen_deps = 1;
388+ break;
389+ case TCC_OPTION_MF:
390+ deps_outfile = optarg;
391+ break;
377392 case TCC_OPTION_x:
378393 break;
379394 default:
@@ -479,14 +494,20 @@ int main(int argc, char **argv) · 99 unmodified lines
479494 if (do_bench)
480495 tcc_print_stats(s, getclock_us() - start_time);
481496
482− if (s->output_type == TCC_OUTPUT_PREPROCESS) {
483− if (outfile)
484− fclose(s->outfile);
485− } else if (s->output_type == TCC_OUTPUT_MEMORY)
497+ if (s->output_type == TCC_OUTPUT_MEMORY)
486498 ret = tcc_run(s, argc - optind, argv + optind);
487499 else {
488− ret = tcc_output_file(s, outfile ? outfile : tcc_default_target(s));
489− ret = ret ? 1 : 0;
500+ if (s->output_type == TCC_OUTPUT_PREPROCESS) {
501+ if (outfile)
502+ fclose(s->outfile);
503+ } else {
504+ ret = tcc_output_file(s, outfile ? outfile : tcc_default_target(s));
505+ ret = ret ? 1 : 0;
506+ }
507+
508+ /* dump collected dependencies */
509+ if (gen_deps && !ret)
510+ tcc_gen_makedeps(s, outfile, deps_outfile);
490511 }
491512 }
492513
tcc.h+4−0
@@ -525,6 +525,10 @@ struct TCCState { · 524 unmodified lines
525525 char **input_libs;
526526 int nb_input_libs;
527527
528+ /* automatically collected dependencies for this compilation */
529+ char **target_deps;
530+ int nb_target_deps;
531+
528532 /* for tcc_relocate */
529533 int runtime_added;
530534 void *runtime_mem;
tccpp.c+3−0
@@ -1491,6 +1491,9 @@ ST_FUNC void preprocess(int is_bof) · 1490 unmodified lines
14911491 #ifdef INC_DEBUG
14921492 printf("%s: including %s\n", file->filename, buf1);
14931493 #endif
1494+ /* update target deps */
1495+ dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
1496+ tcc_strdup(buf1));
14941497
14951498 /* XXX: fix current line init */
14961499 /* push current file in stack */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t