ccanlint: Allow path to gcov to be overriden
authorDavid Gibson <david@gibson.dropbear.id.au>
Wed, 18 Jan 2017 03:23:51 +0000 (14:23 +1100)
committerDavid Gibson <david@gibson.dropbear.id.au>
Wed, 18 Jan 2017 23:23:33 +0000 (10:23 +1100)
Currently ccanlint always assumes that the coverage tool can be
invoked under the command "gcov".

However, the coverage tool generally needs to be closely matched to
the compiler version.  So, the current behaviour won't work with
compilers other than gcc, like clang.  It won't even work for a gcc
version which isn't the standard system one matching gcov.

To address this, allow the command for the coverage tool to be
overridden on the ccanlint command line with a new --gcov option.  We
also allow it to be overridden for make check with a GCOV make
variable.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Makefile
tools/ccanlint/ccanlint.c
tools/gcov.c
tools/tools.h

index d1e08a375277269a1004d301487a9a01621b0154..7f57869ed2dd7663c073aac3b1fc3c2ba48eff02 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -62,6 +62,9 @@ LINT_DEPS := $(LINT_SRCS:%.c=%.d) $(LINT).d
 LINT_CCAN_MODULES := asort autodata dgraph ilog lbalance ptr_valid strmap
 LINT_CCAN_SRCS := $(wildcard $(LINT_CCAN_MODULES:%=ccan/%/*.c))
 LINT_OBJS := $(LINT_SRCS:%.c=%.o) $(LINT_CCAN_SRCS:%.c=%.o) $(TOOLS_OBJS)
+ifneq ($(GCOV),)
+LINT_GCOV = --gcov="$(GCOV)"
+endif
 $(LINT): $(LINT).c $(LINT_OBJS)
        $(PRE)$(CC) $(CCAN_CFLAGS) $(DEP_CFLAGS) $(LINT).c $(LINT_OBJS) -lm -o $@
 
@@ -72,7 +75,7 @@ TEST_DEPS := $(MODULES:%=%/.d)
 
 # We produce .ok files when the tests succeed
 %.ok: $(LINT) %info
-       $(PRE)$(LINT) $(LINT_OPTS$(notdir $@)) --deps-fail-ignore $(LINTFLAGS) $(dir $*) && touch $@
+       $(PRE)$(LINT) $(LINT_OPTS$(notdir $@)) --deps-fail-ignore $(LINT_GCOV) $(LINTFLAGS) $(dir $*) && touch $@
 
 check: $(MODULES:%=%/.ok)
 fastcheck: $(MODULES:%=%/.fast.ok)
index f06f200b8daf0017ebe68fc655ac393747e7cbf6..237e412817d8f99ff44d9e68afeed050365d89b6 100644 (file)
@@ -616,6 +616,7 @@ int main(int argc, char *argv[])
        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;
+       const char *override_gcov = NULL;
        
        /* Empty graph node to which we attach everything else. */
        dgraph_init_node(&top.node);
@@ -644,6 +645,8 @@ int main(int argc, char *argv[])
                         NULL, &override_compiler, "set the compiler");
        opt_register_arg("--cflags <flags>", opt_set_const_charp,
                         NULL, &override_cflags, "set the compiler flags");
+       opt_register_arg("--gcov <coverage tool>", opt_set_const_charp,
+                        NULL, &override_gcov, "set the coverage tool");
        opt_register_noarg("--deps-fail-ignore", opt_set_bool,
                           &deps_fail_ignore,
                           "don't fail if external dependencies are missing");
@@ -688,6 +691,8 @@ int main(int argc, char *argv[])
                cflags = override_cflags;
        if (override_compiler)
                compiler = override_compiler;
+       if (override_gcov)
+               gcov = override_gcov;
 
        if (argc == 1)
                pass = test_module(&top.node, cwd, "",
index f922d8d97ed1dc5496213d81840305c0d99c5985..c36f69b09da87500ed9654b82234a33544f39bf4 100644 (file)
@@ -2,16 +2,28 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
+const char *gcov; /* = NULL */
+
 bool run_gcov(const void *ctx, unsigned int *time_ms, char **output,
              const char *fmt, ...)
 {
+       const char *cmd = gcov;
        char *args;
        va_list ap;
        bool rc;
 
+       if (!gcov) {
+#ifdef __GNUC__
+               cmd = "gcov";
+#endif
+       }
+
+       if (!cmd)
+               return false;
+
        va_start(ap, fmt);
        args = tal_vfmt(ctx, fmt, ap);
-       rc = run_command(ctx, time_ms, output, "gcov %s", args);
+       rc = run_command(ctx, time_ms, output, "%s %s", cmd, args);
        tal_free(args);
        return rc;
 }
@@ -20,6 +32,13 @@ const char *gcov_unavailable(void *ctx)
 {
        const char *err = NULL;
 
+       /* 
+        * If the user has specified a path, assume they know what
+        * they're doing
+        */
+       if (gcov)
+               return NULL;
+
 #ifdef __GNUC__
        unsigned int timeleft = default_timeout_ms;
        char *output;
index e5aaee2f9c4d0d898bcd7840b66c3bc9c8fcd8d8..257a14ae18b1857bb9a2e29764302ce147d6b647 100644 (file)
@@ -103,6 +103,7 @@ extern const unsigned int default_timeout_ms;
 const char *find_ccan_dir(const char *base);
 
 /* Run gcov coverage tool */
+extern const char *gcov;
 const char *gcov_unavailable(void *ctx);
 bool run_gcov(const void *ctx, unsigned int *time_ms, char **output,
              const char *fmt, ...);