Blame view

scripts/basic/fixdep.c 10.5 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
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
   * option which is mentioned in any of the listed prequisites.
   *
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
37
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 if the user changes his CONFIG_HIS_DRIVER option, only the objects
   * which depend on "include/linux/config/his/driver.h" will be rebuilt,
   * 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
78
79
80
81
82
83
84
85
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
116
117
118
119
120
121
122
123
124
125
   * dependencies on include/config/my/option.h for every
   * CONFIG_MY_OPTION encountered in any of the prequisites.
   *
   * 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.
   *
   * The algorithm to grep for "CONFIG_..." is bit unusual, but should
   * be fast ;-) We don't even try to really parse the header files, but
   * 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>
  
  #define INT_CONF ntohl(0x434f4e46)
  #define INT_ONFI ntohl(0x4f4e4649)
  #define INT_NFIG ntohl(0x4e464947)
  #define INT_FIG_ ntohl(0x4649475f)
  
  char *target;
  char *depfile;
  char *cmdline;
4356f4890   Trevor Keith   kbuild: add stati...
126
  static void usage(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
  {
  	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>
  ");
  	exit(1);
  }
4d99f93bd   Sam Ravnborg   kbuild: escape '#...
132
133
  /*
   * Print out the commandline prefixed with cmd_<target filename> :=
6176aa9ae   Jan Beulich   kbuild: consolida...
134
   */
4356f4890   Trevor Keith   kbuild: add stati...
135
  static void print_cmdline(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  {
6176aa9ae   Jan Beulich   kbuild: consolida...
137
138
139
  	printf("cmd_%s := %s
  
  ", target, cmdline);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  }
8af27e1dc   Eric Dumazet   fixdep: use hash ...
141
142
143
144
145
146
  struct item {
  	struct item	*next;
  	unsigned int	len;
  	unsigned int	hash;
  	char		name[0];
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147

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

8af27e1dc   Eric Dumazet   fixdep: use hash ...
151
152
153
154
  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
155

8af27e1dc   Eric Dumazet   fixdep: use hash ...
156
157
158
159
  	for (i = 0; i < sz; i++)
  		hash = (hash ^ str[i]) * 0x01000193;
  	return hash;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
  
  /*
   * Lookup a value in the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
164
  static int is_defined_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
166
167
168
169
170
  	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
171
172
173
174
175
176
177
178
  			return 1;
  	}
  	return 0;
  }
  
  /*
   * Add a new value to the configuration string.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
179
  static void define_config(const char *name, int len, unsigned int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
181
  	struct item *aux = malloc(sizeof(*aux) + len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

8af27e1dc   Eric Dumazet   fixdep: use hash ...
183
184
185
186
187
188
189
190
191
  	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
192
193
194
195
196
  }
  
  /*
   * Clear the set of configuration strings.
   */
4356f4890   Trevor Keith   kbuild: add stati...
197
  static void clear_config(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
199
200
201
202
203
204
205
206
207
208
  	struct item *aux, *next;
  	unsigned int i;
  
  	for (i = 0; i < HASHSZ; i++) {
  		for (aux = hashtab[i]; aux; aux = next) {
  			next = aux->next;
  			free(aux);
  		}
  		hashtab[i] = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
  }
  
  /*
   * Record the use of a CONFIG_* word.
   */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
214
  static void use_config(const char *m, int slen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
216
217
  	unsigned int hash = strhash(m, slen);
  	int c, i;
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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222

8af27e1dc   Eric Dumazet   fixdep: use hash ...
223
224
225
226
227
  	printf("    $(wildcard include/config/");
  	for (i = 0; i < slen; i++) {
  		c = m[i];
  		if (c == '_')
  			c = '/';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		else
8af27e1dc   Eric Dumazet   fixdep: use hash ...
229
230
  			c = tolower(c);
  		putchar(c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  	}
8af27e1dc   Eric Dumazet   fixdep: use hash ...
232
233
  	printf(".h) \\
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  }
8af27e1dc   Eric Dumazet   fixdep: use hash ...
235
  static void parse_config_file(const char *map, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  {
8af27e1dc   Eric Dumazet   fixdep: use hash ...
237
  	const int *end = (const int *) (map + len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	/* start at +1, so that p can never be < map */
8af27e1dc   Eric Dumazet   fixdep: use hash ...
239
240
  	const int *m   = (const int *) map + 1;
  	const char *p, *q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
  
  	for (; m < end; m++) {
48b9d03c5   J.A. Magallon   [PATCH] Kill sign...
243
244
245
246
  		if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
  		if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
  		if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
  		if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
255
256
257
258
259
  		continue;
  	conf:
  		if (p > map + len - 7)
  			continue;
  		if (memcmp(p, "CONFIG_", 7))
  			continue;
  		for (q = p + 7; q < map + len; q++) {
  			if (!(isalnum(*q) || *q == '_'))
  				goto found;
  		}
  		continue;
  
  	found:
c21b1e4d9   Jan Beulich   [PATCH] kbuild: f...
260
261
  		if (!memcmp(q - 7, "_MODULE", 7))
  			q -= 7;
04c58f819   Andy Green   kbuild: scripts/b...
262
263
  		if( (q-p-7) < 0 )
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
267
268
  		use_config(p+7, q-p-7);
  	}
  }
  
  /* test is s ends in sub */
4356f4890   Trevor Keith   kbuild: add stati...
269
  static int strrcmp(char *s, char *sub)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
  {
  	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 ...
279
  static void do_config_file(const char *filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
  {
  	struct stat st;
  	int fd;
  	void *map;
  
  	fd = open(filename, O_RDONLY);
  	if (fd < 0) {
a3ba81131   Ben Gamari   Make fixdep error...
287
  		fprintf(stderr, "fixdep: error opening config file: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  		perror(filename);
  		exit(2);
  	}
  	fstat(fd, &st);
  	if (st.st_size == 0) {
  		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_config_file(map, st.st_size);
  
  	munmap(map, st.st_size);
  
  	close(fd);
  }
7840fea20   Michal Marek   kbuild: Fix compu...
309
310
311
312
313
  /*
   * 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...
314
  static void parse_dep_file(void *map, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  {
48b9d03c5   J.A. Magallon   [PATCH] Kill sign...
316
317
318
  	char *m = map;
  	char *end = m + len;
  	char *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  	char s[PATH_MAX];
b7bd18217   Michal Marek   fixdep: Do not re...
320
  	int first;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
325
326
327
328
  
  	p = strchr(m, ':');
  	if (!p) {
  		fprintf(stderr, "fixdep: parse error
  ");
  		exit(1);
  	}
  	memcpy(s, m, p-m); s[p-m] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  	m = p+1;
  
  	clear_config();
b7bd18217   Michal Marek   fixdep: Do not re...
332
  	first = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
336
337
338
339
340
341
342
343
  	while (m < end) {
  		while (m < end && (*m == ' ' || *m == '\\' || *m == '
  '))
  			m++;
  		p = m;
  		while (p < end && *p != ' ') p++;
  		if (p == end) {
  			do p--; while (!isalnum(*p));
  			p++;
  		}
  		memcpy(s, m, p-m); s[p-m] = 0;
264a26838   Sam Ravnborg   kbuild: move auto...
344
  		if (strrcmp(s, "include/generated/autoconf.h") &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  		    strrcmp(s, "arch/um/include/uml-config.h") &&
6a5be57f0   Peter Foley   fixdep: fix extra...
346
  		    strrcmp(s, "include/linux/kconfig.h") &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  		    strrcmp(s, ".ver")) {
b7bd18217   Michal Marek   fixdep: Do not re...
348
  			/*
7840fea20   Michal Marek   kbuild: Fix compu...
349
350
351
352
  			 * 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.
b7bd18217   Michal Marek   fixdep: Do not re...
353
  			 */
7840fea20   Michal Marek   kbuild: Fix compu...
354
355
356
357
358
359
360
  			if (first) {
  				printf("source_%s := %s
  
  ", target, s);
  				printf("deps_%s := \\
  ", target);
  			} else
b7bd18217   Michal Marek   fixdep: Do not re...
361
362
  				printf("  %s \\
  ", s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
  			do_config_file(s);
  		}
b7bd18217   Michal Marek   fixdep: Do not re...
365
  		first = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
368
369
370
371
372
373
374
  		m = p + 1;
  	}
  	printf("
  %s: $(deps_%s)
  
  ", target, target);
  	printf("$(deps_%s):
  ", target);
  }
4356f4890   Trevor Keith   kbuild: add stati...
375
  static void print_deps(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
379
380
381
382
  {
  	struct stat st;
  	int fd;
  	void *map;
  
  	fd = open(depfile, O_RDONLY);
  	if (fd < 0) {
a3ba81131   Ben Gamari   Make fixdep error...
383
  		fprintf(stderr, "fixdep: error opening depfile: ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
  		perror(depfile);
  		exit(2);
  	}
a3ba81131   Ben Gamari   Make fixdep error...
387
388
389
390
391
  	if (fstat(fd, &st) < 0) {
                  fprintf(stderr, "fixdep: error fstat'ing depfile: ");
                  perror(depfile);
                  exit(2);
          }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  	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);
  }
4356f4890   Trevor Keith   kbuild: add stati...
411
  static void traps(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
  {
  	static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
d067aa741   Amerigo Wang   kbuild: fix a com...
414
  	int *p = (int *)test;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

d067aa741   Amerigo Wang   kbuild: fix a com...
416
  	if (*p != INT_CONF) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  		fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x
  ",
d067aa741   Amerigo Wang   kbuild: fix a com...
419
  			*p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  		exit(2);
  	}
  }
  
  int main(int argc, char *argv[])
  {
  	traps();
  
  	if (argc != 4)
  		usage();
  
  	depfile = argv[1];
  	target = argv[2];
  	cmdline = argv[3];
  
  	print_cmdline();
  	print_deps();
  
  	return 0;
  }