#include "talloc/talloc.h" #include "string/string.h" #include "tools.h" #include #include #include static char ** __attribute__((format(printf, 3, 4))) lines_from_cmd(const void *ctx, unsigned int *num, char *format, ...) { va_list ap; char *cmd, *buffer; FILE *p; va_start(ap, format); cmd = talloc_vasprintf(ctx, format, ap); va_end(ap); p = popen(cmd, "r"); if (!p) err(1, "Executing '%s'", cmd); buffer = grab_fd(ctx, fileno(p)); if (!buffer) err(1, "Reading from '%s'", cmd); pclose(p); return strsplit(ctx, buffer, "\n", num); } static int unlink_info(char *infofile) { unlink(infofile); return 0; } /* Be careful about trying to compile over running programs (parallel make) */ static char *compile_info(const void *ctx, const char *dir) { char *infofile = talloc_asprintf(ctx, "%s/_info.%u", dir, getpid()); char *cmd = talloc_asprintf(ctx, "cc " CFLAGS " -o %s %s/_info.c", infofile, dir); talloc_set_destructor(infofile, unlink_info); if (system(cmd) != 0) return NULL; return infofile; } static char **get_one_deps(const void *ctx, const char *dir, unsigned int *num) { char **deps, *cmd, *infofile; infofile = compile_info(ctx, dir); if (!infofile) errx(1, "Could not compile _info for '%s'", dir); cmd = talloc_asprintf(ctx, "%s depends", infofile); deps = lines_from_cmd(cmd, num, "%s", cmd); if (!deps) err(1, "Could not run '%s'", cmd); return deps; } static bool have_dep(char **deps, unsigned int num, const char *dep) { unsigned int i; for (i = 0; i < num; i++) if (streq(deps[i], dep)) return true; return false; } /* Gets all the dependencies, recursively. */ char **get_deps(const void *ctx, const char *dir) { char **deps; unsigned int i, num; deps = get_one_deps(ctx, dir, &num); for (i = 0; i < num; i++) { char **newdeps; unsigned int j, newnum; if (!strstarts(deps[i], "ccan/")) continue; newdeps = get_one_deps(ctx, deps[i], &newnum); /* Should be short, so brute-force out dups. */ for (j = 0; j < newnum; j++) { if (have_dep(deps, num, newdeps[j])) continue; deps = talloc_realloc(NULL, deps, char *, num + 2); deps[num++] = newdeps[j]; deps[num] = NULL; } } return deps; }