Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kbuild: fixdep: support concatenated dep files

The current use-case for fixdep is: a source file is run through a single
processing step, which creates a single dependency file as a side-effect,
which fixdep transforms into the file used by the kernel build process.

In order to transparently run the C pre-processor on device-tree files,
we wish to run both gcc -E and dtc on a source file in a single rule.
This generates two dependency files, which must be transformed together
into the file used by the kernel build process. This change modifies
fixdep so it can process the concatenation of multiple separate input
dependency files, and produce a correct unified output.

The code changes have the slight benefit of transforming the loop in
parse_dep_file() into more of a lexer/tokenizer, with the loop body being
more of a parser. Previously, some of this logic was mixed together
before the loop. I also added some comments, which I hope are useful.

Benchmarking shows that on a cross-compiled ARM tegra_defconfig build,
there is less than 0.5 seconds speed decrease with this change, on top
of a build time of ~2m24s. This is probably within the noise.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>

+61 -32
+61 -32
scripts/basic/fixdep.c
··· 320 320 char *end = m + len; 321 321 char *p; 322 322 char s[PATH_MAX]; 323 - int first; 324 - 325 - p = strchr(m, ':'); 326 - if (!p) { 327 - fprintf(stderr, "fixdep: parse error\n"); 328 - exit(1); 329 - } 330 - memcpy(s, m, p-m); s[p-m] = 0; 331 - m = p+1; 323 + int is_target; 324 + int saw_any_target = 0; 325 + int is_first_dep = 0; 332 326 333 327 clear_config(); 334 328 335 - first = 1; 336 329 while (m < end) { 330 + /* Skip any "white space" */ 337 331 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) 338 332 m++; 333 + /* Find next "white space" */ 339 334 p = m; 340 - while (p < end && *p != ' ') p++; 341 - if (p == end) { 342 - do p--; while (!isalnum(*p)); 335 + while (p < end && *p != ' ' && *p != '\\' && *p != '\n') 343 336 p++; 337 + /* Is the token we found a target name? */ 338 + is_target = (*(p-1) == ':'); 339 + /* Don't write any target names into the dependency file */ 340 + if (is_target) { 341 + /* The /next/ file is the first dependency */ 342 + is_first_dep = 1; 343 + } else { 344 + /* Save this token/filename */ 345 + memcpy(s, m, p-m); 346 + s[p - m] = 0; 347 + 348 + /* Ignore certain dependencies */ 349 + if (strrcmp(s, "include/generated/autoconf.h") && 350 + strrcmp(s, "arch/um/include/uml-config.h") && 351 + strrcmp(s, "include/linux/kconfig.h") && 352 + strrcmp(s, ".ver")) { 353 + /* 354 + * Do not list the source file as dependency, 355 + * so that kbuild is not confused if a .c file 356 + * is rewritten into .S or vice versa. Storing 357 + * it in source_* is needed for modpost to 358 + * compute srcversions. 359 + */ 360 + if (is_first_dep) { 361 + /* 362 + * If processing the concatenation of 363 + * multiple dependency files, only 364 + * process the first target name, which 365 + * will be the original source name, 366 + * and ignore any other target names, 367 + * which will be intermediate temporary 368 + * files. 369 + */ 370 + if (!saw_any_target) { 371 + saw_any_target = 1; 372 + printf("source_%s := %s\n\n", 373 + target, s); 374 + printf("deps_%s := \\\n", 375 + target); 376 + } 377 + is_first_dep = 0; 378 + } else 379 + printf(" %s \\\n", s); 380 + do_config_file(s); 381 + } 344 382 } 345 - memcpy(s, m, p-m); s[p-m] = 0; 346 - if (strrcmp(s, "include/generated/autoconf.h") && 347 - strrcmp(s, "arch/um/include/uml-config.h") && 348 - strrcmp(s, "include/linux/kconfig.h") && 349 - strrcmp(s, ".ver")) { 350 - /* 351 - * Do not list the source file as dependency, so that 352 - * kbuild is not confused if a .c file is rewritten 353 - * into .S or vice versa. Storing it in source_* is 354 - * needed for modpost to compute srcversions. 355 - */ 356 - if (first) { 357 - printf("source_%s := %s\n\n", target, s); 358 - printf("deps_%s := \\\n", target); 359 - } else 360 - printf(" %s \\\n", s); 361 - do_config_file(s); 362 - } 363 - first = 0; 383 + /* 384 + * Start searching for next token immediately after the first 385 + * "whitespace" character that follows this token. 386 + */ 364 387 m = p + 1; 365 388 } 389 + 390 + if (!saw_any_target) { 391 + fprintf(stderr, "fixdep: parse error; no targets found\n"); 392 + exit(1); 393 + } 394 + 366 395 printf("\n%s: $(deps_%s)\n\n", target, target); 367 396 printf("$(deps_%s):\n", target); 368 397 }