171 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * "Optimize" a list of dependencies as spit out by gcc -MD4 * for the build framework.5 *6 * Original author:7 * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>8 *9 * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),10 * Please check it for detailed explanation. This fixdep borow only the11 * base transformation of dependecies without the CONFIG mangle.12 */13 14#include <sys/types.h>15#include <sys/stat.h>16#include <sys/mman.h>17#include <unistd.h>18#include <fcntl.h>19#include <string.h>20#include <stdlib.h>21#include <stdio.h>22#include <limits.h>23 24char *target;25char *depfile;26char *cmdline;27 28static void usage(void)29{30 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");31 exit(1);32}33 34/*35 * Print out the commandline prefixed with cmd_<target filename> :=36 */37static void print_cmdline(void)38{39 printf("cmd_%s := %s\n\n", target, cmdline);40}41 42/*43 * Important: The below generated source_foo.o and deps_foo.o variable44 * assignments are parsed not only by make, but also by the rather simple45 * parser in scripts/mod/sumversion.c.46 */47static void parse_dep_file(void *map, size_t len)48{49 char *m = map;50 char *end = m + len;51 char *p;52 char s[PATH_MAX];53 int is_target, has_target = 0;54 int saw_any_target = 0;55 int is_first_dep = 0;56 57 while (m < end) {58 /* Skip any "white space" */59 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))60 m++;61 /* Find next "white space" */62 p = m;63 while (p < end && *p != ' ' && *p != '\\' && *p != '\n')64 p++;65 /* Is the token we found a target name? */66 is_target = (*(p-1) == ':');67 /* Don't write any target names into the dependency file */68 if (is_target) {69 /* The /next/ file is the first dependency */70 is_first_dep = 1;71 has_target = 1;72 } else if (has_target) {73 /* Save this token/filename */74 memcpy(s, m, p-m);75 s[p - m] = 0;76 77 /*78 * Do not list the source file as dependency,79 * so that kbuild is not confused if a .c file80 * is rewritten into .S or vice versa. Storing81 * it in source_* is needed for modpost to82 * compute srcversions.83 */84 if (is_first_dep) {85 /*86 * If processing the concatenation of87 * multiple dependency files, only88 * process the first target name, which89 * will be the original source name,90 * and ignore any other target names,91 * which will be intermediate temporary92 * files.93 */94 if (!saw_any_target) {95 saw_any_target = 1;96 printf("source_%s := %s\n\n",97 target, s);98 printf("deps_%s := \\\n",99 target);100 }101 is_first_dep = 0;102 } else103 printf(" %s \\\n", s);104 }105 /*106 * Start searching for next token immediately after the first107 * "whitespace" character that follows this token.108 */109 m = p + 1;110 }111 112 if (!saw_any_target) {113 fprintf(stderr, "fixdep: parse error; no targets found\n");114 exit(1);115 }116 117 printf("\n%s: $(deps_%s)\n\n", target, target);118 printf("$(deps_%s):\n", target);119}120 121static void print_deps(void)122{123 struct stat st;124 int fd;125 void *map;126 127 fd = open(depfile, O_RDONLY);128 if (fd < 0) {129 fprintf(stderr, "fixdep: error opening depfile: ");130 perror(depfile);131 exit(2);132 }133 if (fstat(fd, &st) < 0) {134 fprintf(stderr, "fixdep: error fstat'ing depfile: ");135 perror(depfile);136 exit(2);137 }138 if (st.st_size == 0) {139 fprintf(stderr, "fixdep: %s is empty\n", depfile);140 close(fd);141 return;142 }143 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);144 if ((long) map == -1) {145 perror("fixdep: mmap");146 close(fd);147 return;148 }149 150 parse_dep_file(map, st.st_size);151 152 munmap(map, st.st_size);153 154 close(fd);155}156 157int main(int argc, char **argv)158{159 if (argc != 4)160 usage();161 162 depfile = argv[1];163 target = argv[2];164 cmdline = argv[3];165 166 print_cmdline();167 print_deps();168 169 return 0;170}171