bool compile = false;
bool recurse = true;
bool ccan = true;
- char *dirname, *basename;
if (argv[1] && streq(argv[1], "--direct")) {
argv++;
if (!ccan && !compile)
errx(1, "--non-ccan needs --compile");
- dirname = talloc_dirname(NULL, argv[1]);
- basename = talloc_basename(NULL, argv[1]);
-
if (compile)
- deps = get_deps(talloc_autofree_context(),
- dirname, basename, recurse, NULL);
+ deps = get_deps(talloc_autofree_context(), argv[1],
+ recurse, NULL);
else
deps = get_safe_ccan_deps(talloc_autofree_context(),
- dirname, basename, recurse, NULL);
+ argv[1], recurse, NULL);
for (i = 0; deps[i]; i++)
if (strstarts(deps[i], "ccan/") == ccan)
prefix = talloc_append_string(talloc_basename(NULL,
optarg),
": ");
- if (chdir(optarg) != 0)
- err(1, "Changing into directory '%s'", optarg);
break;
case 's':
summary = true;
#define REGISTER_TEST(name, ...)
struct manifest {
+ char *dir;
/* The module name, ie. final element of dir name */
char *basename;
struct ccan_file *info_file;
struct ccan_file {
struct list_node list;
+ /* Name (usually, within m->dir). */
char *name;
+ /* Full path name. */
+ char *fullname;
+
/* Pristine version of the original file.
* Use get_ccan_file_lines to fill this. */
const char *contents;
};
/* A new ccan_file, with the given name (talloc_steal onto returned value). */
-struct ccan_file *new_ccan_file(const void *ctx, char *name);
+struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name);
/* Use this rather than accessing f->lines directly: loads on demand. */
char **get_ccan_file_lines(struct ccan_file *f);
/* Are we happy to compile stuff, or just non-intrusive tests? */
extern bool safe_mode;
+/* Where is the ccan dir? Available after first manifest. */
+extern const char *ccan_dir;
+
#endif /* CCAN_LINT_H */
}
filename = link_objects(m, obj_list(m), &err);
if (filename) {
- char *realname = talloc_asprintf(m, "../%s.o", m->basename);
+ char *realname = talloc_asprintf(m, "%s.o", m->dir);
/* We leave this object file around, all built. */
if (rename(filename, realname) != 0)
return talloc_asprintf(m, "Failed to rename %s to %s",
list_for_each(&m->c_files, i, list) {
char *err;
+ char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
/* One point for each obj file. */
build_objs.total_score++;
- i->compiled = compile_object(m, i->name, &err);
+ i->compiled = compile_object(m, fullfile, ccan_dir, &err);
if (!i->compiled) {
if (report)
report = talloc_append_string(report, err);
static char *lib_list(const struct manifest *m)
{
unsigned int i, num;
- char **libs = get_libs(m, ".", ".", &num, &m->info_file->compiled);
+ char **libs = get_libs(m, ".", &num, &m->info_file->compiled);
char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++)
}
close(fd);
- if (!compile_and_link(m, tmpfile, obj_list(m), "", lib_list(m), &err))
+ if (!compile_and_link(m, tmpfile, ccan_dir, obj_list(m), "",
+ lib_list(m), &err))
return err;
return NULL;
}
list_for_each(&m->dep_dirs, i, list) {
char *objfile;
- if (!expect_obj_file(i->name))
+ if (!expect_obj_file(i->fullname))
continue;
- objfile = talloc_asprintf(m, "%s.o", i->name);
+ objfile = talloc_asprintf(m, "%s.o", i->fullname);
if (stat(objfile, &st) != 0) {
report = talloc_asprintf_append(report,
"object file %s\n",
objfile);
} else {
- struct ccan_file *f = new_ccan_file(m, objfile);
+ struct ccan_file *f = new_ccan_file(m, "", objfile);
list_add_tail(&m->dep_objs, &f->list);
}
/* We may need libtap for testing, unless we're "tap" */
if (!streq(m->basename, "tap")
&& (!list_empty(&m->run_tests) || !list_empty(&m->api_tests))) {
- if (stat("../tap.o", &st) != 0) {
+ char *tapobj = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir);
+ if (stat(tapobj, &st) != 0) {
report = talloc_asprintf_append(report,
- "object file ../tap.o"
- " (for tests)\n");
+ "object file %s"
+ " (for tests)\n",
+ tapobj);
}
}
struct stat st;
struct ccan_file *f;
- dir = talloc_asprintf(m, "../%s", dep);
+ dir = talloc_asprintf(m, "%s/%s", ccan_dir, dep);
if (stat(dir, &st) != 0) {
return talloc_asprintf_append(sofar,
"ccan/%s: expected it in"
dep, dir);
}
- f = new_ccan_file(m, dir);
+ f = new_ccan_file(m, "", dir);
list_add_tail(&m->dep_dirs, &f->list);
return sofar;
}
unsigned int i;
char *report = NULL;
char **deps;
+ char *updir = talloc_strdup(m, m->dir);
+
+ *strrchr(updir, '/') = '\0';
if (safe_mode)
- deps = get_safe_ccan_deps(m, "..", m->basename, true,
+ deps = get_safe_ccan_deps(m, m->dir, true,
&m->info_file->compiled);
else
- deps = get_deps(m, "..", m->basename, true,
- &m->info_file->compiled);
+ deps = get_deps(m, m->dir, true, &m->info_file->compiled);
for (i = 0; deps[i]; i++) {
if (!strstarts(deps[i], "ccan/"))
continue;
- report = add_dep(report, m, deps[i] + strlen("ccan/"));
+ report = add_dep(report, m, deps[i]);
}
return report;
}
}
close(fd);
- if (compile_object(m, tmpfile, &err))
+ if (compile_object(m, tmpfile, ccan_dir, &err))
return NULL;
return err;
}
static char *compile(struct manifest *m, struct ccan_file *cfile)
{
char *err;
+ char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, cfile->name);
- cfile->compiled = compile_object(m, cfile->name, &err);
+ cfile->compiled = compile_object(m, fullfile, ccan_dir, &err);
if (cfile->compiled)
return NULL;
return err;
/* We expect to be linked with tap, unless that's us. */
if (!streq(m->basename, "tap"))
- list = talloc_strdup(m, "../tap.o");
+ list = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir);
else
list = talloc_strdup(m, "");
list = talloc_asprintf_append(list, " %s", i->compiled);
if (link_with_module)
- list = talloc_asprintf_append(list, " ../%s.o", m->basename);
+ list = talloc_asprintf_append(list, " %s.o", m->dir);
/* Other ccan modules. */
list_for_each(&m->dep_objs, i, list)
static char *lib_list(const struct manifest *m)
{
unsigned int i, num;
- char **libs = get_libs(m, ".", ".", &num, &m->info_file->compiled);
+ char **libs = get_libs(m, ".", &num, &m->info_file->compiled);
char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++)
{
char *errmsg;
- file->compiled = compile_and_link(ctx, file->name,
+ file->compiled = compile_and_link(ctx, file->fullname, ccan_dir,
obj_list(m, link_with_module),
fail ? "-DFAIL" : "",
lib_list(m), &errmsg);
static void *check_has_tests(struct manifest *m)
{
struct stat st;
+ char *test_dir = talloc_asprintf(m, "%s/test", m->dir);
- if (lstat("test", &st) != 0) {
+ if (lstat(test_dir, &st) != 0) {
if (errno != ENOENT)
- err(1, "statting test/");
+ err(1, "statting %s", test_dir);
return "You have no test directory";
}
struct run_tests_result *res;
struct ccan_file *i;
char *cmdout;
+ char *olddir;
+
+ /* We run tests in the module directory, so any paths
+ * referenced can all be module-local. */
+ olddir = talloc_getcwd(m);
+ if (!olddir)
+ err(1, "Could not save cwd");
+ if (chdir(m->dir) != 0)
+ err(1, "Could not chdir to %s", m->dir);
list_head_init(list);
list = NULL;
}
+ if (chdir(olddir) != 0)
+ err(1, "Could not chdir to %s", olddir);
+
return list;
}
#include <ctype.h>
#include <stdarg.h>
+const char *ccan_dir;
+
char **get_ccan_file_lines(struct ccan_file *f)
{
if (!f->lines)
return f->doc_sections;
}
-struct ccan_file *new_ccan_file(const void *ctx, char *name)
+struct ccan_file *new_ccan_file(const void *ctx, const char *dir, char *name)
{
struct ccan_file *f;
f->doc_sections = NULL;
f->compiled = NULL;
f->name = talloc_steal(f, name);
+ f->fullname = talloc_asprintf(f, "%s/%s", dir, f->name);
return f;
}
if (ent->d_name[0] == '.')
continue;
- f = new_ccan_file(m, talloc_asprintf(m, "%s%s",
- dir, ent->d_name));
+ f = new_ccan_file(m, m->dir,
+ talloc_asprintf(m, "%s%s",
+ dir, ent->d_name));
if (lstat(f->name, &st) != 0)
err(1, "lstat %s", f->name);
if (chdir(dir) != 0)
err(1, "Failed to chdir to %s", dir);
- m->basename = talloc_getcwd(m);
- if (!m->basename)
+ m->dir = talloc_getcwd(m);
+ if (!m->dir)
err(1, "Getting current directory");
- len = strlen(m->basename);
- while (len && m->basename[len-1] == '/')
- m->basename[--len] = '\0';
- m->basename = strrchr(m->basename, '/');
+ len = strlen(m->dir);
+ while (len && m->dir[len-1] == '/')
+ m->dir[--len] = '\0';
+
+ m->basename = strrchr(m->dir, '/');
if (!m->basename)
errx(1, "I don't expect to be run from the root directory");
m->basename++;
+ /* We expect the ccan dir to be two levels above module dir. */
+ if (!ccan_dir) {
+ char *p;
+ ccan_dir = talloc_strdup(NULL, m->dir);
+ p = strrchr(ccan_dir, '/');
+ *p = '\0';
+ p = strrchr(ccan_dir, '/');
+ *p = '\0';
+ }
+
add_files(m, "");
if (chdir(olddir) != 0)
struct run_tests_result *res;
struct ccan_file *i;
char *cmdout;
+ char *olddir;
+
+ /* We run tests in the module directory, so any paths
+ * referenced can all be module-local. */
+ olddir = talloc_getcwd(m);
+ if (!olddir)
+ err(1, "Could not save cwd");
+ if (chdir(m->dir) != 0)
+ err(1, "Could not chdir to %s", m->dir);
list_head_init(list);
list = NULL;
}
+ if (chdir(olddir) != 0)
+ err(1, "Could not chdir to %s", olddir);
+
return list;
}
}
/* Compile a single C file to an object file. Returns errmsg if fails. */
-char *compile_object(const void *ctx, const char *cfile, char **errmsg)
+char *compile_object(const void *ctx, const char *cfile, const char *ccandir,
+ char **errmsg)
{
char *file = temp_file(ctx, ".o");
- *errmsg = run_command(ctx, "cc " CFLAGS " -c -o %s %s", file, cfile);
+ *errmsg = run_command(ctx, "cc " CFLAGS " -I%s -c -o %s %s",
+ ccandir, file, cfile);
if (*errmsg) {
talloc_free(file);
return NULL;
/* Compile and link single C file, with object files.
* Returns name of result, or NULL (and fills in errmsg). */
-char *compile_and_link(const void *ctx, const char *cfile, const char *objs,
- const char *extra_cflags, const char *libs,
- char **errmsg)
+char *compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
+ const char *objs, const char *extra_cflags,
+ const char *libs, char **errmsg)
{
char *file = temp_file(ctx, "");
- *errmsg = run_command(ctx, "cc " CFLAGS " %s -o %s %s %s %s",
- extra_cflags, file, cfile, objs, libs);
+ *errmsg = run_command(ctx, "cc " CFLAGS " -I%s %s -o %s %s %s %s",
+ ccandir, extra_cflags, file, cfile, objs, libs);
if (*errmsg) {
talloc_free(file);
return NULL;
/* Be careful about trying to compile over running programs (parallel make).
* temp_file helps here. */
-static char *compile_info(const void *ctx, const char *dir, const char *name)
+static char *compile_info(const void *ctx, const char *dir)
{
- char *info_c_file, *info, *errmsg;
+ char *info_c_file, *info, *errmsg, *ccandir;
size_t len;
int fd;
/* Copy it to a file with proper .c suffix. */
- info = grab_file(ctx, talloc_asprintf(ctx, "%s/%s/_info", dir, name),
- &len);
+ info = grab_file(ctx, talloc_asprintf(ctx, "%s/_info", dir), &len);
if (!info)
return NULL;
if (close(fd) != 0)
return NULL;
- return compile_and_link(ctx, info_c_file, "", "", "", &errmsg);
+ ccandir = talloc_dirname(ctx, dir);
+ *strrchr(ccandir, '/') = '\0';
+ return compile_and_link(ctx, info_c_file, ccandir, "", "", "",
+ &errmsg);
}
static char **get_one_deps(const void *ctx, const char *dir,
- const char *name, unsigned int *num,
- char **infofile)
+ unsigned int *num, char **infofile)
{
char **deps, *cmd;
if (!*infofile) {
- *infofile = compile_info(ctx, dir, name);
+ *infofile = compile_info(ctx, dir);
if (!*infofile)
- errx(1, "Could not compile _info for '%s'", name);
+ errx(1, "Could not compile _info for '%s'", dir);
}
cmd = talloc_asprintf(ctx, "%s depends", *infofile);
/* This is a terrible hack. We scan for ccan/ strings. */
static char **get_one_safe_deps(const void *ctx,
- const char *dir, const char *name,
+ const char *dir,
unsigned int *num,
char **infofile)
{
char **deps, **lines, *raw, *fname;
unsigned int i, n = 0;
- fname = talloc_asprintf(ctx, "%s/%s/_info", dir, name);
+ fname = talloc_asprintf(ctx, "%s/_info", dir);
raw = grab_file(fname, fname, NULL);
if (!raw)
errx(1, "Could not open %s", fname);
/* Gets all the dependencies, recursively. */
static char **
-get_all_deps(const void *ctx, const char *dir, const char *name,
+get_all_deps(const void *ctx, const char *dir,
char **infofile,
- char **(*get_one)(const void *, const char *, const char *,
+ char **(*get_one)(const void *, const char *,
unsigned int *, char **))
{
char **deps;
unsigned int i, num;
- deps = get_one(ctx, dir, name, &num, infofile);
+ deps = get_one(ctx, dir, &num, infofile);
for (i = 0; i < num; i++) {
char **newdeps;
unsigned int j, newnum;
char *subinfo = NULL;
+ char *subdir;
if (!strstarts(deps[i], "ccan/"))
continue;
- newdeps = get_one(ctx, dir, deps[i] + strlen("ccan/"),
- &newnum, &subinfo);
+ subdir = talloc_asprintf(ctx, "%s/%s",
+ talloc_dirname(ctx, dir),
+ deps[i] + strlen("ccan/"));
+ newdeps = get_one(ctx, subdir, &newnum, &subinfo);
/* Should be short, so brute-force out dups. */
for (j = 0; j < newnum; j++) {
}
char **get_libs(const void *ctx, const char *dir,
- const char *name, unsigned int *num,
- char **infofile)
+ unsigned int *num, char **infofile)
{
char **libs, *cmd;
if (!*infofile) {
- *infofile = compile_info(ctx, dir, name);
+ *infofile = compile_info(ctx, dir);
if (!*infofile)
- errx(1, "Could not compile _info for '%s'", name);
+ errx(1, "Could not compile _info for '%s'", dir);
}
cmd = talloc_asprintf(ctx, "%s libs", *infofile);
return libs;
}
-char **get_deps(const void *ctx, const char *dir, const char *name,
+char **get_deps(const void *ctx, const char *dir,
bool recurse, char **infofile)
{
char *temp = NULL, **ret;
if (!recurse) {
unsigned int num;
- ret = get_one_deps(ctx, dir, name, &num, infofile);
+ ret = get_one_deps(ctx, dir, &num, infofile);
} else
- ret = get_all_deps(ctx, dir, name, infofile, get_one_deps);
+ ret = get_all_deps(ctx, dir, infofile, get_one_deps);
if (infofile == &temp && temp) {
unlink(temp);
}
char **get_safe_ccan_deps(const void *ctx, const char *dir,
- const char *name, bool recurse, char **infofile)
+ bool recurse, char **infofile)
{
if (!recurse) {
unsigned int num;
- return get_one_safe_deps(ctx, dir, name, &num, infofile);
+ return get_one_safe_deps(ctx, dir, &num, infofile);
}
- return get_all_deps(ctx, dir, name, infofile, get_one_safe_deps);
+ return get_all_deps(ctx, dir, infofile, get_one_safe_deps);
}
verbose("Adjusting %s\n", dir);
verbose_indent();
- for (deps = get_deps(parent, parent, talloc_basename(parent, dir),
- false, NULL);
- *deps; deps++) {
+ for (deps = get_deps(parent, dir, false, NULL); *deps; deps++) {
char *depdir;
struct adjusted *adj = NULL;
struct replace *repl;
if (access(info, R_OK) != 0)
continue;
- for (deps = get_deps(*file, talloc_dirname(*file, *file),
- talloc_basename(*file, *file), false, NULL);
+ for (deps = get_deps(*file, *file, false, NULL);
*deps; deps++) {
if (!strstarts(*deps, "ccan/"))
continue;
#define CFLAGS "-g -Wall -Wundef -Wstrict-prototypes -Wold-style-definition -Werror -I../.."
/* This actually compiles and runs the info file to get dependencies. */
-char **get_deps(const void *ctx, const char *dir, const char *name,
- bool recurse, char **infofile);
+char **get_deps(const void *ctx, const char *dir, bool recurse,
+ char **infofile);
/* This is safer: just looks for ccan/ strings in info */
-char **get_safe_ccan_deps(const void *ctx, const char *dir, const char *name,
+char **get_safe_ccan_deps(const void *ctx, const char *dir,
bool recurse, char **infofile);
/* This also needs to compile the info file. */
char **get_libs(const void *ctx, const char *dir,
- const char *name, unsigned int *num, char **infofile);
+ unsigned int *num, char **infofile);
/* From tools.c */
char *talloc_basename(const void *ctx, const char *dir);
/* Compile multiple object files into a single. */
char *link_objects(const void *ctx, 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, char **errmsg);
+char *compile_object(const void *ctx, const char *cfile, const char *ccandir,
+ char **errmsg);
/* Compile and link single C file, with object files, libs, etc. */
-char *compile_and_link(const void *ctx, const char *cfile, const char *objs,
- const char *extra_cflags, const char *libs,
- char **errmsg);
+char *compile_and_link(const void *ctx, const char *cfile, const char *ccandir,
+ const char *objs, const char *extra_cflags,
+ const char *libs, char **errmsg);
#endif /* CCAN_TOOLS_H */