score->total = 0;
list_for_each(&m->c_files, i, list) {
- char *err;
+ char *output;
char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
i->compiled = maybe_temp_file(m, "", keep, fullfile);
- err = compile_object(m, fullfile, ccan_dir, "", i->compiled);
- if (err) {
+ if (!compile_object(m, fullfile, ccan_dir, "", i->compiled,
+ &output)) {
talloc_free(i->compiled);
score->error = "Compiling object files";
- score_file_error(score, i, 0, err);
+ score_file_error(score, i, 0, output);
}
+ talloc_free(output);
}
if (!score->error) {
score->pass = true;
unsigned int *timeleft, struct score *score)
{
char *contents;
- char *tmpfile;
+ char *tmpfile, *cmdout;
char *basename = talloc_asprintf(m, "%s/example.c", m->dir);
int fd;
err(1, "Failure writing to temporary file %s", tmpfile);
close(fd);
- score->error = compile_and_link(m, tmpfile, ccan_dir, obj_list(m), "",
- lib_list(m),
- maybe_temp_file(m, "", keep, tmpfile));
- if (!score->error) {
+ if (compile_and_link(score, tmpfile, ccan_dir, obj_list(m), "",
+ lib_list(m),
+ maybe_temp_file(m, "", keep, tmpfile),
+ &cmdout)) {
score->pass = true;
score->score = score->total;
+ } else {
+ score->error = cmdout;
}
}
unsigned int *timeleft, struct score *score)
{
char *contents;
- char *tmpsrc, *tmpobj;
+ char *tmpsrc, *tmpobj, *cmdout;
int fd;
struct ccan_file *mainh = main_header(m);
err(1, "writing to temporary file %s", tmpsrc);
close(fd);
- score->error = compile_object(m, tmpsrc, ccan_dir, "", tmpobj);
- if (score->error) {
- score->error = talloc_asprintf(score,
- "#include of the main header file:\n%s",
- score->error);
- } else {
+ if (compile_object(score, tmpsrc, ccan_dir, "", tmpobj, &cmdout)) {
score->pass = true;
score->score = score->total;
+ } else {
+ score->error = talloc_asprintf(score,
+ "#include of the main header file:\n%s",
+ cmdout);
}
}
static const char *can_run_coverage(struct manifest *m)
{
unsigned int timeleft = default_timeout_ms;
- char *output = run_command(m, &timeleft, "gcov -h");
+ char *output;
- if (output)
+ if (!run_command(m, &timeleft, &output, "gcov -h"))
return talloc_asprintf(m, "No gcov support: %s", output);
return NULL;
}
char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
i->cov_compiled = maybe_temp_file(m, "", keep, fullfile);
- err = compile_object(m, fullfile, ccan_dir, "",
- i->cov_compiled);
- if (err) {
+ if (!compile_object(m, fullfile, ccan_dir, "",
+ i->cov_compiled, &err)) {
score_file_error(score, i, 0, err);
talloc_free(i->cov_compiled);
i->cov_compiled = NULL;
const char *modobjs,
bool keep)
{
- char *errmsg;
+ char *output;
file->cov_compiled = maybe_temp_file(ctx, "", keep, file->fullname);
- errmsg = compile_and_link(ctx, file->fullname, ccan_dir,
- obj_list(m, modobjs),
- COVERAGE_CFLAGS,
- lib_list(m), file->cov_compiled);
- if (errmsg) {
+ if (!compile_and_link(ctx, file->fullname, ccan_dir,
+ obj_list(m, modobjs),
+ COVERAGE_CFLAGS,
+ lib_list(m), file->cov_compiled, &output)) {
talloc_free(file->cov_compiled);
file->cov_compiled = NULL;
- return errmsg;
+ return output;
}
-
+ talloc_free(output);
return NULL;
}
bool keep,
struct ccan_file *cfile)
{
+ char *output;
cfile->compiled = maybe_temp_file(m, ".o", keep, cfile->fullname);
- return compile_object(m, cfile->fullname, ccan_dir, "",
- cfile->compiled);
+ if (compile_object(m, cfile->fullname, ccan_dir, "",
+ cfile->compiled, &output)) {
+ talloc_free(output);
+ return NULL;
+ }
+ return output;
}
static void do_compile_test_helpers(struct manifest *m,
char *errmsg;
file->compiled = maybe_temp_file(ctx, "", keep, file->fullname);
- errmsg = compile_and_link(ctx, file->fullname, ccan_dir,
- obj_list(m, link_with_module),
- fail ? "-DFAIL" : "",
- lib_list(m), file->compiled);
- if (errmsg) {
+ if (!compile_and_link(ctx, file->fullname, ccan_dir,
+ obj_list(m, link_with_module),
+ fail ? "-DFAIL" : "",
+ lib_list(m), file->compiled, &errmsg)) {
talloc_free(file->compiled);
return errmsg;
}
+ talloc_free(errmsg);
return NULL;
}
char *errmsg;
file->compiled = maybe_temp_file(ctx, "", keep, file->fullname);
- errmsg = compile_and_link(ctx, file->fullname, ccan_dir,
- obj_list(m, file),
- "", lib_list(m), file->compiled);
- if (errmsg) {
+ if (!compile_and_link(ctx, file->fullname, ccan_dir,
+ obj_list(m, file),
+ "", lib_list(m), file->compiled, &errmsg)) {
talloc_free(file->compiled);
file->compiled = NULL;
return errmsg;
}
+ talloc_free(errmsg);
return NULL;
}
struct ccan_file *i;
char *cmdout;
char *covcmd;
- bool ok;
bool full_gcov = (verbose > 1);
struct list_head *list;
/* Run them all. */
foreach_ptr(list, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) {
- cmdout = run_command(m, timeleft, i->cov_compiled);
- if (cmdout) {
+ if (run_command(score, timeleft, &cmdout,
+ "%s", i->cov_compiled)) {
+ covcmd = talloc_asprintf_append(covcmd, " %s",
+ i->fullname);
+ } else {
score->error = "Running test with coverage";
score_file_error(score, i, 0, cmdout);
return;
}
- covcmd = talloc_asprintf_append(covcmd, " %s",
- i->fullname);
}
}
/* Now run gcov: we want output even if it succeeds. */
- cmdout = run_with_timeout(m, covcmd, &ok, timeleft);
- if (!ok) {
+ if (!run_command(score, timeleft, &cmdout, "%s", covcmd)) {
score->error = talloc_asprintf(score, "Running gcov: %s",
cmdout);
return;
foreach_ptr(list, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) {
score->total++;
- cmdout = run_command(m, timeleft, i->compiled);
- if (cmdout)
- score_file_error(score, i, 0, cmdout);
- else
+ if (run_command(m, timeleft, &cmdout, "%s",
+ i->compiled))
score->score++;
+ else
+ score_file_error(score, i, 0, cmdout);
}
}
static const char *can_run_vg(struct manifest *m)
{
unsigned int timeleft = default_timeout_ms;
- char *output = run_command(m, &timeleft,
- "valgrind -q --error-exitcode=0 true");
+ char *output;
- if (output)
+ if (!run_command(m, &timeleft, &output,
+ "valgrind -q --error-exitcode=0 true"))
return talloc_asprintf(m, "No valgrind support: %s", output);
return NULL;
}
foreach_ptr(list, &m->run_tests, &m->api_tests) {
list_for_each(list, i, list) {
score->total++;
- cmdout = run_command(m, timeleft,
- "valgrind -q --error-exitcode=100 %s",
- i->compiled);
- if (cmdout) {
+ if (run_command(score, timeleft, &cmdout,
+ "valgrind -q --error-exitcode=100 %s",
+ i->compiled)) {
+ score->score++;
+ } else {
score->error = "Running under valgrind";
score_file_error(score, i, 0, cmdout);
- } else
- score->score++;
+ }
}
}
bool compile_verbose = false;
-/* Compile multiple object files into a single. Returns errmsg if fails. */
+/* Compile multiple object files into a single. Returns NULL if fails. */
char *link_objects(const void *ctx, const char *basename, bool in_pwd,
const char *objs, char **errmsg)
{
if (compile_verbose)
printf("Linking objects into %s\n", file);
- *errmsg = run_command(ctx, NULL, "ld -r -o %s %s", file, objs);
- if (*errmsg) {
- talloc_free(file);
- return NULL;
- }
- return file;
+ if (run_command(ctx, NULL, errmsg, "ld -r -o %s %s", file, objs))
+ return file;
+
+ talloc_free(file);
+ return NULL;
}
-/* Compile a single C file to an object file. Returns errmsg if fails. */
-char *compile_object(const void *ctx, const char *cfile, const char *ccandir,
- const char *extra_cflags,
- const char *outfile)
+/* Compile a single C file to an object file. */
+bool compile_object(const void *ctx, const char *cfile, const char *ccandir,
+ const char *extra_cflags,
+ const char *outfile, char **output)
{
if (compile_verbose)
printf("Compiling %s\n", outfile);
- return run_command(ctx, NULL, CCAN_COMPILER " " CCAN_CFLAGS
+ return run_command(ctx, NULL, output, CCAN_COMPILER " " CCAN_CFLAGS
" -I%s %s -c -o %s %s",
ccandir, extra_cflags, outfile, cfile);
}
/* Compile and link single C file, with object files.
- * Returns error message or NULL on success. */
-char *compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
- const char *objs, const char *extra_cflags,
- const char *libs, const char *outfile)
+ * Returns false on failure. */
+bool compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
+ const char *objs, const char *extra_cflags,
+ const char *libs, const char *outfile, char **output)
{
if (compile_verbose)
printf("Compiling and linking %s\n", outfile);
- return run_command(ctx, NULL, CCAN_COMPILER " " CCAN_CFLAGS
+ return run_command(ctx, NULL, output, CCAN_COMPILER " " CCAN_CFLAGS
" -I%s %s -o %s %s %s %s",
ccandir, extra_cflags, outfile, cfile, objs, libs);
}
* temp_file helps here. */
static char *compile_info(const void *ctx, const char *dir)
{
- char *info_c_file, *info, *ccandir, *compiled;
+ char *info_c_file, *info, *ccandir, *compiled, *output;
size_t len;
int fd;
compiled = maybe_temp_file(ctx, "", false, "info");
if (compile_and_link(ctx, info_c_file, ccandir, "", "", "",
- compiled))
- return NULL;
- return compiled;
+ compiled, &output))
+ return compiled;
+ return NULL;
}
static char **get_one_deps(const void *ctx, const char *dir,
return ret;
}
-/* Returns output if command fails. */
-char *run_command(const void *ctx, unsigned int *time_ms, const char *fmt, ...)
+/* Tallocs *output off ctx; return false if command fails. */
+bool run_command(const void *ctx, unsigned int *time_ms, char **output,
+ const char *fmt, ...)
{
va_list ap;
- char *cmd, *contents;
+ char *cmd;
bool ok;
unsigned int default_time = default_timeout_ms;
if (!time_ms)
time_ms = &default_time;
- else if (*time_ms == 0)
- return talloc_strdup(ctx, "\n== TIMED OUT ==\n");
+ else if (*time_ms == 0) {
+ *output = talloc_strdup(ctx, "\n== TIMED OUT ==\n");
+ return false;
+ }
va_start(ap, fmt);
cmd = talloc_vasprintf(ctx, fmt, ap);
va_end(ap);
- contents = run_with_timeout(ctx, cmd, &ok, time_ms);
- if (ok) {
- talloc_free(contents);
- return NULL;
- }
-
- if (!contents)
+ *output = run_with_timeout(ctx, cmd, &ok, time_ms);
+ if (ok)
+ return true;
+ if (!*output)
err(1, "Problem running child");
if (*time_ms == 0)
- contents = talloc_asprintf_append(contents,
- "\n== TIMED OUT ==\n");
- return contents;
+ *output = talloc_asprintf_append(*output,
+ "\n== TIMED OUT ==\n");
+ return false;
}
static int unlink_all(char *dir)
#ifndef CCAN_TOOLS_H
#define CCAN_TOOLS_H
#include <stdbool.h>
+#include <ccan/compiler/compiler.h>
#include "config.h"
#ifndef CCAN_COMPILER
char *talloc_basename(const void *ctx, const char *dir);
char *talloc_dirname(const void *ctx, const char *dir);
char *talloc_getcwd(const void *ctx);
-char *run_command(const void *ctx, unsigned int *time_ms, const char *fmt, ...);
+bool PRINTF_FMT(4,5) run_command(const void *ctx,
+ unsigned int *time_ms,
+ char **output,
+ const char *fmt, ...);
char *run_with_timeout(const void *ctx, const char *cmd,
bool *ok, unsigned *timeout_ms);
char *temp_dir(const void *ctx);
/* Compile multiple object files into a single. */
char *link_objects(const void *ctx, const char *basename, bool in_pwd,
const char *objs, char **errmsg);
-/* Compile a single C file to an object file. Returns errmsg if fails. */
-char *compile_object(const void *ctx, const char *cfile, const char *ccandir,
- const char *extra_cflags,
- const char *outfile);
-/* Compile and link single C file, with object files, libs, etc. NULL on
- * success, error output on fail. */
-char *compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
- const char *objs, const char *extra_cflags,
- const char *libs, const char *outfile);
+/* Compile a single C file to an object file. Returns false if fails. */
+bool compile_object(const void *ctx, const char *cfile, const char *ccandir,
+ const char *extra_cflags,
+ const char *outfile, char **output);
+/* Compile and link single C file, with object files, libs, etc. */
+bool compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
+ const char *objs, const char *extra_cflags,
+ const char *libs, const char *outfile, char **output);
/* If in_pwd is false, return a file int temp_dir, otherwise a local file. */
char *maybe_temp_file(const void *ctx, const char *extension, bool in_pwd,