Commit 747a6943 authored by Rusty Russell's avatar Rusty Russell

ccanlint: fix directory issues properly.

parent 3871832e
......@@ -12,7 +12,6 @@ int main(int argc, char *argv[])
bool compile = false;
bool recurse = true;
bool ccan = true;
char *dirname, *basename;
if (argv[1] && streq(argv[1], "--direct")) {
argv++;
......@@ -37,15 +36,12 @@ int main(int argc, char *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)
......
......@@ -255,8 +255,6 @@ int main(int argc, char *argv[])
prefix = talloc_append_string(talloc_basename(NULL,
optarg),
": ");
if (chdir(optarg) != 0)
err(1, "Changing into directory '%s'", optarg);
break;
case 's':
summary = true;
......
......@@ -12,6 +12,7 @@
#define REGISTER_TEST(name, ...)
struct manifest {
char *dir;
/* The module name, ie. final element of dir name */
char *basename;
struct ccan_file *info_file;
......@@ -113,8 +114,12 @@ struct line_info {
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;
......@@ -132,7 +137,7 @@ struct ccan_file {
};
/* 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);
......@@ -179,4 +184,7 @@ struct dependent {
/* 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 */
......@@ -44,7 +44,7 @@ static void *do_build(struct manifest *m)
}
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",
......
......@@ -28,11 +28,12 @@ static void *check_objs_build(struct manifest *m)
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);
......
......@@ -36,7 +36,7 @@ static char *obj_list(const struct manifest *m)
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++)
......@@ -70,7 +70,8 @@ static void *check_use_build(struct manifest *m)
}
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;
}
......
......@@ -44,16 +44,16 @@ static void *check_depends_built(struct manifest *m)
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);
}
......@@ -62,10 +62,12 @@ static void *check_depends_built(struct manifest *m)
/* 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);
}
}
......
......@@ -20,7 +20,7 @@ static char *add_dep(char *sofar, struct manifest *m, const char *dep)
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"
......@@ -28,7 +28,7 @@ static char *add_dep(char *sofar, struct manifest *m, const char *dep)
dep, dir);
}
f = new_ccan_file(m, dir);
f = new_ccan_file(m, "", dir);
list_add_tail(&m->dep_dirs, &f->list);
return sofar;
}
......@@ -38,19 +38,21 @@ static void *check_depends_exist(struct manifest *m)
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;
}
......
......@@ -43,7 +43,7 @@ static void *check_includes_build(struct manifest *m)
}
close(fd);
if (compile_object(m, tmpfile, &err))
if (compile_object(m, tmpfile, ccan_dir, &err))
return NULL;
return err;
}
......
......@@ -24,8 +24,9 @@ static const char *can_build(struct manifest *m)
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;
......
......@@ -28,7 +28,7 @@ static char *obj_list(const struct manifest *m, bool link_with_module)
/* 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, "");
......@@ -37,7 +37,7 @@ static char *obj_list(const struct manifest *m, bool link_with_module)
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)
......@@ -49,7 +49,7 @@ static char *obj_list(const struct manifest *m, bool link_with_module)
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++)
......@@ -63,7 +63,7 @@ static char *compile(const void *ctx,
{
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);
......
......@@ -15,10 +15,11 @@ static char test_is_not_dir[] = "test is not a directory";
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";
}
......
......@@ -33,6 +33,15 @@ static void *do_run_tests(struct manifest *m)
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);
......@@ -65,6 +74,9 @@ static void *do_run_tests(struct manifest *m)
list = NULL;
}
if (chdir(olddir) != 0)
err(1, "Could not chdir to %s", olddir);
return list;
}
......
......@@ -15,6 +15,8 @@
#include <ctype.h>
#include <stdarg.h>
const char *ccan_dir;
char **get_ccan_file_lines(struct ccan_file *f)
{
if (!f->lines)
......@@ -32,7 +34,7 @@ struct list_head *get_ccan_file_docs(struct ccan_file *f)
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;
......@@ -42,6 +44,7 @@ struct ccan_file *new_ccan_file(const void *ctx, char *name)
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;
}
......@@ -66,8 +69,9 @@ static void add_files(struct manifest *m, const char *dir)
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);
......@@ -177,18 +181,29 @@ struct manifest *get_manifest(const void *ctx, const char *dir)
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)
......
......@@ -36,6 +36,15 @@ static void *do_run_tests_vg(struct manifest *m)
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);
......@@ -68,6 +77,9 @@ static void *do_run_tests_vg(struct manifest *m)
list = NULL;
}
if (chdir(olddir) != 0)
err(1, "Could not chdir to %s", olddir);
return list;
}
......
......@@ -16,11 +16,13 @@ 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)
{
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;
......@@ -30,14 +32,14 @@ char *compile_object(const void *ctx, const char *cfile, char **errmsg)
/* 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;
......
......@@ -37,15 +37,14 @@ lines_from_cmd(const void *ctx, unsigned int *num, char *format, ...)
/* 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;
......@@ -59,19 +58,21 @@ static char *compile_info(const void *ctx, const char *dir, const char *name)
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);
......@@ -110,14 +111,14 @@ static char *replace(const void *ctx, const char *src,
/* 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);
......@@ -169,25 +170,28 @@ static bool have_dep(char **deps, unsigned int num, const char *dep)
/* 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++) {
......@@ -203,15 +207,14 @@ get_all_deps(const void *ctx, const char *dir, const char *name,
}
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);
......@@ -221,7 +224,7 @@ char **get_libs(const void *ctx, const char *dir,
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;
......@@ -230,9 +233,9 @@ char **get_deps(const void *ctx, const char *dir, const char *name,
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);
......@@ -242,11 +245,11 @@ char **get_deps(const void *ctx, const char *dir, const char *name,
}
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);
}
......@@ -457,9 +457,7 @@ static void adjust_dir(const char *dir)
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;
......@@ -497,8 +495,7 @@ static void adjust_dependents(const char *dir)
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;
......
......@@ -12,16 +12,16 @@
#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);
......@@ -38,9 +38,10 @@ char *temp_file(const void *ctx, const char *extension);
/* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment