Blame view

scripts/basic/fixdep.c 11 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
80
81
82
83
84
   *
   * It will also filter out all the dependencies on *.ver. We need
   * to make sure that the generated version checksum are globally up
   * to date before even starting the recursive build, so it's too late
   * at this point anyway.
   *
dee81e988   Alexey Dobriyan   fixdep: faster CO...
85
   * We don't even try to really parse the header files, but
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
   * 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)
   */
  /*
   * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
   * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
   * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
   * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
   * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
   * those files will have correct dependencies.
   */
  
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/mman.h>
  #include <unistd.h>
  #include <fcntl.h>
  #include <string.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <limits.h>
  #include <ctype.h>
  #include <arpa/inet.h>
d8329e35c   Nicolas Pitre   fixdep: accept ex...
116
  int insert_extra_deps;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  char *target;
  char *depfile;
  char *cmdline;
4356f4890   Trevor Keith   kbuild: add stati...
120
  static void usage(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  {
d8329e35c   Nicolas Pitre   fixdep: accept ex...
122
123
124
125
  	fprintf(stderr, "Usage: fixdep [-e] <depfile> <target> <cmdline>
  ");
  	fprintf(stderr, " -e  insert extra dependencies given on stdin
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  	exit(1);
  }
4d99f93bd   Sam Ravnborg   kbuild: escape '#...
128
129
  /*
   * Print out the commandline prefixed with cmd_<target filename> :=
6176aa9ae   Jan Beulich   kbuild: consolida...
130
   */
4356f4890   Trevor Keith   kbuild: add stati...
131
  static void print_cmdline(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
6176aa9ae   Jan Beulich   kbuild: consolida...
133
134
135
  	printf("cmd_%s := %s
  
  ", target, cmdline);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  }
d8329e35c   Nicolas Pitre   fixdep: accept ex...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  /*
   * Print out a dependency path from a symbol name
   */
  static void print_config(const char *m, int slen)
  {
  	int c, i;
  
  	printf("    $(wildcard include/config/");
  	for (i = 0; i < slen; i++) {
  		c = m[i];
  		if (c == '_')
  			c = '/';
  		else
  			c = tolower(c);
  		putchar(c);
  	}
  	printf(".h) \\
  ");
  }
  
  static void do_extra_deps(void)
  {
  	if (insert_extra_deps) {
  		char buf[80];
  		while(fgets(buf, sizeof(buf), stdin)) {
  			int len = strlen(buf);
  			if (len < 2 || buf[len-1] != '
  ') {
  				fprintf(stderr, "fixdep: bad data on stdin
  ");
  				exit(1);
  			}
  			print_config(buf, len-1);
  		}
  	}
  }
8af27e1dc   Eric Dumazet   fixdep: use hash ...
173
174
175
176
177
178
  struct item {
  	struct item	*next;
  	unsigned int	len;
  	unsigned int	hash;
  	char		name[0];
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

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

8af27e1dc   Eric Dumazet   fixdep: use hash ...
183
184
185
186
  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
187

8af27e1dc   Eric Dumazet   fixdep: use hash ...
188
189
190
191
  	for (i = 0; i < sz; i++)
  		hash = (hash ^ str[i]) * 0x01000193;
  	return hash;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
  
  /*
   * Lookup a value in the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
196
  static int is_defined_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
198
199
200
201
202
  	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
203
204
205
206
207
208
209
210
  			return 1;
  	}
  	return 0;
  }
  
  /*
   * Add a new value to the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
211
  static void define_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
213
  	struct item *aux = malloc(sizeof(*aux) + len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

8af27e1dc   Eric Dumazet   fixdep: use hash ...
215
216
217
218
219
220
221
222
223
  	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
224
225
226
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
   * Record the use of a CONFIG_* word.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
229
  static void use_config(const char *m, int slen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
231
  	unsigned int hash = strhash(m, slen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

8af27e1dc   Eric Dumazet   fixdep: use hash ...
233
  	if (is_defined_config(m, slen, hash))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	    return;
8af27e1dc   Eric Dumazet   fixdep: use hash ...
235
  	define_config(m, slen, hash);
d8329e35c   Nicolas Pitre   fixdep: accept ex...
236
  	print_config(m, slen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  }
dee81e988   Alexey Dobriyan   fixdep: faster CO...
238
  static void parse_config_file(const char *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  {
dee81e988   Alexey Dobriyan   fixdep: faster CO...
240
241
242
  	const char *q, *r;
  
  	while ((p = strstr(p, "CONFIG_"))) {
d72110961   Masahiro Yamada   kbuild: fixdep: o...
243
  		p += 7;
dee81e988   Alexey Dobriyan   fixdep: faster CO...
244
245
246
247
248
249
250
251
252
253
  		q = p;
  		while (*q && (isalnum(*q) || *q == '_'))
  			q++;
  		if (memcmp(q - 7, "_MODULE", 7) == 0)
  			r = q - 7;
  		else
  			r = q;
  		if (r > p)
  			use_config(p, r - p);
  		p = q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  	}
  }
d8329e35c   Nicolas Pitre   fixdep: accept ex...
256
  /* test if s ends in sub */
4c835b57b   Nicolas Iooss   fixdep: constify ...
257
  static int strrcmp(const char *s, const char *sub)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
264
265
266
  {
  	int slen = strlen(s);
  	int sublen = strlen(sub);
  
  	if (sublen > slen)
  		return 1;
  
  	return memcmp(s + slen - sublen, sub, sublen);
  }
8af27e1dc   Eric Dumazet   fixdep: use hash ...
267
  static void do_config_file(const char *filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
  {
  	struct stat st;
  	int fd;
dee81e988   Alexey Dobriyan   fixdep: faster CO...
271
  	char *map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
  
  	fd = open(filename, O_RDONLY);
  	if (fd < 0) {
a3ba81131   Ben Gamari   Make fixdep error...
275
  		fprintf(stderr, "fixdep: error opening config file: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
  		perror(filename);
  		exit(2);
  	}
46fe94ad1   Tom Rini   kbuild: fixdep: C...
279
280
281
282
283
  	if (fstat(fd, &st) < 0) {
  		fprintf(stderr, "fixdep: error fstat'ing config file: ");
  		perror(filename);
  		exit(2);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
  	if (st.st_size == 0) {
  		close(fd);
  		return;
  	}
dee81e988   Alexey Dobriyan   fixdep: faster CO...
288
289
290
  	map = malloc(st.st_size + 1);
  	if (!map) {
  		perror("fixdep: malloc");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
  		close(fd);
  		return;
  	}
dee81e988   Alexey Dobriyan   fixdep: faster CO...
294
295
296
297
298
299
300
  	if (read(fd, map, st.st_size) != st.st_size) {
  		perror("fixdep: read");
  		close(fd);
  		return;
  	}
  	map[st.st_size] = '\0';
  	close(fd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301

dee81e988   Alexey Dobriyan   fixdep: faster CO...
302
  	parse_config_file(map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303

dee81e988   Alexey Dobriyan   fixdep: faster CO...
304
  	free(map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  }
7840fea20   Michal Marek   kbuild: Fix compu...
306
307
308
309
310
  /*
   * 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.
   */
4356f4890   Trevor Keith   kbuild: add stati...
311
  static void parse_dep_file(void *map, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  {
48b9d03c5   J.A. Magallon   [PATCH] Kill sign...
313
314
315
  	char *m = map;
  	char *end = m + len;
  	char *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  	char s[PATH_MAX];
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
317
318
319
  	int is_target;
  	int saw_any_target = 0;
  	int is_first_dep = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	while (m < end) {
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
322
  		/* Skip any "white space" */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  		while (m < end && (*m == ' ' || *m == '\\' || *m == '
  '))
  			m++;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
326
  		/* Find next "white space" */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  		p = m;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
328
329
  		while (p < end && *p != ' ' && *p != '\\' && *p != '
  ')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  			p++;
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
331
332
333
334
335
336
337
338
339
340
341
342
343
  		/* 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;
  		} else {
  			/* Save this token/filename */
  			memcpy(s, m, p-m);
  			s[p - m] = 0;
  
  			/* Ignore certain dependencies */
  			if (strrcmp(s, "include/generated/autoconf.h") &&
c1a95fda2   Nicolas Pitre   kbuild: add fine ...
344
  			    strrcmp(s, "include/generated/autoksyms.h") &&
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  			    strrcmp(s, "arch/um/include/uml-config.h") &&
  			    strrcmp(s, "include/linux/kconfig.h") &&
  			    strrcmp(s, ".ver")) {
  				/*
  				 * 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) {
  					/*
  					 * 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.
  					 */
  					if (!saw_any_target) {
  						saw_any_target = 1;
  						printf("source_%s := %s
  
  ",
  							target, s);
  						printf("deps_%s := \\
  ",
  							target);
  					}
  					is_first_dep = 0;
  				} else
  					printf("  %s \\
  ", s);
  				do_config_file(s);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  		}
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
382
383
384
385
  		/*
  		 * Start searching for next token immediately after the first
  		 * "whitespace" character that follows this token.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  		m = p + 1;
  	}
2ab8a9966   Stephen Warren   kbuild: fixdep: s...
388
389
390
391
392
393
  
  	if (!saw_any_target) {
  		fprintf(stderr, "fixdep: parse error; no targets found
  ");
  		exit(1);
  	}
d8329e35c   Nicolas Pitre   fixdep: accept ex...
394
  	do_extra_deps();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
398
399
400
401
  	printf("
  %s: $(deps_%s)
  
  ", target, target);
  	printf("$(deps_%s):
  ", target);
  }
4356f4890   Trevor Keith   kbuild: add stati...
402
  static void print_deps(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
409
  {
  	struct stat st;
  	int fd;
  	void *map;
  
  	fd = open(depfile, O_RDONLY);
  	if (fd < 0) {
a3ba81131   Ben Gamari   Make fixdep error...
410
  		fprintf(stderr, "fixdep: error opening depfile: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
  		perror(depfile);
  		exit(2);
  	}
a3ba81131   Ben Gamari   Make fixdep error...
414
  	if (fstat(fd, &st) < 0) {
bb66fc671   Masahiro Yamada   kbuild: trivial -...
415
416
417
418
  		fprintf(stderr, "fixdep: error fstat'ing depfile: ");
  		perror(depfile);
  		exit(2);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  	if (st.st_size == 0) {
  		fprintf(stderr,"fixdep: %s is empty
  ",depfile);
  		close(fd);
  		return;
  	}
  	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  	if ((long) map == -1) {
  		perror("fixdep: mmap");
  		close(fd);
  		return;
  	}
  
  	parse_dep_file(map, st.st_size);
  
  	munmap(map, st.st_size);
  
  	close(fd);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  int main(int argc, char *argv[])
  {
d8329e35c   Nicolas Pitre   fixdep: accept ex...
440
441
442
443
  	if (argc == 5 && !strcmp(argv[1], "-e")) {
  		insert_extra_deps = 1;
  		argv++;
  	} else if (argc != 4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
449
450
451
452
453
454
  		usage();
  
  	depfile = argv[1];
  	target = argv[2];
  	cmdline = argv[3];
  
  	print_cmdline();
  	print_deps();
  
  	return 0;
  }