]> git.ozlabs.org Git - ccan/blobdiff - tools/ccanlint/ccanlint.c
tools/ccanlint: don't assert on relative directories for -d.
[ccan] / tools / ccanlint / ccanlint.c
index 83549cc968ffb71feb36da499453e3a3e996deec..158195cbdef04adf4c6ca1323ccc68c3862b1f1b 100644 (file)
@@ -43,13 +43,11 @@ int verbose = 0;
 static struct ccanlint_map tests;
 bool safe_mode = false;
 bool keep_results = false;
+bool non_ccan_deps = false;
+bool build_failed = false;
 static bool targeting = false;
 static unsigned int timeout;
 
-/* These are overridden at runtime if we can find config.h */
-const char *compiler = NULL;
-const char *cflags = NULL;
-
 const char *config_header;
 
 const char *ccan_dir;
@@ -93,10 +91,11 @@ static const char *dep_failed(struct manifest *m)
        return "dependency couldn't run";
 }
 
-static bool cannot_run(struct dgraph_node *node, void *unused)
+static bool cannot_run(struct dgraph_node *node, void *all)
 {
        struct ccanlint *c = container_of(node, struct ccanlint, node);
        c->can_run = dep_failed;
+
        return true;
 }
 
@@ -559,10 +558,12 @@ static char *opt_set_target(const char *arg, struct dgraph_node *all)
 
 static bool run_tests(struct dgraph_node *all,
                      bool summary,
+                     bool deps_fail_ignore,
                      struct manifest *m,
                      const char *prefix)
 {
        struct run_info run;
+       const char *comment = "";
 
        run.quiet = summary;
        run.m = m;
@@ -570,9 +571,18 @@ static bool run_tests(struct dgraph_node *all,
        run.score = run.total = 0;
        run.pass = true;
 
+       non_ccan_deps = build_failed = false;
+
        dgraph_traverse_to(all, run_test, &run);
 
-       printf("%sTotal score: %u/%u\n", prefix, run.score, run.total);
+       /* We can completely fail if we're missing external stuff: ignore */
+       if (deps_fail_ignore && non_ccan_deps && build_failed) {
+               comment = " (missing non-ccan dependencies?)";
+               run.pass = true;
+       }
+       printf("%sTotal score: %u/%u%s\n",
+              prefix, run.score, run.total, comment);
+
        return run.pass;
 }
 
@@ -585,17 +595,33 @@ static bool add_to_all(const char *member, struct ccanlint *c,
        return true;
 }
 
+static bool test_module(struct dgraph_node *all,
+                       const char *dir, const char *prefix, bool summary,
+                       bool deps_fail_ignore)
+{
+       struct manifest *m = get_manifest(autofree(), dir);
+       char *testlink = path_join(NULL, temp_dir(), "test");
+
+       /* Create a symlink from temp dir back to src dir's
+        * test directory. */
+       unlink(testlink);
+       if (symlink(path_join(m, dir, "test"), testlink) != 0)
+               err(1, "Creating test symlink in %s", temp_dir());
+
+       return run_tests(all, summary, deps_fail_ignore, m, prefix);
+}
+
 int main(int argc, char *argv[])
 {
-       bool summary = false, pass = true;
+       bool summary = false, pass = true, deps_fail_ignore = false;
        unsigned int i;
-       struct manifest *m;
        const char *prefix = "";
-       char *dir = path_cwd(NULL), *base_dir = dir, *testlink;
-       struct dgraph_node all;
+       char *cwd = path_cwd(NULL), *dir;
+       struct ccanlint top;  /* cannot_run may try to set ->can_run */
+       const char *override_compiler = NULL, *override_cflags = NULL;
        
        /* Empty graph node to which we attach everything else. */
-       dgraph_init_node(&all);
+       dgraph_init_node(&top.node);
 
        opt_register_early_noarg("--verbose|-v", opt_inc_intval, &verbose,
                                 "verbose mode (up to -vvvv)");
@@ -614,12 +640,16 @@ int main(int argc, char *argv[])
        opt_register_arg("--timeout <milleseconds>", opt_set_uintval,
                         NULL, &timeout,
                         "ignore (terminate) tests that are slower than this");
-       opt_register_arg("-t|--target <testname>", opt_set_target, NULL, &all,
+       opt_register_arg("-t|--target <testname>", opt_set_target, NULL,
+                        &top.node,
                         "only run one test (and its prerequisites)");
        opt_register_arg("--compiler <compiler>", opt_set_const_charp,
-                        NULL, &compiler, "set the compiler");
+                        NULL, &override_compiler, "set the compiler");
        opt_register_arg("--cflags <flags>", opt_set_const_charp,
-                        NULL, &cflags, "set the compiler flags");
+                        NULL, &override_cflags, "set the compiler flags");
+       opt_register_noarg("--deps-fail-ignore", opt_set_bool,
+                          &deps_fail_ignore,
+                          "don't fail if external dependencies are missing");
        opt_register_noarg("-?|-h|--help", opt_usage_and_exit,
                           "\nA program for checking and guiding development"
                           " of CCAN modules.",
@@ -644,54 +674,43 @@ int main(int argc, char *argv[])
        opt_parse(&argc, argv, opt_log_stderr_exit);
 
        if (!targeting)
-               strmap_iterate(&tests, add_to_all, &all);
-
-       /* This links back to the module's test dir. */
-       testlink = tal_fmt(NULL, "%s/test", temp_dir());
+               strmap_iterate(&tests, add_to_all, &top.node);
 
-       /* Defaults to pwd. */
-       if (argc == 1) {
-               i = 1;
-               goto got_dir;
-       }
-
-       for (i = 1; i < argc; i++) {
-               dir = argv[i];
-
-               if (dir[0] != '/')
-                       dir = tal_fmt(NULL, "%s/%s", base_dir, dir);
-               while (strends(dir, "/"))
-                       dir[strlen(dir)-1] = '\0';
-
-       got_dir:
-               /* We assume there's a ccan/ in there somewhere... */
-               if (i == 1) {
-                       ccan_dir = find_ccan_dir(dir);
-                       if (!ccan_dir)
-                               errx(1, "Cannot find ccan/ base directory in %s",
-                                    dir);
-                       config_header = read_config_header(ccan_dir,
-                                                          &compiler, &cflags,
-                                                          verbose > 1);
+       if (argc == 1)
+               dir = cwd;
+       else
+               dir = path_simplify(NULL, take(path_join(NULL, cwd, argv[1])));
+
+       ccan_dir = find_ccan_dir(dir);
+       if (!ccan_dir)
+               errx(1, "Cannot find ccan/ base directory in %s", dir);
+       config_header = read_config_header(ccan_dir, verbose > 1);
+
+       /* We do this after read_config_header has set compiler & cflags */
+       if (override_cflags)
+               cflags = override_cflags;
+       if (override_compiler)
+               compiler = override_compiler;
+
+       if (argc == 1)
+               pass = test_module(&top.node, cwd, "",
+                                  summary, deps_fail_ignore);
+       else {
+               for (i = 1; i < argc; i++) {
+                       dir = path_canon(NULL,
+                                        take(path_join(NULL, cwd, argv[i])));
+                       if (!dir)
+                               err(1, "Cannot get canonical name of '%s'",
+                                   argv[i]);
+
+                       prefix = path_join(NULL, ccan_dir, "ccan");
+                       prefix = path_rel(NULL, take(prefix), dir);
+                       prefix = tal_strcat(NULL, take(prefix), ": ");
+
+                       pass &= test_module(&top.node, dir, prefix, summary,
+                                           deps_fail_ignore);
+                       reset_tests(&top.node);
                }
-
-               if (dir != base_dir)
-                       prefix = tal_strcat(NULL,
-                                           take(path_basename(NULL,dir)),
-                                           ": ");
-
-               m = get_manifest(autofree(), dir);
-
-               /* Create a symlink from temp dir back to src dir's
-                * test directory. */
-               unlink(testlink);
-               if (symlink(tal_fmt(m, "%s/test", dir), testlink) != 0)
-                       err(1, "Creating test symlink in %s", temp_dir());
-
-               if (!run_tests(&all, summary, m, prefix))
-                       pass = false;
-
-               reset_tests(&all);
        }
        return pass ? 0 : 1;
 }