Browse Source

ccanlint: compile modules required by examples.

If an example #includes <ccan/foo/...> we assume it needs module foo,
but we would fail instead of building it if it isn't built.
Rusty Russell 15 years ago
parent
commit
2d4243996a

+ 1 - 0
tools/ccanlint/compulsory_tests/build.h

@@ -1,4 +1,5 @@
 #ifndef CCANLINT_BUILD_H
 #define CCANLINT_BUILD_H
 char *build_module(struct manifest *m, bool keep, char **errstr);
+char *build_submodule(struct manifest *m);
 #endif /* CCANLINT_BUILD_H */

+ 34 - 21
tools/ccanlint/compulsory_tests/check_depends_built.c

@@ -50,41 +50,54 @@ static char *build_subdir_objs(struct manifest *m)
 	return NULL;
 }
 
+char *build_submodule(struct manifest *m)
+{
+	char *errstr;
+	struct stat st;
+
+	if (m->compiled)
+		return NULL;
+
+	if (!expect_obj_file(m))
+		return NULL;
+
+	m->compiled = talloc_asprintf(m, "%s.o", m->dir);
+	if (stat(m->compiled, &st) == 0)
+		return NULL;
+
+	if (verbose >= 2)
+		printf("  Building dependency %s\n", m->dir);
+
+	errstr = build_subdir_objs(m);
+	if (errstr)
+		return errstr;
+
+	m->compiled = build_module(m, false, &errstr);
+	if (!m->compiled)
+		return errstr;
+	return NULL;
+}
+
 static void check_depends_built(struct manifest *m,
 				bool keep,
 				unsigned int *timeleft, struct score *score)
 {
 	struct manifest *i;
-	struct stat st;
 
 	list_for_each(&m->deps, i, list) {
-		char *errstr;
-		if (!expect_obj_file(i))
-			continue;
-
-		i->compiled = talloc_asprintf(i, "%s.o", i->dir);
-		if (stat(i->compiled, &st) == 0)
-			continue;
-
-		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) {
+		char *errstr = build_submodule(i);
+
+		if (errstr) {
 			score->error = talloc_asprintf(score,
 						       "Dependency %s"
 						       " did not build:\n%s",
 						       i->basename, errstr);
 			return;
-		}			
+		}
 	}
 
-	if (!score->error) {
-		score->pass = true;
-		score->score = score->total;
-	}
+	score->pass = true;
+	score->score = score->total;
 }
 
 struct ccanlint depends_built = {

+ 51 - 51
tools/ccanlint/tests/examples_compile.c

@@ -10,6 +10,8 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <assert.h>
+#include <err.h>
+#include "../compulsory_tests/build.h"
 
 static const char *can_run(struct manifest *m)
 {
@@ -20,85 +22,83 @@ static const char *can_run(struct manifest *m)
 	return NULL;
 }
 
-/* FIXME: We should build if it doesn't exist... */
-static bool expect_obj_file(const char *dir)
+static void add_mod(struct manifest ***deps, struct manifest *m)
 {
-	struct manifest *dep_man;
-	bool has_c_files;
-
-	dep_man = get_manifest(dir, dir);
-
-	/* 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;
+	unsigned int num = talloc_get_size(*deps) / sizeof(*deps);
+	*deps = talloc_realloc(NULL, *deps, struct manifest *, num + 1);
+	(*deps)[num] = m;
 }
 
-static char *add_dep(const struct manifest *m, char *list, const char *mod)
+static bool have_mod(struct manifest *deps[], const char *basename)
 {
-	char **deps, *obj;
 	unsigned int i;
 
-	/* Not ourselves. */
-	if (streq(m->basename, mod))
-		return list;
+	for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); i++)
+		if (strcmp(deps[i]->basename, basename) == 0)
+			return true;
+	return false;
+}
 
-	/* Not if there's no object file for that module */
-	if (!expect_obj_file(talloc_asprintf(list, "%s/ccan/%s", ccan_dir,mod)))
-		return list;
+static void add_dep(struct manifest ***deps, const char *basename)
+{
+	unsigned int i;
+	struct manifest *m;
+	char *errstr;
 
-	obj = talloc_asprintf(list, "%s/ccan/%s.o", ccan_dir, mod);
+	if (have_mod(*deps, basename))
+		return;
 
-	/* Not anyone we've already included. */
-	if (strstr(list, obj))
-		return list;
+	m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s",
+						ccan_dir, basename));
+	errstr = build_submodule(m);
+	if (errstr)
+		errx(1, "%s", errstr);
 
-	list = talloc_asprintf_append(list, " %s", obj);
+	add_mod(deps, m);
 
 	/* Get that modules depends as well... */
 	assert(!safe_mode);
-	deps = get_deps(m, talloc_asprintf(list, "%s/ccan/%s", ccan_dir, mod),
-			false, NULL);
+	if (m->info_file) {
+		char **infodeps;
+
+		infodeps = get_deps(m, m->dir, false, &m->info_file->compiled);
 
-	for (i = 0; deps[i]; i++) {
-		if (strstarts(deps[i], "ccan/"))
-			list = add_dep(m, list, deps[i] + strlen("ccan/"));
+		for (i = 0; infodeps[i]; i++) {
+			if (strstarts(infodeps[i], "ccan/"))
+				add_dep(deps, infodeps[i] + strlen("ccan/"));
+		}
 	}
-	return list;
 }
 
-/* FIXME: Merge this into one place. */
-static char *obj_list(const struct manifest *m, struct ccan_file *f)
+static char *obj_list(struct manifest *m, struct ccan_file *f)
 {
-	char *list = talloc_strdup(m, "");
-	struct manifest *subm;
-	char **lines;
-
-	/* This module. */
-	if (m->compiled)
-		list = talloc_asprintf_append(list, " %s", m->compiled);
+	struct manifest **deps = talloc_array(f, struct manifest *, 0);
+	char **lines, *list;
+	unsigned int i;
 
-	/* Other ccan modules we depend on. */
-	list_for_each(&m->deps, subm, list) {
-		if (subm->compiled)
-			list = talloc_asprintf_append(list, " %s",
-						      subm->compiled);
-	}
+	/* This one for a start. */
+	add_dep(&deps, m->basename);
 
 	/* Other modules implied by includes. */
 	for (lines = get_ccan_file_lines(f); *lines; lines++) {
 		unsigned preflen = strspn(*lines, " \t");
 		if (strstarts(*lines + preflen, "#include <ccan/")) {
-			const char *mod;
-			unsigned modlen;
+			char *modname;
 
-			mod = *lines + preflen + strlen("#include <ccan/");
-			modlen = strcspn(mod, "/");
-			mod = talloc_strndup(f, mod, modlen);
-			list = add_dep(m, list, mod);
+			modname = talloc_strdup(f, *lines + preflen
+						+ strlen("#include <ccan/"));
+			modname[strcspn(modname, "/")] = '\0';
+			if (!have_mod(deps, modname))
+				add_dep(&deps, modname);
 		}
 	}
 
+	list = talloc_strdup(f, "");
+	for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); i++) {
+		if (deps[i]->compiled)
+			list = talloc_asprintf_append(list, " %s",
+						      deps[i]->compiled);
+	}
 	return list;
 }