Blame view

scripts/basic/fixdep.c 9.61 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * "Optimize" a list of dependencies as spit out by gcc -MD
   * for the kernel build
   * ===========================================================================
   *
   * Author       Kai Germaschewski
   * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
   *
   * This software may be used and distributed according to the terms
   * of the GNU General Public License, incorporated herein by reference.
   *
   *
   * Introduction:
   *
   * gcc produces a very nice and correct list of dependencies which
   * tells make when to remake a file.
   *
   * To use this list as-is however has the drawback that virtually
264a26838   Sam Ravnborg   kbuild: move auto...
19
   * every file in the kernel includes autoconf.h.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
   *
264a26838   Sam Ravnborg   kbuild: move auto...
21
   * If the user re-runs make *config, autoconf.h will be
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
   * regenerated.  make notices that and will rebuild every file which
   * includes autoconf.h, i.e. basically all files. This is extremely
   * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
   *
   * So we play the same trick that "mkdep" played before. We replace
264a26838   Sam Ravnborg   kbuild: move auto...
27
   * the dependency on autoconf.h by a dependency on every config
4e433fc4d   Cao jin   fixdep: trivial: ...
28
   * option which is mentioned in any of the listed prerequisites.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
   *
c21b1e4d9   Jan Beulich   [PATCH] kbuild: f...
30
31
32
33
34
   * kconfig populates a tree in include/config/ with an empty file
   * for each config symbol and when the configuration is updated
   * the files representing changed config options are touched
   * which then let make pick up the changes and the files that use
   * the config symbols are rebuilt.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
   *
   * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
4e433fc4d   Cao jin   fixdep: trivial: ...
37
   * which depend on "include/config/his/driver.h" will be rebuilt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
   * so most likely only his driver ;-)
   *
   * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
   *
   * So to get dependencies right, there are two issues:
   * o if any of the files the compiler read changed, we need to rebuild
   * o if the command line given to the compile the file changed, we
   *   better rebuild as well.
   *
   * The former is handled by using the -MD output, the later by saving
   * the command line used to compile the old object and comparing it
   * to the one we would now use.
   *
   * Again, also this idea is pretty old and has been discussed on
   * kbuild-devel a long time ago. I don't have a sensibly working
   * internet connection right now, so I rather don't mention names
   * without double checking.
   *
   * This code here has been based partially based on mkdep.c, which
   * says the following about its history:
   *
   *   Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
   *   This is a C version of syncdep.pl by Werner Almesberger.
   *
   *
   * It is invoked as
   *
   *   fixdep <depfile> <target> <cmdline>
   *
   * and will read the dependency file <depfile>
   *
   * The transformed dependency snipped is written to stdout.
   *
   * It first generates a line
   *
   *   cmd_<target> = <cmdline>
   *
   * and then basically copies the .<target>.d file to stdout, in the
264a26838   Sam Ravnborg   kbuild: move auto...
76
   * process filtering out the dependency on autoconf.h and adding
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
   * dependencies on include/config/my/option.h for every
4e433fc4d   Cao jin   fixdep: trivial: ...
78
   * CONFIG_MY_OPTION encountered in any of the prerequisites.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
   *
dee81e988   Alexey Dobriyan   fixdep: faster CO...
80
   * We don't even try to really parse the header files, but
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
87
88
89
90
   * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
   * be picked up as well. It's not a problem with respect to
   * correctness, since that can only give too many dependencies, thus
   * we cannot miss a rebuild. Since people tend to not mention totally
   * unrelated CONFIG_ options all over the place, it's not an
   * efficiency problem either.
   *
   * (Note: it'd be easy to port over the complete mkdep state machine,
   *  but I don't think the added complexity is worth it)
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
  
  #include <sys/types.h>
  #include <sys/stat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
  #include <unistd.h>
  #include <fcntl.h>
  #include <string.h>
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
97
  #include <stdarg.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  #include <stdlib.h>
  #include <stdio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  #include <ctype.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101

4356f4890   Trevor Keith   kbuild: add stati...
102
  static void usage(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  {
bbda5ec67   Masahiro Yamada   kbuild: simplify ...
104
105
  	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  	exit(1);
  }
4d99f93bd   Sam Ravnborg   kbuild: escape '#...
108
  /*
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
   * In the intended usage of this program, the stdout is redirected to .*.cmd
   * files. The return value of printf() and putchar() must be checked to catch
   * any error, e.g. "No space left on device".
   */
  static void xprintf(const char *format, ...)
  {
  	va_list ap;
  	int ret;
  
  	va_start(ap, format);
  	ret = vprintf(format, ap);
  	if (ret < 0) {
  		perror("fixdep");
  		exit(1);
  	}
  	va_end(ap);
  }
  
  static void xputchar(int c)
  {
  	int ret;
  
  	ret = putchar(c);
  	if (ret == EOF) {
  		perror("fixdep");
  		exit(1);
  	}
  }
  
  /*
d8329e35c   Nicolas Pitre   fixdep: accept ex...
139
140
   * Print out a dependency path from a symbol name
   */
fbfa9be99   Masahiro Yamada   kbuild: move incl...
141
  static void print_dep(const char *m, int slen, const char *dir)
d8329e35c   Nicolas Pitre   fixdep: accept ex...
142
  {
b3aa58d2e   Nicolas Pitre   fixdep: suppress ...
143
  	int c, prev_c = '/', i;
d8329e35c   Nicolas Pitre   fixdep: accept ex...
144

6f9ac9f44   Masahiro Yamada   fixdep: check ret...
145
  	xprintf("    $(wildcard %s/", dir);
d8329e35c   Nicolas Pitre   fixdep: accept ex...
146
147
148
149
150
151
  	for (i = 0; i < slen; i++) {
  		c = m[i];
  		if (c == '_')
  			c = '/';
  		else
  			c = tolower(c);
b3aa58d2e   Nicolas Pitre   fixdep: suppress ...
152
  		if (c != '/' || prev_c != '/')
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
153
  			xputchar(c);
b3aa58d2e   Nicolas Pitre   fixdep: suppress ...
154
  		prev_c = c;
d8329e35c   Nicolas Pitre   fixdep: accept ex...
155
  	}
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
156
157
  	xprintf(".h) \\
  ");
d8329e35c   Nicolas Pitre   fixdep: accept ex...
158
  }
8af27e1dc   Eric Dumazet   fixdep: use hash ...
159
160
161
162
  struct item {
  	struct item	*next;
  	unsigned int	len;
  	unsigned int	hash;
859c81750   Gustavo A. R. Silva   modpost,fixdep: R...
163
  	char		name[];
8af27e1dc   Eric Dumazet   fixdep: use hash ...
164
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

8af27e1dc   Eric Dumazet   fixdep: use hash ...
166
167
  #define HASHSZ 256
  static struct item *hashtab[HASHSZ];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

8af27e1dc   Eric Dumazet   fixdep: use hash ...
169
170
171
172
  static unsigned int strhash(const char *str, unsigned int sz)
  {
  	/* fnv32 hash */
  	unsigned int i, hash = 2166136261U;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

8af27e1dc   Eric Dumazet   fixdep: use hash ...
174
175
176
177
  	for (i = 0; i < sz; i++)
  		hash = (hash ^ str[i]) * 0x01000193;
  	return hash;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  
  /*
   * Lookup a value in the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
182
  static int is_defined_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
184
185
186
187
188
  	struct item *aux;
  
  	for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) {
  		if (aux->hash == hash && aux->len == len &&
  		    memcmp(aux->name, name, len) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
194
195
196
  			return 1;
  	}
  	return 0;
  }
  
  /*
   * Add a new value to the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
197
  static void define_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
199
  	struct item *aux = malloc(sizeof(*aux) + len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

8af27e1dc   Eric Dumazet   fixdep: use hash ...
201
202
203
204
205
206
207
208
209
  	if (!aux) {
  		perror("fixdep:malloc");
  		exit(1);
  	}
  	memcpy(aux->name, name, len);
  	aux->len = len;
  	aux->hash = hash;
  	aux->next = hashtab[hash % HASHSZ];
  	hashtab[hash % HASHSZ] = aux;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
   * Record the use of a CONFIG_* word.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
215
  static void use_config(const char *m, int slen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
217
  	unsigned int hash = strhash(m, slen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

8af27e1dc   Eric Dumazet   fixdep: use hash ...
219
  	if (is_defined_config(m, slen, hash))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	    return;
8af27e1dc   Eric Dumazet   fixdep: use hash ...
221
  	define_config(m, slen, hash);
fbfa9be99   Masahiro Yamada   kbuild: move incl...
222
  	print_dep(m, slen, "include/config");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  }
ab9ce9fee   Masahiro Yamada   fixdep: use exist...
224
225
226
227
228
229
230
231
232
233
  /* test if s ends in sub */
  static int str_ends_with(const char *s, int slen, const char *sub)
  {
  	int sublen = strlen(sub);
  
  	if (sublen > slen)
  		return 0;
  
  	return !memcmp(s + slen - sublen, sub, sublen);
  }
dee81e988   Alexey Dobriyan   fixdep: faster CO...
234
  static void parse_config_file(const char *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  {
dee81e988   Alexey Dobriyan   fixdep: faster CO...
236
  	const char *q, *r;
5b8ad96d1   Rasmus Villemoes   fixdep: remove so...
237
  	const char *start = p;
dee81e988   Alexey Dobriyan   fixdep: faster CO...
238
239
  
  	while ((p = strstr(p, "CONFIG_"))) {
5b8ad96d1   Rasmus Villemoes   fixdep: remove so...
240
241
242
243
  		if (p > start && (isalnum(p[-1]) || p[-1] == '_')) {
  			p += 7;
  			continue;
  		}
d72110961   Masahiro Yamada   kbuild: fixdep: o...
244
  		p += 7;
dee81e988   Alexey Dobriyan   fixdep: faster CO...
245
  		q = p;
3f9070a67   Masahiro Yamada   fixdep: remove re...
246
  		while (isalnum(*q) || *q == '_')
dee81e988   Alexey Dobriyan   fixdep: faster CO...
247
  			q++;
ab9ce9fee   Masahiro Yamada   fixdep: use exist...
248
  		if (str_ends_with(p, q - p, "_MODULE"))
dee81e988   Alexey Dobriyan   fixdep: faster CO...
249
250
251
252
253
254
  			r = q - 7;
  		else
  			r = q;
  		if (r > p)
  			use_config(p, r - p);
  		p = q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  	}
  }
4003fd80c   Masahiro Yamada   fixdep: factor ou...
257
  static void *read_file(const char *filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  {
  	struct stat st;
  	int fd;
4003fd80c   Masahiro Yamada   fixdep: factor ou...
261
  	char *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  
  	fd = open(filename, O_RDONLY);
  	if (fd < 0) {
4003fd80c   Masahiro Yamada   fixdep: factor ou...
265
  		fprintf(stderr, "fixdep: error opening file: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
  		perror(filename);
  		exit(2);
  	}
46fe94ad1   Tom Rini   kbuild: fixdep: C...
269
  	if (fstat(fd, &st) < 0) {
4003fd80c   Masahiro Yamada   fixdep: factor ou...
270
  		fprintf(stderr, "fixdep: error fstat'ing file: ");
46fe94ad1   Tom Rini   kbuild: fixdep: C...
271
272
273
  		perror(filename);
  		exit(2);
  	}
4003fd80c   Masahiro Yamada   fixdep: factor ou...
274
275
  	buf = malloc(st.st_size + 1);
  	if (!buf) {
dee81e988   Alexey Dobriyan   fixdep: faster CO...
276
  		perror("fixdep: malloc");
7c2ec43a2   Lukas Bulwahn   fixdep: exit with...
277
  		exit(2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
  	}
4003fd80c   Masahiro Yamada   fixdep: factor ou...
279
  	if (read(fd, buf, st.st_size) != st.st_size) {
dee81e988   Alexey Dobriyan   fixdep: faster CO...
280
  		perror("fixdep: read");
7c2ec43a2   Lukas Bulwahn   fixdep: exit with...
281
  		exit(2);
dee81e988   Alexey Dobriyan   fixdep: faster CO...
282
  	}
4003fd80c   Masahiro Yamada   fixdep: factor ou...
283
  	buf[st.st_size] = '\0';
dee81e988   Alexey Dobriyan   fixdep: faster CO...
284
  	close(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285

4003fd80c   Masahiro Yamada   fixdep: factor ou...
286
  	return buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  }
87b95a813   Masahiro Yamada   fixdep: refactor ...
288
289
290
291
  /* Ignore certain dependencies */
  static int is_ignored_file(const char *s, int len)
  {
  	return str_ends_with(s, len, "include/generated/autoconf.h") ||
87d660f08   Masahiro Yamada   fixdep: remove un...
292
  	       str_ends_with(s, len, "include/generated/autoksyms.h");
87b95a813   Masahiro Yamada   fixdep: refactor ...
293
  }
7840fea20   Michal Marek   kbuild: Fix compu...
294
295
296
297
298
  /*
   * Important: The below generated source_foo.o and deps_foo.o variable
   * assignments are parsed not only by make, but also by the rather simple
   * parser in scripts/mod/sumversion.c.
   */
bbda5ec67   Masahiro Yamada   kbuild: simplify ...
299
  static void parse_dep_file(char *m, const char *target)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  {
48b9d03c5   J.A. Magallon   [PATCH] Kill sign...
301
  	char *p;
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
302
  	int is_last, is_target;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
303
304
  	int saw_any_target = 0;
  	int is_first_dep = 0;
4003fd80c   Masahiro Yamada   fixdep: factor ou...
305
  	void *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306

01b5cbe70   Masahiro Yamada   fixdep: use mallo...
307
  	while (1) {
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
308
  		/* Skip any "white space" */
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
309
310
  		while (*m == ' ' || *m == '\\' || *m == '
  ')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  			m++;
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
312
313
314
  
  		if (!*m)
  			break;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
315
  		/* Find next "white space" */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  		p = m;
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
317
318
  		while (*p && *p != ' ' && *p != '\\' && *p != '
  ')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  			p++;
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
320
  		is_last = (*p == '\0');
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
321
322
323
324
325
326
  		/* Is the token we found a target name? */
  		is_target = (*(p-1) == ':');
  		/* Don't write any target names into the dependency file */
  		if (is_target) {
  			/* The /next/ file is the first dependency */
  			is_first_dep = 1;
87b95a813   Masahiro Yamada   fixdep: refactor ...
327
  		} else if (!is_ignored_file(m, p - m)) {
ccfe78873   Masahiro Yamada   fixdep: remove un...
328
  			*p = '\0';
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
329

87b95a813   Masahiro Yamada   fixdep: refactor ...
330
331
332
333
334
335
336
  			/*
  			 * Do not list the source file as dependency, so that
  			 * kbuild is not confused if a .c file is rewritten
  			 * into .S or vice versa. Storing it in source_* is
  			 * needed for modpost to compute srcversions.
  			 */
  			if (is_first_dep) {
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
337
  				/*
87b95a813   Masahiro Yamada   fixdep: refactor ...
338
339
340
341
342
343
  				 * If processing the concatenation of multiple
  				 * dependency files, only process the first
  				 * target name, which will be the original
  				 * source name, and ignore any other target
  				 * names, which will be intermediate temporary
  				 * files.
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
344
  				 */
87b95a813   Masahiro Yamada   fixdep: refactor ...
345
346
  				if (!saw_any_target) {
  					saw_any_target = 1;
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
347
348
349
350
351
352
  					xprintf("source_%s := %s
  
  ",
  						target, m);
  					xprintf("deps_%s := \\
  ", target);
87b95a813   Masahiro Yamada   fixdep: refactor ...
353
354
355
  				}
  				is_first_dep = 0;
  			} else {
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
356
357
  				xprintf("  %s \\
  ", m);
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
358
  			}
87b95a813   Masahiro Yamada   fixdep: refactor ...
359
360
361
362
  
  			buf = read_file(m);
  			parse_config_file(buf);
  			free(buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  		}
01b5cbe70   Masahiro Yamada   fixdep: use mallo...
364
365
366
  
  		if (is_last)
  			break;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
367
368
369
370
  		/*
  		 * Start searching for next token immediately after the first
  		 * "whitespace" character that follows this token.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
  		m = p + 1;
  	}
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
373
374
375
376
377
378
  
  	if (!saw_any_target) {
  		fprintf(stderr, "fixdep: parse error; no targets found
  ");
  		exit(1);
  	}
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
379
380
381
382
383
384
  	xprintf("
  %s: $(deps_%s)
  
  ", target, target);
  	xprintf("$(deps_%s):
  ", target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  int main(int argc, char *argv[])
  {
5d1ef76f5   Masahiro Yamada   fixdep: move glob...
388
  	const char *depfile, *target, *cmdline;
4003fd80c   Masahiro Yamada   fixdep: factor ou...
389
  	void *buf;
bbda5ec67   Masahiro Yamada   kbuild: simplify ...
390
  	if (argc != 4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
394
395
  		usage();
  
  	depfile = argv[1];
  	target = argv[2];
  	cmdline = argv[3];
6f9ac9f44   Masahiro Yamada   fixdep: check ret...
396
397
398
  	xprintf("cmd_%s := %s
  
  ", target, cmdline);
4003fd80c   Masahiro Yamada   fixdep: factor ou...
399
400
  
  	buf = read_file(depfile);
bbda5ec67   Masahiro Yamada   kbuild: simplify ...
401
  	parse_dep_file(buf, target);
4003fd80c   Masahiro Yamada   fixdep: factor ou...
402
  	free(buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  
  	return 0;
  }