Browse Source

ccanlint: compile tests in parallel

Measuring ccanlint -d ccan/tdb2 on my dual core hyperthread laptop gives:
Before: 6:47
After: 5:59
Rusty Russell 14 years ago
parent
commit
4640e61b45
3 changed files with 67 additions and 17 deletions
  1. 15 0
      tools/ccanlint/async.c
  2. 7 0
      tools/ccanlint/ccanlint.h
  3. 45 17
      tools/ccanlint/tests/tests_compile.c

+ 15 - 0
tools/ccanlint/async.c

@@ -198,3 +198,18 @@ void *collect_command(bool *ok, char **output)
 	talloc_free(c);
 	return (void *)ctx;
 }
+
+/* Compile and link single C file, with object files, async. */
+void compile_and_link_async(const void *ctx, unsigned int time_ms,
+			    const char *cfile, const char *ccandir,
+			    const char *objs, const char *compiler,
+			    const char *cflags,
+			    const char *libs, const char *outfile)
+{
+	if (compile_verbose)
+		printf("Compiling and linking (async) %s\n", outfile);
+	run_command_async(ctx, time_ms,
+			  "%s %s -I%s -o %s %s %s %s",
+			  compiler, cflags,
+			  ccandir, outfile, cfile, objs, libs);
+}

+ 7 - 0
tools/ccanlint/ccanlint.h

@@ -239,6 +239,13 @@ void score_file_error(struct score *, struct ccan_file *f, unsigned line,
 void run_command_async(const void *ctx, unsigned int time_ms,
 		       const char *fmt, ...);
 
+/* Async version of compile_and_link. */
+void compile_and_link_async(const void *ctx, unsigned int time_ms,
+			    const char *cfile, const char *ccandir,
+			    const char *objs, const char *compiler,
+			    const char *cflags,
+			    const char *libs, const char *outfile);
+
 /* Get results of a command, returning ctx (and free it). */
 void *collect_command(bool *ok, char **output);
 

+ 45 - 17
tools/ccanlint/tests/tests_compile.c

@@ -95,30 +95,57 @@ static bool compile(const void *ctx,
 	return true;
 }
 
+static void compile_async(const void *ctx,
+			  struct manifest *m,
+			  struct ccan_file *file,
+			  bool link_with_module,
+			  bool keep,
+			  enum compile_type ctype,
+			  unsigned int time_ms)
+{
+	char *flags;
+
+	file->compiled[ctype] = maybe_temp_file(ctx, "", keep, file->fullname);
+	flags = talloc_asprintf(ctx, "%s%s",
+				cflags,
+				ctype == COMPILE_NOFEAT
+				? " "REDUCE_FEATURES_FLAGS : "");
+
+	compile_and_link_async(file, time_ms, file->fullname, ccan_dir,
+			       test_obj_list(m, link_with_module, ctype, ctype),
+			       compiler, flags, lib_list(m, ctype),
+			       file->compiled[ctype]);
+}
+
 static void compile_tests(struct manifest *m, bool keep,
 			  struct score *score,
-			  enum compile_type ctype)
+			  enum compile_type ctype,
+			  unsigned int time_ms)
 {
 	char *cmdout;
 	struct ccan_file *i;
 	struct list_head *list;
-	bool errors = false, warnings = false;
+	bool errors = false, warnings = false, ok;
 
 	foreach_ptr(list, &m->compile_ok_tests, &m->run_tests, &m->api_tests) {
 		list_for_each(list, i, list) {
-			if (!compile(score, m, i, false,
-				     list == &m->api_tests, keep,
-				     ctype, &cmdout)) {
-				score_file_error(score, i, 0,
-						 "Compile failed:\n%s",
-						 cmdout);
-				errors = true;
-			} else if (!streq(cmdout, "")) {
-				score_file_error(score, i, 0,
-						 "Compile gave warnings:\n%s",
-						 cmdout);
-				warnings = true;
-			}
+			compile_async(score, m, i,
+				      list == &m->api_tests, keep,
+				      ctype, time_ms);
+		}
+	}
+
+	while ((i = collect_command(&ok, &cmdout)) != NULL) {
+		if (!ok) {
+			score_file_error(score, i, 0,
+					 "Compile failed:\n%s",
+					 cmdout);
+			errors = true;
+		} else if (!streq(cmdout, "")) {
+			score_file_error(score, i, 0,
+					 "Compile gave warnings:\n%s",
+					 cmdout);
+			warnings = true;
 		}
 	}
 
@@ -156,11 +183,12 @@ static void compile_tests(struct manifest *m, bool keep,
 	score->score = score->total - warnings;
 }
 
+/* FIXME: If we time out, set *timeleft to 0 */
 static void do_compile_tests(struct manifest *m,
 			     bool keep,
 			     unsigned int *timeleft, struct score *score)
 {
-	compile_tests(m, keep, score, COMPILE_NORMAL);
+	compile_tests(m, keep, score, COMPILE_NORMAL, *timeleft);
 }
 
 struct ccanlint tests_compile = {
@@ -185,7 +213,7 @@ static void do_compile_tests_without_features(struct manifest *m,
 					      unsigned int *timeleft,
 					      struct score *score)
 {
-	compile_tests(m, keep, score, COMPILE_NOFEAT);
+	compile_tests(m, keep, score, COMPILE_NOFEAT, *timeleft);
 }
 
 struct ccanlint tests_compile_without_features = {