18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * "Optimize" a list of dependencies as spit out by gcc -MD 48c2ecf20Sopenharmony_ci * for the build framework. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Original author: 78c2ecf20Sopenharmony_ci * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c), 108c2ecf20Sopenharmony_ci * Please check it for detailed explanation. This fixdep borow only the 118c2ecf20Sopenharmony_ci * base transformation of dependecies without the CONFIG mangle. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <sys/types.h> 158c2ecf20Sopenharmony_ci#include <sys/stat.h> 168c2ecf20Sopenharmony_ci#include <sys/mman.h> 178c2ecf20Sopenharmony_ci#include <unistd.h> 188c2ecf20Sopenharmony_ci#include <fcntl.h> 198c2ecf20Sopenharmony_ci#include <string.h> 208c2ecf20Sopenharmony_ci#include <stdlib.h> 218c2ecf20Sopenharmony_ci#include <stdio.h> 228c2ecf20Sopenharmony_ci#include <limits.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cichar *target; 258c2ecf20Sopenharmony_cichar *depfile; 268c2ecf20Sopenharmony_cichar *cmdline; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void usage(void) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n"); 318c2ecf20Sopenharmony_ci exit(1); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci * Print out the commandline prefixed with cmd_<target filename> := 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_cistatic void print_cmdline(void) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci printf("cmd_%s := %s\n\n", target, cmdline); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * Important: The below generated source_foo.o and deps_foo.o variable 448c2ecf20Sopenharmony_ci * assignments are parsed not only by make, but also by the rather simple 458c2ecf20Sopenharmony_ci * parser in scripts/mod/sumversion.c. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_cistatic void parse_dep_file(void *map, size_t len) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci char *m = map; 508c2ecf20Sopenharmony_ci char *end = m + len; 518c2ecf20Sopenharmony_ci char *p; 528c2ecf20Sopenharmony_ci char s[PATH_MAX]; 538c2ecf20Sopenharmony_ci int is_target, has_target = 0; 548c2ecf20Sopenharmony_ci int saw_any_target = 0; 558c2ecf20Sopenharmony_ci int is_first_dep = 0; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci while (m < end) { 588c2ecf20Sopenharmony_ci /* Skip any "white space" */ 598c2ecf20Sopenharmony_ci while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) 608c2ecf20Sopenharmony_ci m++; 618c2ecf20Sopenharmony_ci /* Find next "white space" */ 628c2ecf20Sopenharmony_ci p = m; 638c2ecf20Sopenharmony_ci while (p < end && *p != ' ' && *p != '\\' && *p != '\n') 648c2ecf20Sopenharmony_ci p++; 658c2ecf20Sopenharmony_ci /* Is the token we found a target name? */ 668c2ecf20Sopenharmony_ci is_target = (*(p-1) == ':'); 678c2ecf20Sopenharmony_ci /* Don't write any target names into the dependency file */ 688c2ecf20Sopenharmony_ci if (is_target) { 698c2ecf20Sopenharmony_ci /* The /next/ file is the first dependency */ 708c2ecf20Sopenharmony_ci is_first_dep = 1; 718c2ecf20Sopenharmony_ci has_target = 1; 728c2ecf20Sopenharmony_ci } else if (has_target) { 738c2ecf20Sopenharmony_ci /* Save this token/filename */ 748c2ecf20Sopenharmony_ci memcpy(s, m, p-m); 758c2ecf20Sopenharmony_ci s[p - m] = 0; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Do not list the source file as dependency, 798c2ecf20Sopenharmony_ci * so that kbuild is not confused if a .c file 808c2ecf20Sopenharmony_ci * is rewritten into .S or vice versa. Storing 818c2ecf20Sopenharmony_ci * it in source_* is needed for modpost to 828c2ecf20Sopenharmony_ci * compute srcversions. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci if (is_first_dep) { 858c2ecf20Sopenharmony_ci /* 868c2ecf20Sopenharmony_ci * If processing the concatenation of 878c2ecf20Sopenharmony_ci * multiple dependency files, only 888c2ecf20Sopenharmony_ci * process the first target name, which 898c2ecf20Sopenharmony_ci * will be the original source name, 908c2ecf20Sopenharmony_ci * and ignore any other target names, 918c2ecf20Sopenharmony_ci * which will be intermediate temporary 928c2ecf20Sopenharmony_ci * files. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci if (!saw_any_target) { 958c2ecf20Sopenharmony_ci saw_any_target = 1; 968c2ecf20Sopenharmony_ci printf("source_%s := %s\n\n", 978c2ecf20Sopenharmony_ci target, s); 988c2ecf20Sopenharmony_ci printf("deps_%s := \\\n", 998c2ecf20Sopenharmony_ci target); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci is_first_dep = 0; 1028c2ecf20Sopenharmony_ci } else 1038c2ecf20Sopenharmony_ci printf(" %s \\\n", s); 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci /* 1068c2ecf20Sopenharmony_ci * Start searching for next token immediately after the first 1078c2ecf20Sopenharmony_ci * "whitespace" character that follows this token. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci m = p + 1; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (!saw_any_target) { 1138c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: parse error; no targets found\n"); 1148c2ecf20Sopenharmony_ci exit(1); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci printf("\n%s: $(deps_%s)\n\n", target, target); 1188c2ecf20Sopenharmony_ci printf("$(deps_%s):\n", target); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void print_deps(void) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct stat st; 1248c2ecf20Sopenharmony_ci int fd; 1258c2ecf20Sopenharmony_ci void *map; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci fd = open(depfile, O_RDONLY); 1288c2ecf20Sopenharmony_ci if (fd < 0) { 1298c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: error opening depfile: "); 1308c2ecf20Sopenharmony_ci perror(depfile); 1318c2ecf20Sopenharmony_ci exit(2); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci if (fstat(fd, &st) < 0) { 1348c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: error fstat'ing depfile: "); 1358c2ecf20Sopenharmony_ci perror(depfile); 1368c2ecf20Sopenharmony_ci exit(2); 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci if (st.st_size == 0) { 1398c2ecf20Sopenharmony_ci fprintf(stderr, "fixdep: %s is empty\n", depfile); 1408c2ecf20Sopenharmony_ci close(fd); 1418c2ecf20Sopenharmony_ci return; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 1448c2ecf20Sopenharmony_ci if ((long) map == -1) { 1458c2ecf20Sopenharmony_ci perror("fixdep: mmap"); 1468c2ecf20Sopenharmony_ci close(fd); 1478c2ecf20Sopenharmony_ci return; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci parse_dep_file(map, st.st_size); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci munmap(map, st.st_size); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci close(fd); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci if (argc != 4) 1608c2ecf20Sopenharmony_ci usage(); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci depfile = argv[1]; 1638c2ecf20Sopenharmony_ci target = argv[2]; 1648c2ecf20Sopenharmony_ci cmdline = argv[3]; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci print_cmdline(); 1678c2ecf20Sopenharmony_ci print_deps(); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return 0; 1708c2ecf20Sopenharmony_ci} 171