162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * "Optimize" a list of dependencies as spit out by gcc -MD 462306a36Sopenharmony_ci * for the build framework. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Original author: 762306a36Sopenharmony_ci * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c), 1062306a36Sopenharmony_ci * Please check it for detailed explanation. This fixdep borow only the 1162306a36Sopenharmony_ci * base transformation of dependecies without the CONFIG mangle. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <sys/types.h> 1562306a36Sopenharmony_ci#include <sys/stat.h> 1662306a36Sopenharmony_ci#include <sys/mman.h> 1762306a36Sopenharmony_ci#include <unistd.h> 1862306a36Sopenharmony_ci#include <fcntl.h> 1962306a36Sopenharmony_ci#include <string.h> 2062306a36Sopenharmony_ci#include <stdlib.h> 2162306a36Sopenharmony_ci#include <stdio.h> 2262306a36Sopenharmony_ci#include <limits.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cichar *target; 2562306a36Sopenharmony_cichar *depfile; 2662306a36Sopenharmony_cichar *cmdline; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void usage(void) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n"); 3162306a36Sopenharmony_ci exit(1); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* 3562306a36Sopenharmony_ci * Print out the commandline prefixed with cmd_<target filename> := 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_cistatic void print_cmdline(void) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci printf("cmd_%s := %s\n\n", target, cmdline); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * Important: The below generated source_foo.o and deps_foo.o variable 4462306a36Sopenharmony_ci * assignments are parsed not only by make, but also by the rather simple 4562306a36Sopenharmony_ci * parser in scripts/mod/sumversion.c. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cistatic void parse_dep_file(void *map, size_t len) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci char *m = map; 5062306a36Sopenharmony_ci char *end = m + len; 5162306a36Sopenharmony_ci char *p; 5262306a36Sopenharmony_ci char s[PATH_MAX]; 5362306a36Sopenharmony_ci int is_target, has_target = 0; 5462306a36Sopenharmony_ci int saw_any_target = 0; 5562306a36Sopenharmony_ci int is_first_dep = 0; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci while (m < end) { 5862306a36Sopenharmony_ci /* Skip any "white space" */ 5962306a36Sopenharmony_ci while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) 6062306a36Sopenharmony_ci m++; 6162306a36Sopenharmony_ci /* Find next "white space" */ 6262306a36Sopenharmony_ci p = m; 6362306a36Sopenharmony_ci while (p < end && *p != ' ' && *p != '\\' && *p != '\n') 6462306a36Sopenharmony_ci p++; 6562306a36Sopenharmony_ci /* Is the token we found a target name? */ 6662306a36Sopenharmony_ci is_target = (*(p-1) == ':'); 6762306a36Sopenharmony_ci /* Don't write any target names into the dependency file */ 6862306a36Sopenharmony_ci if (is_target) { 6962306a36Sopenharmony_ci /* The /next/ file is the first dependency */ 7062306a36Sopenharmony_ci is_first_dep = 1; 7162306a36Sopenharmony_ci has_target = 1; 7262306a36Sopenharmony_ci } else if (has_target) { 7362306a36Sopenharmony_ci /* Save this token/filename */ 7462306a36Sopenharmony_ci memcpy(s, m, p-m); 7562306a36Sopenharmony_ci s[p - m] = 0; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* 7862306a36Sopenharmony_ci * Do not list the source file as dependency, 7962306a36Sopenharmony_ci * so that kbuild is not confused if a .c file 8062306a36Sopenharmony_ci * is rewritten into .S or vice versa. Storing 8162306a36Sopenharmony_ci * it in source_* is needed for modpost to 8262306a36Sopenharmony_ci * compute srcversions. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci if (is_first_dep) { 8562306a36Sopenharmony_ci /* 8662306a36Sopenharmony_ci * If processing the concatenation of 8762306a36Sopenharmony_ci * multiple dependency files, only 8862306a36Sopenharmony_ci * process the first target name, which 8962306a36Sopenharmony_ci * will be the original source name, 9062306a36Sopenharmony_ci * and ignore any other target names, 9162306a36Sopenharmony_ci * which will be intermediate temporary 9262306a36Sopenharmony_ci * files. 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ci if (!saw_any_target) { 9562306a36Sopenharmony_ci saw_any_target = 1; 9662306a36Sopenharmony_ci printf("source_%s := %s\n\n", 9762306a36Sopenharmony_ci target, s); 9862306a36Sopenharmony_ci printf("deps_%s := \\\n", 9962306a36Sopenharmony_ci target); 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci is_first_dep = 0; 10262306a36Sopenharmony_ci } else 10362306a36Sopenharmony_ci printf(" %s \\\n", s); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci /* 10662306a36Sopenharmony_ci * Start searching for next token immediately after the first 10762306a36Sopenharmony_ci * "whitespace" character that follows this token. 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ci m = p + 1; 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (!saw_any_target) { 11362306a36Sopenharmony_ci fprintf(stderr, "fixdep: parse error; no targets found\n"); 11462306a36Sopenharmony_ci exit(1); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci printf("\n%s: $(deps_%s)\n\n", target, target); 11862306a36Sopenharmony_ci printf("$(deps_%s):\n", target); 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic void print_deps(void) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct stat st; 12462306a36Sopenharmony_ci int fd; 12562306a36Sopenharmony_ci void *map; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci fd = open(depfile, O_RDONLY); 12862306a36Sopenharmony_ci if (fd < 0) { 12962306a36Sopenharmony_ci fprintf(stderr, "fixdep: error opening depfile: "); 13062306a36Sopenharmony_ci perror(depfile); 13162306a36Sopenharmony_ci exit(2); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci if (fstat(fd, &st) < 0) { 13462306a36Sopenharmony_ci fprintf(stderr, "fixdep: error fstat'ing depfile: "); 13562306a36Sopenharmony_ci perror(depfile); 13662306a36Sopenharmony_ci exit(2); 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci if (st.st_size == 0) { 13962306a36Sopenharmony_ci fprintf(stderr, "fixdep: %s is empty\n", depfile); 14062306a36Sopenharmony_ci close(fd); 14162306a36Sopenharmony_ci return; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 14462306a36Sopenharmony_ci if ((long) map == -1) { 14562306a36Sopenharmony_ci perror("fixdep: mmap"); 14662306a36Sopenharmony_ci close(fd); 14762306a36Sopenharmony_ci return; 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci parse_dep_file(map, st.st_size); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci munmap(map, st.st_size); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci close(fd); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciint main(int argc, char **argv) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci if (argc != 4) 16062306a36Sopenharmony_ci usage(); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci depfile = argv[1]; 16362306a36Sopenharmony_ci target = argv[2]; 16462306a36Sopenharmony_ci cmdline = argv[3]; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci print_cmdline(); 16762306a36Sopenharmony_ci print_deps(); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci} 171