aboutsummaryrefslogtreecommitdiffstats
path: root/tools/build
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2015-09-23 06:33:58 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-09-28 14:50:55 -0400
commit9f7ef9854e800bc3bab3d9a527e8f8f960eec1a6 (patch)
treeea1228ac76dcc0954798be4066b93c9189a0e295 /tools/build
parent0c00c3fb4e4a6ff714b7ad864f58e0fb33b3534c (diff)
tools build: Add fixdep dependency helper
For dependency tracking we currently use targets that fall out of the gcc -MD command. We store this info in the .cmd file and include as makefile during the build. This format put object as target and all the c and header files as dependencies, like: util/abspath.o: util/abspath.c /usr/include/stdc-predef.h util/cache.h \ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \ ... If any of those dependency header files (krava.h below) is removed the build fails on: make[1]: *** No rule to make target 'krava.h', needed by 'inc.o'. Stop. This patch adds fixdep helper, that is used by kbuild to alter the shape of the object dependencies like: source_util/abspath.o := util/abspath.c deps_util/abspath.o := \ /usr/include/stdc-predef.h \ util/cache.h \ ... util/abspath.o: $(deps_util/abspath.o) $(deps_util/abspath.o): With this format the header removal won't make the build fail, because it'll be picked up by the last empty target defined for each header. As previously mentioned the fixdep tool is taken from kbuild. It's not complete backport, only the part that alters the standard dependency info was taken, the part that adds the CONFIG_* dependency logic will be probably taken later on. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Kai Germaschewski <kai.germaschewski@gmx.de> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1443004442-32660-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/build')
-rw-r--r--tools/build/Build1
-rw-r--r--tools/build/Makefile43
-rw-r--r--tools/build/fixdep.c168
3 files changed, 212 insertions, 0 deletions
diff --git a/tools/build/Build b/tools/build/Build
new file mode 100644
index 000000000000..63a6c34c0c88
--- /dev/null
+++ b/tools/build/Build
@@ -0,0 +1 @@
fixdep-y := fixdep.o
diff --git a/tools/build/Makefile b/tools/build/Makefile
new file mode 100644
index 000000000000..a93036272d43
--- /dev/null
+++ b/tools/build/Makefile
@@ -0,0 +1,43 @@
1ifeq ($(srctree),)
2srctree := $(patsubst %/,%,$(dir $(shell pwd)))
3srctree := $(patsubst %/,%,$(dir $(srctree)))
4endif
5
6include $(srctree)/tools//scripts/Makefile.include
7
8define allow-override
9 $(if $(or $(findstring environment,$(origin $(1))),\
10 $(findstring command line,$(origin $(1)))),,\
11 $(eval $(1) = $(2)))
12endef
13
14$(call allow-override,CC,$(CROSS_COMPILE)gcc)
15$(call allow-override,LD,$(CROSS_COMPILE)ld)
16
17ifeq ($(V),1)
18 Q =
19else
20 Q = @
21endif
22
23export Q srctree CC LD
24
25MAKEFLAGS := --no-print-directory
26build := -f $(srctree)/tools/build/Makefile.build dir=. obj
27
28all: fixdep
29
30clean:
31 $(call QUIET_CLEAN, fixdep)
32 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
33 $(Q)rm -f fixdep
34
35$(OUTPUT)fixdep-in.o: FORCE
36 $(Q)$(MAKE) $(build)=fixdep
37
38$(OUTPUT)fixdep: $(OUTPUT)fixdep-in.o
39 $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $<
40
41FORCE:
42
43.PHONY: FORCE
diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c
new file mode 100644
index 000000000000..1521d36cef0d
--- /dev/null
+++ b/tools/build/fixdep.c
@@ -0,0 +1,168 @@
1/*
2 * "Optimize" a list of dependencies as spit out by gcc -MD
3 * for the build framework.
4 *
5 * Original author:
6 * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>
7 *
8 * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),
9 * Please check it for detailed explanation. This fixdep borow only the
10 * base transformation of dependecies without the CONFIG mangle.
11 */
12
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/mman.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <string.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <limits.h>
22
23char *target;
24char *depfile;
25char *cmdline;
26
27static void usage(void)
28{
29 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
30 exit(1);
31}
32
33/*
34 * Print out the commandline prefixed with cmd_<target filename> :=
35 */
36static void print_cmdline(void)
37{
38 printf("cmd_%s := %s\n\n", target, cmdline);
39}
40
41/*
42 * Important: The below generated source_foo.o and deps_foo.o variable
43 * assignments are parsed not only by make, but also by the rather simple
44 * parser in scripts/mod/sumversion.c.
45 */
46static void parse_dep_file(void *map, size_t len)
47{
48 char *m = map;
49 char *end = m + len;
50 char *p;
51 char s[PATH_MAX];
52 int is_target;
53 int saw_any_target = 0;
54 int is_first_dep = 0;
55
56 while (m < end) {
57 /* Skip any "white space" */
58 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
59 m++;
60 /* Find next "white space" */
61 p = m;
62 while (p < end && *p != ' ' && *p != '\\' && *p != '\n')
63 p++;
64 /* Is the token we found a target name? */
65 is_target = (*(p-1) == ':');
66 /* Don't write any target names into the dependency file */
67 if (is_target) {
68 /* The /next/ file is the first dependency */
69 is_first_dep = 1;
70 } else {
71 /* Save this token/filename */
72 memcpy(s, m, p-m);
73 s[p - m] = 0;
74
75 /*
76 * Do not list the source file as dependency,
77 * so that kbuild is not confused if a .c file
78 * is rewritten into .S or vice versa. Storing
79 * it in source_* is needed for modpost to
80 * compute srcversions.
81 */
82 if (is_first_dep) {
83 /*
84 * If processing the concatenation of
85 * multiple dependency files, only
86 * process the first target name, which
87 * will be the original source name,
88 * and ignore any other target names,
89 * which will be intermediate temporary
90 * files.
91 */
92 if (!saw_any_target) {
93 saw_any_target = 1;
94 printf("source_%s := %s\n\n",
95 target, s);
96 printf("deps_%s := \\\n",
97 target);
98 }
99 is_first_dep = 0;
100 } else
101 printf(" %s \\\n", s);
102 }
103 /*
104 * Start searching for next token immediately after the first
105 * "whitespace" character that follows this token.
106 */
107 m = p + 1;
108 }
109
110 if (!saw_any_target) {
111 fprintf(stderr, "fixdep: parse error; no targets found\n");
112 exit(1);
113 }
114
115 printf("\n%s: $(deps_%s)\n\n", target, target);
116 printf("$(deps_%s):\n", target);
117}
118
119static void print_deps(void)
120{
121 struct stat st;
122 int fd;
123 void *map;
124
125 fd = open(depfile, O_RDONLY);
126 if (fd < 0) {
127 fprintf(stderr, "fixdep: error opening depfile: ");
128 perror(depfile);
129 exit(2);
130 }
131 if (fstat(fd, &st) < 0) {
132 fprintf(stderr, "fixdep: error fstat'ing depfile: ");
133 perror(depfile);
134 exit(2);
135 }
136 if (st.st_size == 0) {
137 fprintf(stderr, "fixdep: %s is empty\n", depfile);
138 close(fd);
139 return;
140 }
141 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
142 if ((long) map == -1) {
143 perror("fixdep: mmap");
144 close(fd);
145 return;
146 }
147
148 parse_dep_file(map, st.st_size);
149
150 munmap(map, st.st_size);
151
152 close(fd);
153}
154
155int main(int argc, char **argv)
156{
157 if (argc != 4)
158 usage();
159
160 depfile = argv[1];
161 target = argv[2];
162 cmdline = argv[3];
163
164 print_cmdline();
165 print_deps();
166
167 return 0;
168}