Web updates.
[ccan] / tools / ccanlint / tests / check_depends_built.c
1 #include <tools/ccanlint/ccanlint.h>
2 #include <tools/tools.h>
3 #include <ccan/talloc/talloc.h>
4 #include <ccan/str/str.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <err.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 static const char *can_build(struct manifest *m)
18 {
19         if (safe_mode)
20                 return "Safe mode enabled";
21         return NULL;
22 }
23
24 /* FIXME: recursive ccanlint if they ask for it. */
25 static bool expect_obj_file(const char *dir)
26 {
27         char *olddir;
28         struct manifest *dep_man;
29         bool has_c_files;
30
31         olddir = talloc_getcwd(dir);
32         if (!olddir)
33                 err(1, "Getting current directory");
34
35         /* We will fail below if this doesn't exist. */
36         if (chdir(dir) != 0)
37                 return false;
38
39         dep_man = get_manifest(dir);
40         if (chdir(olddir) != 0)
41                 err(1, "Returning to original directory '%s'", olddir);
42         talloc_free(olddir);
43
44         /* If it has C files, we expect an object file built from them. */
45         has_c_files = !list_empty(&dep_man->c_files);
46         talloc_free(dep_man);
47         return has_c_files;
48 }
49
50 static void *check_depends_built(struct manifest *m)
51 {
52         struct ccan_file *i;
53         struct stat st;
54         char *report = NULL;
55
56         list_for_each(&m->dep_dirs, i, list) {
57                 char *objfile;
58
59                 if (!expect_obj_file(i->name))
60                         continue;
61
62                 objfile = talloc_asprintf(m, "%s.o", i->name);
63                 if (stat(objfile, &st) != 0) {
64                         report = talloc_asprintf_append(report,
65                                                         "object file %s\n",
66                                                         objfile);
67                 } else {
68                         struct ccan_file *f = new_ccan_file(m, objfile);
69                         list_add_tail(&m->dep_objs, &f->list);
70                 }
71                         
72         }
73
74         /* We may need libtap for testing, unless we're "tap" */
75         if (!streq(m->basename, "tap")
76             && (!list_empty(&m->run_tests) || !list_empty(&m->api_tests))) {
77                 if (stat("../tap.o", &st) != 0) {
78                         report = talloc_asprintf_append(report,
79                                                         "object file ../tap.o"
80                                                         " (for tests)\n");
81                 }
82         }
83
84         return talloc_steal(m, report);
85 }
86
87 static const char *describe_depends_built(struct manifest *m,
88                                           void *check_result)
89 {
90         return talloc_asprintf(check_result, 
91                                "The following dependencies are not built:\n"
92                                "%s", (char *)check_result);
93 }
94
95 struct ccanlint depends_built = {
96         .name = "CCAN dependencies are built",
97         .total_score = 1,
98         .check = check_depends_built,
99         .describe = describe_depends_built,
100         .can_run = can_build,
101 };
102
103 REGISTER_TEST(depends_built, &depends_exist, NULL);