From: Rusty Russell Date: Tue, 23 Nov 2010 12:49:19 +0000 (+1030) Subject: ccanlint: build depends if necessary X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=451d97ad85e65061223f04dceaca0454c7b2201a ccanlint: build depends if necessary Now it will build copies of other ccan deps if it can't find them. --- diff --git a/tools/ccanlint/ccanlint.h b/tools/ccanlint/ccanlint.h index f5f7b51d..458bed54 100644 --- a/tools/ccanlint/ccanlint.h +++ b/tools/ccanlint/ccanlint.h @@ -26,6 +26,11 @@ struct manifest { char *basename; struct ccan_file *info_file; + /* Linked off deps. */ + struct list_node list; + /* Where our final compiled output is */ + char *compiled; + struct list_head c_files; struct list_head h_files; @@ -41,7 +46,7 @@ struct manifest { struct list_head mangled_examples; /* From tests/check_depends_exist.c */ - struct list_head dep_dirs; + struct list_head deps; }; struct manifest *get_manifest(const void *ctx, const char *dir); diff --git a/tools/ccanlint/compulsory_tests/build.c b/tools/ccanlint/compulsory_tests/build.c index 7c73f0d4..5bea548c 100644 --- a/tools/ccanlint/compulsory_tests/build.c +++ b/tools/ccanlint/compulsory_tests/build.c @@ -13,6 +13,7 @@ #include #include #include +#include "build.h" static const char *can_build(struct manifest *m) { @@ -33,12 +34,27 @@ static char *obj_list(const struct manifest *m) return list; } +char *build_module(struct manifest *m, bool keep, char **errstr) +{ + char *name = link_objects(m, m->basename, false, obj_list(m), errstr); + if (name) { + if (keep) { + char *realname = talloc_asprintf(m, "%s.o", m->dir); + /* We leave this object file around, all built. */ + if (!move_file(name, realname)) + err(1, "Renaming %s to %s", name, realname); + name = realname; + } + } + return name; +} + static void do_build(struct manifest *m, bool keep, unsigned int *timeleft, struct score *score) { - char *filename, *errstr; + char *errstr; if (list_empty(&m->c_files)) { /* No files? No score, but we "pass". */ @@ -47,19 +63,12 @@ static void do_build(struct manifest *m, return; } - filename = link_objects(m, m->basename, false, obj_list(m), &errstr); - if (!filename) { - score->error = "The object file didn't build"; + m->compiled = build_module(m, keep, &errstr); + if (!m->compiled) { score_file_error(score, NULL, 0, errstr); return; } - if (keep) { - char *realname = talloc_asprintf(m, "%s.o", m->dir); - /* We leave this object file around, all built. */ - if (!move_file(filename, realname)) - err(1, "Renaming %s to %s", filename, realname); - } score->pass = true; score->score = score->total; } diff --git a/tools/ccanlint/compulsory_tests/build.h b/tools/ccanlint/compulsory_tests/build.h new file mode 100644 index 00000000..64abca44 --- /dev/null +++ b/tools/ccanlint/compulsory_tests/build.h @@ -0,0 +1,4 @@ +#ifndef CCANLINT_BUILD_H +#define CCANLINT_BUILD_H +char *build_module(struct manifest *m, bool keep, char **errstr); +#endif /* CCANLINT_BUILD_H */ diff --git a/tools/ccanlint/compulsory_tests/check_build.c b/tools/ccanlint/compulsory_tests/check_build.c index 830ea914..8cd9ed86 100644 --- a/tools/ccanlint/compulsory_tests/check_build.c +++ b/tools/ccanlint/compulsory_tests/check_build.c @@ -24,12 +24,13 @@ static const char *can_build(struct manifest *m) static char *obj_list(const struct manifest *m) { char *list = talloc_strdup(m, ""); - struct ccan_file *i; + struct manifest *i; /* Other CCAN deps. */ - list_for_each(&m->dep_dirs, i, list) { + list_for_each(&m->deps, i, list) { if (i->compiled) - list = talloc_asprintf_append(list, "%s ", i->compiled); + list = talloc_asprintf_append(list, "%s ", + i->compiled); } return list; } diff --git a/tools/ccanlint/compulsory_tests/check_depends_built.c b/tools/ccanlint/compulsory_tests/check_depends_built.c index 41e5d888..3bd82f83 100644 --- a/tools/ccanlint/compulsory_tests/check_depends_built.c +++ b/tools/ccanlint/compulsory_tests/check_depends_built.c @@ -13,6 +13,7 @@ #include #include #include +#include "build.h" static const char *can_build(struct manifest *m) { @@ -21,50 +22,63 @@ static const char *can_build(struct manifest *m) return NULL; } -/* FIXME: recursive ccanlint if they ask for it. */ -static bool expect_obj_file(const char *dir) +static bool expect_obj_file(struct manifest *m) { - struct manifest *dep_man; - bool has_c_files; + /* If it has C files, we expect an object file built from them. */ + return !list_empty(&m->c_files); +} - dep_man = get_manifest(dir, dir); +static char *build_subdir_objs(struct manifest *m) +{ + struct ccan_file *i; - /* If it has C files, we expect an object file built from them. */ - has_c_files = !list_empty(&dep_man->c_files); - talloc_free(dep_man); - return has_c_files; + list_for_each(&m->c_files, i, list) { + char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name); + char *output; + + i->compiled = maybe_temp_file(m, "", false, fullfile); + if (!compile_object(m, fullfile, ccan_dir, "", i->compiled, + &output)) { + talloc_free(i->compiled); + i->compiled = NULL; + return talloc_asprintf(m, + "Dependency %s" + " did not build:\n%s", + m->basename, output); + } + } + return NULL; } static void check_depends_built(struct manifest *m, bool keep, unsigned int *timeleft, struct score *score) { - struct ccan_file *i; + struct manifest *i; struct stat st; - list_for_each(&m->dep_dirs, i, list) { - if (!expect_obj_file(i->fullname)) + list_for_each(&m->deps, i, list) { + char *errstr; + if (!expect_obj_file(i)) continue; - i->compiled = talloc_asprintf(i, "%s.o", i->fullname); - if (stat(i->compiled, &st) != 0) { - score->error = "Dependencies are not built"; - score_file_error(score, i, 0, - talloc_asprintf(score, - "object file %s", - i->compiled)); - i->compiled = NULL; - } - } + i->compiled = talloc_asprintf(i, "%s.o", i->dir); + if (stat(i->compiled, &st) == 0) + continue; - /* We may need libtap for testing, unless we're "tap" */ - if (!streq(m->basename, "tap") - && (!list_empty(&m->run_tests) || !list_empty(&m->api_tests))) { - char *tapobj = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir); - if (stat(tapobj, &st) != 0) { + if (verbose >= 2) + printf(" Building dependency %s\n", i->dir); + score->error = build_subdir_objs(i); + if (score->error) + return; + i->compiled = build_module(i, keep, &errstr); + if (!i->compiled) { score->error = talloc_asprintf(score, - "tap object file not built"); - } + "Dependency %s" + " did not build:\n%s", + i->basename, errstr); + return; + } } if (!score->error) { @@ -75,7 +89,7 @@ static void check_depends_built(struct manifest *m, struct ccanlint depends_built = { .key = "depends-built", - .name = "Module's CCAN dependencies are already built", + .name = "Module's CCAN dependencies can be found or built", .check = check_depends_built, .can_run = can_build, }; diff --git a/tools/ccanlint/compulsory_tests/check_depends_exist.c b/tools/ccanlint/compulsory_tests/check_depends_exist.c index e2437083..d1f33b64 100644 --- a/tools/ccanlint/compulsory_tests/check_depends_exist.c +++ b/tools/ccanlint/compulsory_tests/check_depends_exist.c @@ -14,17 +14,23 @@ #include #include -static void add_dep(struct manifest *m, const char *dep, struct score *score) +static bool add_dep(struct manifest *m, const char *dep, struct score *score) { struct stat st; - struct ccan_file *f; + struct manifest *subm; + char *dir = talloc_asprintf(m, "%s/%s", ccan_dir, dep); - f = new_ccan_file(m, ccan_dir, talloc_strdup(m, dep)); - if (stat(f->fullname, &st) != 0) { - score->error = "Depends don't exist"; - score_file_error(score, f, 0, "could not stat"); - } else - list_add_tail(&m->dep_dirs, &f->list); + /* FIXME: get_manifest has a tendency to exit. */ + if (stat(dir, &st) != 0) { + score->error + = talloc_asprintf(m, + "Could not stat dependency %s: %s", + dir, strerror(errno)); + return false; + } + subm = get_manifest(m, dir); + list_add_tail(&m->deps, &subm->list); + return true; } static void check_depends_exist(struct manifest *m, @@ -47,12 +53,19 @@ static void check_depends_exist(struct manifest *m, if (!strstarts(deps[i], "ccan/")) continue; - add_dep(m, deps[i], score); + if (!add_dep(m, deps[i], score)) + return; } - if (!score->error) { - score->pass = true; - score->score = score->total; + + /* We may need libtap for testing, unless we're "tap" */ + if (!streq(m->basename, "tap") + && (!list_empty(&m->run_tests) || !list_empty(&m->api_tests))) { + if (!add_dep(m, "ccan/tap", score)) + return; } + + score->pass = true; + score->score = score->total; } struct ccanlint depends_exist = { diff --git a/tools/ccanlint/file_analysis.c b/tools/ccanlint/file_analysis.c index d17940a5..59dd40fd 100644 --- a/tools/ccanlint/file_analysis.c +++ b/tools/ccanlint/file_analysis.c @@ -173,6 +173,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir) struct list_head *list; m->info_file = NULL; + m->compiled = NULL; list_head_init(&m->c_files); list_head_init(&m->h_files); list_head_init(&m->api_tests); @@ -184,7 +185,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir) list_head_init(&m->other_files); list_head_init(&m->examples); list_head_init(&m->mangled_examples); - list_head_init(&m->dep_dirs); + list_head_init(&m->deps); olddir = talloc_getcwd(NULL); if (!olddir) diff --git a/tools/ccanlint/tests/build-coverage.c b/tools/ccanlint/tests/build-coverage.c index 9415647f..31bb7882 100644 --- a/tools/ccanlint/tests/build-coverage.c +++ b/tools/ccanlint/tests/build-coverage.c @@ -50,16 +50,12 @@ static bool build_module_objs_with_coverage(struct manifest *m, bool keep, return true; } +/* FIXME: Merge this into one place. */ static char *obj_list(const struct manifest *m, const char *modobjs) { - char *list; + char *list = talloc_strdup(m, ""); struct ccan_file *i; - - /* We expect to be linked with tap, unless that's us. */ - if (!streq(m->basename, "tap")) - list = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir); - else - list = talloc_strdup(m, ""); + struct manifest *subm; /* Objects from any other C files. */ list_for_each(&m->other_test_c_files, i, list) @@ -69,9 +65,10 @@ static char *obj_list(const struct manifest *m, const char *modobjs) list = talloc_append_string(list, modobjs); /* Other ccan modules (don't need coverage versions of those). */ - list_for_each(&m->dep_dirs, i, list) { - if (i->compiled) - list = talloc_asprintf_append(list, " %s", i->compiled); + list_for_each(&m->deps, subm, list) { + if (subm->compiled) + list = talloc_asprintf_append(list, " %s", + subm->compiled); } return list; diff --git a/tools/ccanlint/tests/compile_tests.c b/tools/ccanlint/tests/compile_tests.c index e95849b2..80ebe913 100644 --- a/tools/ccanlint/tests/compile_tests.c +++ b/tools/ccanlint/tests/compile_tests.c @@ -22,16 +22,12 @@ static const char *can_build(struct manifest *m) return NULL; } +/* FIXME: Merge this into one place. */ static char *obj_list(const struct manifest *m, bool link_with_module) { - char *list; + char *list = talloc_strdup(m, ""); struct ccan_file *i; - - /* We expect to be linked with tap, unless that's us. */ - if (!streq(m->basename, "tap")) - list = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir); - else - list = talloc_strdup(m, ""); + struct manifest *subm; /* Objects from any other C files. */ list_for_each(&m->other_test_c_files, i, list) @@ -43,9 +39,10 @@ static char *obj_list(const struct manifest *m, bool link_with_module) list = talloc_asprintf_append(list, " %s", i->compiled); /* Other ccan modules. */ - list_for_each(&m->dep_dirs, i, list) { - if (i->compiled) - list = talloc_asprintf_append(list, " %s", i->compiled); + list_for_each(&m->deps, subm, list) { + if (subm->compiled) + list = talloc_asprintf_append(list, " %s", + subm->compiled); } return list; diff --git a/tools/ccanlint/tests/depends_accurate.c b/tools/ccanlint/tests/depends_accurate.c index 3ba19f60..943fa350 100644 --- a/tools/ccanlint/tests/depends_accurate.c +++ b/tools/ccanlint/tests/depends_accurate.c @@ -28,19 +28,16 @@ static char *strip_spaces(const void *ctx, char *line) return p; } -static bool has_dep(struct manifest *m, const char *depname, bool tap_ok) +static bool has_dep(struct manifest *m, const char *depname) { - struct ccan_file *f; - - if (tap_ok && streq(depname, "ccan/tap")) - return true; + struct manifest *i; /* We can include ourselves, of course. */ - if (streq(depname + strlen("ccan/"), m->basename)) + if (streq(depname, m->basename)) return true; - list_for_each(&m->dep_dirs, f, list) { - if (streq(f->name, depname)) + list_for_each(&m->deps, i, list) { + if (streq(i->basename, depname)) return true; } return false; @@ -57,10 +54,6 @@ static void check_depends_accurate(struct manifest *m, &m->compile_ok_tests, &m->compile_fail_tests, &m->other_test_c_files) { struct ccan_file *f; - bool tap_ok; - - /* Including ccan/tap is fine for tests. */ - tap_ok = (list != &m->c_files && list != &m->h_files); list_for_each(list, f, list) { unsigned int i; @@ -74,11 +67,11 @@ static void check_depends_accurate(struct manifest *m, if (!strstarts(p, "#includeerror = "Includes a ccan module" " not listed in _info"; diff --git a/tools/ccanlint/tests/examples_compile.c b/tools/ccanlint/tests/examples_compile.c index 31b0a3ae..7cee7795 100644 --- a/tools/ccanlint/tests/examples_compile.c +++ b/tools/ccanlint/tests/examples_compile.c @@ -67,10 +67,12 @@ static char *add_dep(const struct manifest *m, char *list, const char *mod) return list; } +/* FIXME: Merge this into one place. */ static char *obj_list(const struct manifest *m, struct ccan_file *f) { char *list = talloc_strdup(m, ""); struct ccan_file *i; + struct manifest *subm; char **lines; /* Object files for this module. */ @@ -78,9 +80,10 @@ static char *obj_list(const struct manifest *m, struct ccan_file *f) list = talloc_asprintf_append(list, " %s", i->compiled); /* Other ccan modules we depend on. */ - list_for_each(&m->dep_dirs, i, list) { - if (i->compiled) - list = talloc_asprintf_append(list, " %s", i->compiled); + list_for_each(&m->deps, subm, list) { + if (subm->compiled) + list = talloc_asprintf_append(list, " %s", + subm->compiled); } /* Other modules implied by includes. */