diff --git a/main.c b/main.c index f729262..b0d1411 100644 --- a/main.c +++ b/main.c @@ -10,6 +10,7 @@ bool opt_fcommon = true; static FileType opt_x; static StringArray opt_include; static bool opt_E; +static bool opt_M; static bool opt_S; static bool opt_c; static bool opt_cc1; @@ -176,6 +177,11 @@ static void parse_args(int argc, char **argv) { continue; } + if (!strcmp(argv[i], "-M")) { + opt_M = true; + continue; + } + if (!strcmp(argv[i], "-cc1-input")) { base_file = argv[++i]; continue; @@ -326,6 +332,20 @@ static void print_tokens(Token *tok) { fprintf(out, "\n"); } +// If -M options is given, the compiler write a list of input files to +// stdout in a format that "make" command can read. This feature is +// used to automate file dependency management. +static void print_dependencies(void) { + FILE *out = open_file(opt_o ? opt_o : "-"); + fprintf(out, "%s:", replace_extn(base_file, ".o")); + + File **files = get_input_files(); + + for (int i = 0; files[i]; i++) + fprintf(out, " \\\n %s", files[i]->name); + fprintf(out, "\n\n"); +} + static Token *must_tokenize_file(char *path) { Token *tok = tokenize_file(path); if (!tok) @@ -369,6 +389,12 @@ static void cc1(void) { tok = append_tokens(tok, tok2); tok = preprocess(tok); + // If -M is given, print file dependencies. + if (opt_M) { + print_dependencies(); + return; + } + // If -E is given, print out preprocessed C code as a result. if (opt_E) { print_tokens(tok); @@ -551,7 +577,7 @@ int main(int argc, char **argv) { assert(type == FILE_C); // Just preprocess - if (opt_E) { + if (opt_E || opt_M) { run_cc1(argc, argv, input, NULL); continue; } diff --git a/test/driver.sh b/test/driver.sh index 8f8ecff..311535f 100755 --- a/test/driver.sh +++ b/test/driver.sh @@ -221,4 +221,11 @@ check '.so' $chibicc -hashmap-test check 'hashmap' +# -M +echo '#include "out2.h"' > $tmp/out.c +echo '#include "out3.h"' >> $tmp/out.c +touch $tmp/out2.h $tmp/out3.h +$chibicc -M -I$tmp $tmp/out.c | grep -q -z '^out.o: .*/out\.c .*/out2\.h .*/out3\.h' +check -M + echo OK