From 37ca11df87fa3cc97aca321a76e564e4058d6900 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 28 Jul 2008 13:04:17 +1000 Subject: [PATCH] Proper recursive dependencies (came from libantithread work) --- .bzrignore | 4 +++ Makefile | 40 ++++++++++++++++++++++------- tools/Makefile | 2 ++ tools/ccan_depends.c | 21 +++++++++++++++ tools/depends.c | 61 ++++++++++++++++++++++++++++++++------------ tools/namespacize.c | 1 + tools/run_tests.c | 35 +++++++++++++++++-------- 7 files changed, 127 insertions(+), 37 deletions(-) create mode 100644 tools/ccan_depends.c diff --git a/.bzrignore b/.bzrignore index 641dbd02..a1564670 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,8 +1,12 @@ _info .depends *~ +tools/ccan_depends tools/doc_extract tools/namespacize tools/run_tests tools/ccanlint/ccanlint tools/ccanlint/generated-init-tests +inter-depends +test-depends +lib-depends diff --git a/Makefile b/Makefile index b60874d7..03d0b82b 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,50 @@ # Hacky makefile to compile everything and run the tests in some kind of sane order. # V=--verbose for verbose tests. -CFLAGS=-O3 -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -Iccan -I. +CFLAGS=-g -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Werror -Iccan -I. -ALL=$(patsubst ccan/%/test, ccan/%, $(wildcard ccan/*/test)) -ALL_DEPENDS=$(patsubst %, %/.depends, $(ALL)) +ALL=$(patsubst ccan/%/test, %, $(wildcard ccan/*/test)) +ALL_DIRS=$(patsubst %, ccan/%, $(ALL)) +ALL_DEPENDS=$(patsubst %, ccan/%/.depends, $(ALL)) +ALL_LIBS=$(patsubst %, ccan/lib%.a, $(ALL)) -test-all: $(ALL_DEPENDS) - $(MAKE) `for f in $(ALL); do echo test-$$f test-$$f; while read d; do echo test-$$d test-$$f; done < $$f/.depends; done | tsort` +test: $(ALL_DIRS:%=test-%) distclean: clean rm -f */_info rm -f $(ALL_DEPENDS) -$(ALL_DEPENDS): %/.depends: %/_info - @$< depends > $@ || ( rm -f $@; exit 1 ) +$(ALL_DEPENDS): $(ALL_DIRS:=/_info) -test-ccan/%: tools/run_tests +$(ALL_DEPENDS): %/.depends: tools/ccan_depends + tools/ccan_depends $* > $@ || ( rm -f $@; exit 1 ) + +foo: + echo $(ALL_LIBS) + +$(ALL_LIBS): + $(AR) r $@ $^ + +test-ccan/%: tools/run_tests ccan/lib%.a @echo Testing $*... @if tools/run_tests $(V) ccan/$* | grep ^'not ok'; then exit 1; else exit 0; fi ccanlint: tools/ccanlint/ccanlint clean: tools-clean - rm -f `find . -name '*.o'` `find . -name '.depends'` + $(RM) `find . -name '*.o'` `find . -name '.depends'` `find . -name '*.a'` + $(RM) inter-depends lib-depends test-depends + +inter-depends: $(ALL_DEPENDS) + for f in $(ALL_DEPENDS); do echo test-ccan/`basename \`dirname $$f\``: `sed -n 's,ccan/\(.*\),ccan/lib\1.a,p' < $$f`; done > $@ + +test-depends: $(ALL_DEPENDS) + for f in $(ALL_DEPENDS); do echo test-ccan/`basename \`dirname $$f\``: `sed -n 's,ccan/\(.*\),test-ccan/\1,p' < $$f`; done > $@ + +lib-depends: $(foreach D,$(ALL),$(wildcard $D/*.[ch])) + for c in $(ALL); do echo ccan/lib$$c.a: `ls ccan/$$c/*.c | grep -v /_info.c | sed 's/.c$$/.o/'`; done > $@ include tools/Makefile +-include inter-depends +-include test-depends +-include lib-depends diff --git a/tools/Makefile b/tools/Makefile index 8f576302..e9574760 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,3 +1,5 @@ +tools/ccan_depends: tools/ccan_depends.o tools/depends.o tools/split.o tools/grab_file.o ccan/talloc/talloc.o + tools/run_tests: tools/run_tests.o tools/depends.o tools/split.o tools/grab_file.o ccan/tap/tap.o ccan/talloc/talloc.o tools/doc_extract: tools/doc_extract.c ccan/talloc/talloc.o diff --git a/tools/ccan_depends.c b/tools/ccan_depends.c new file mode 100644 index 00000000..982d13b3 --- /dev/null +++ b/tools/ccan_depends.c @@ -0,0 +1,21 @@ +#include "tools.h" +#include +#include +#include +#include "string/string.h" + +int main(int argc, char *argv[]) +{ + char **deps; + unsigned int i; + + if (argc != 2) + errx(1, "Usage: ccan_depends \n" + "Spits out all the ccan dependencies (recursively)"); + + deps = get_deps(NULL, argv[1]); + for (i = 0; deps[i]; i++) + if (strstarts(deps[i], "ccan/")) + printf("%s\n", deps[i]); + return 0; +} diff --git a/tools/depends.c b/tools/depends.c index aaae03a9..f416257a 100644 --- a/tools/depends.c +++ b/tools/depends.c @@ -1,9 +1,11 @@ #include "talloc/talloc.h" +#include "string/string.h" #include "tools.h" #include +#include -static char ** __attribute__((format(printf, 2, 3))) -lines_from_cmd(const void *ctx, char *format, ...) +static char ** __attribute__((format(printf, 3, 4))) +lines_from_cmd(const void *ctx, unsigned int *num, char *format, ...) { va_list ap; char *cmd, *buffer; @@ -22,30 +24,55 @@ lines_from_cmd(const void *ctx, char *format, ...) err(1, "Reading from '%s'", cmd); pclose(p); - return split(ctx, buffer, "\n", NULL); + return split(ctx, buffer, "\n", num); } -static char *build_info(const void *ctx, const char *dir) +static char **get_one_deps(const void *ctx, const char *dir, unsigned int *num) { - char *file, *cfile, *cmd; + char **deps, *cmd; + + cmd = talloc_asprintf(ctx, "%s/_info depends", dir); + deps = lines_from_cmd(cmd, num, "%s", cmd); + if (!deps) + err(1, "Could not run '%s'", cmd); + return deps; +} - cfile = talloc_asprintf(ctx, "%s/%s", dir, "_info.c"); - file = talloc_asprintf(cfile, "%s/%s", dir, "_info"); - cmd = talloc_asprintf(file, "gcc " CFLAGS " -o %s %s", file, cfile); - if (system(cmd) != 0) - errx(1, "Failed to compile %s", file); +static bool have_dep(char **deps, unsigned int num, const char *dep) +{ + unsigned int i; - return file; + for (i = 0; i < num; i++) + if (streq(deps[i], dep)) + return true; + return false; } +/* Gets all the dependencies, recursively. */ char **get_deps(const void *ctx, const char *dir) { - char **deps, *cmd; + char **deps; + unsigned int i, num; - cmd = talloc_asprintf(ctx, "%s depends", build_info(ctx, dir)); - deps = lines_from_cmd(cmd, cmd); - if (!deps) - err(1, "Could not run '%s'", cmd); + deps = get_one_deps(ctx, dir, &num); + for (i = 0; i < num; i++) { + char **newdeps; + unsigned int j, newnum; + + if (!strstarts(deps[i], "ccan/")) + continue; + + newdeps = get_one_deps(ctx, deps[i], &newnum); + + /* Should be short, so brute-force out dups. */ + for (j = 0; j < newnum; j++) { + if (have_dep(deps, num, newdeps[j])) + continue; + + deps = talloc_realloc(NULL, deps, char *, num + 2); + deps[num++] = newdeps[j]; + deps[num] = NULL; + } + } return deps; } - diff --git a/tools/namespacize.c b/tools/namespacize.c index 3e656c84..8c6c6632 100644 --- a/tools/namespacize.c +++ b/tools/namespacize.c @@ -10,6 +10,7 @@ #include #include #include +#include "string/string.h" #include "talloc/talloc.h" #include "tools.h" diff --git a/tools/run_tests.c b/tools/run_tests.c index aa7f90a9..2f657d05 100644 --- a/tools/run_tests.c +++ b/tools/run_tests.c @@ -19,7 +19,7 @@ static int verbose; struct test_type { const char *name; - void (*testfn)(struct test_type *t, const char *name); + void (*testfn)(const char *dir, struct test_type *t, const char *name); }; struct test @@ -98,14 +98,27 @@ static void add_obj(const char *testdir, const char *name) objs = obj; } -static int build(const char *name, int fail) +static int build(const char *dir, const char *name, int fail) { const char *cmd; int ret; + char *externals = talloc_strdup(name, ""); + char **deps; - cmd = talloc_asprintf(name, "gcc " CFLAGS " %s -o %s %s %s%s", + for (deps = get_deps(objs, dir); *deps; deps++) { + char *end; + if (!strstarts(*deps, "ccan/")) + continue; + + end = strrchr(*deps, '/') + 1; + /* ccan/foo -> ccan/libfoo.a */ + externals = talloc_asprintf_append(externals, + " ccan/lib%s.a", end); + } + + cmd = talloc_asprintf(name, "gcc " CFLAGS " %s -o %s %s %s%s%s", fail ? "-DFAIL" : "", - output_name(name), name, obj_list(), + output_name(name), name, obj_list(), externals, verbose ? "" : "> /dev/null 2>&1"); if (verbose) @@ -118,17 +131,17 @@ static int build(const char *name, int fail) return ret; } -static void compile_ok(struct test_type *t, const char *name) +static void compile_ok(const char *dir, struct test_type *t, const char *name) { - ok(build(name, 0) == 0, "%s %s", t->name, name); + ok(build(dir, name, 0) == 0, "%s %s", t->name, name); } -static void compile_fail(struct test_type *t, const char *name) +static void compile_fail(const char *dir, struct test_type *t, const char *name) { - if (build(name, 0) != 0) + if (build(dir, name, 0) != 0) fail("non-FAIL build %s", name); else - ok(build(name, 1) > 0, "%s %s", t->name, name); + ok(build(dir, name, 1) > 0, "%s %s", t->name, name); } static void run(const char *name) @@ -188,13 +201,13 @@ int main(int argc, char *argv[]) } } - plan_tests(num_tests + num_objs); + plan_tests(num_tests + num_objs + (num_objs ? 1 : 0)); /* First all the extra object compilations. */ compile_objs(); /* Do all the test compilations. */ for (test = tests; test; test = test->next) - test->type->testfn(test->type, test->name); + test->type->testfn(argv[1], test->type, test->name); cleanup_objs(); -- 2.39.2