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", ...)
This commit is contained in:
33
tcc.c
33
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user