ccanlint: keep separate array of compiled versions.
[ccan] / tools / ccanlint / compulsory_tests / module_builds.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 #include "build.h"
17
18 static const char *can_build(struct manifest *m)
19 {
20         if (safe_mode)
21                 return "Safe mode enabled";
22         return NULL;
23 }
24
25 static char *obj_list(const struct manifest *m, enum compile_type ctype)
26 {
27         char *list = talloc_strdup(m, "");
28         struct ccan_file *i;
29
30         /* Objects from all the C files. */
31         list_for_each(&m->c_files, i, list)
32                 list = talloc_asprintf_append(list, "%s ",
33                                               i->compiled[ctype]);
34
35         return list;
36 }
37
38 char *build_module(struct manifest *m, bool keep,
39                    enum compile_type ctype, char **errstr)
40 {
41         char *name = link_objects(m, m->basename, false, obj_list(m, ctype),
42                                   errstr);
43         if (name) {
44                 if (keep) {
45                         char *realname = talloc_asprintf(m, "%s.o", m->dir);
46                         assert(ctype == COMPILE_NORMAL);
47                         /* We leave this object file around, all built. */
48                         if (!move_file(name, realname))
49                                 err(1, "Renaming %s to %s", name, realname);
50                         name = realname;
51                 }
52         }
53         return name;
54 }
55
56 static void do_build(struct manifest *m,
57                      bool keep,
58                      unsigned int *timeleft,
59                      struct score *score)
60 {
61         char *errstr;
62
63         if (list_empty(&m->c_files)) {
64                 /* No files?  No score, but we "pass". */
65                 score->total = 0;
66                 score->pass = true;
67                 return;
68         }
69
70         m->compiled[COMPILE_NORMAL]
71                 = build_module(m, keep, COMPILE_NORMAL, &errstr);
72         if (!m->compiled[COMPILE_NORMAL]) {
73                 score_file_error(score, NULL, 0, "%s", errstr);
74                 return;
75         }
76
77         score->pass = true;
78         score->score = score->total;
79 }
80
81 struct ccanlint module_builds = {
82         .key = "module_builds",
83         .name = "Module can be built from object files",
84         .check = do_build,
85         .can_run = can_build,
86         .needs = "objects_build"
87 };
88
89 REGISTER_TEST(module_builds);
90