Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * "Optimize" a list of dependencies as spit out by gcc -MD
0004  * for the build framework.
0005  *
0006  * Original author:
0007  *   Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
0008  *
0009  * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),
0010  * Please check it for detailed explanation. This fixdep borow only the
0011  * base transformation of dependecies without the CONFIG mangle.
0012  */
0013 
0014 #include <sys/types.h>
0015 #include <sys/stat.h>
0016 #include <sys/mman.h>
0017 #include <unistd.h>
0018 #include <fcntl.h>
0019 #include <string.h>
0020 #include <stdlib.h>
0021 #include <stdio.h>
0022 #include <limits.h>
0023 
0024 char *target;
0025 char *depfile;
0026 char *cmdline;
0027 
0028 static void usage(void)
0029 {
0030     fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
0031     exit(1);
0032 }
0033 
0034 /*
0035  * Print out the commandline prefixed with cmd_<target filename> :=
0036  */
0037 static void print_cmdline(void)
0038 {
0039     printf("cmd_%s := %s\n\n", target, cmdline);
0040 }
0041 
0042 /*
0043  * Important: The below generated source_foo.o and deps_foo.o variable
0044  * assignments are parsed not only by make, but also by the rather simple
0045  * parser in scripts/mod/sumversion.c.
0046  */
0047 static void parse_dep_file(void *map, size_t len)
0048 {
0049     char *m = map;
0050     char *end = m + len;
0051     char *p;
0052     char s[PATH_MAX];
0053     int is_target, has_target = 0;
0054     int saw_any_target = 0;
0055     int is_first_dep = 0;
0056 
0057     while (m < end) {
0058         /* Skip any "white space" */
0059         while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
0060             m++;
0061         /* Find next "white space" */
0062         p = m;
0063         while (p < end && *p != ' ' && *p != '\\' && *p != '\n')
0064             p++;
0065         /* Is the token we found a target name? */
0066         is_target = (*(p-1) == ':');
0067         /* Don't write any target names into the dependency file */
0068         if (is_target) {
0069             /* The /next/ file is the first dependency */
0070             is_first_dep = 1;
0071             has_target = 1;
0072         } else if (has_target) {
0073             /* Save this token/filename */
0074             memcpy(s, m, p-m);
0075             s[p - m] = 0;
0076 
0077             /*
0078              * Do not list the source file as dependency,
0079              * so that kbuild is not confused if a .c file
0080              * is rewritten into .S or vice versa. Storing
0081              * it in source_* is needed for modpost to
0082              * compute srcversions.
0083              */
0084             if (is_first_dep) {
0085                 /*
0086                  * If processing the concatenation of
0087                  * multiple dependency files, only
0088                  * process the first target name, which
0089                  * will be the original source name,
0090                  * and ignore any other target names,
0091                  * which will be intermediate temporary
0092                  * files.
0093                  */
0094                 if (!saw_any_target) {
0095                     saw_any_target = 1;
0096                     printf("source_%s := %s\n\n",
0097                         target, s);
0098                     printf("deps_%s := \\\n",
0099                         target);
0100                 }
0101                 is_first_dep = 0;
0102             } else
0103                 printf("  %s \\\n", s);
0104         }
0105         /*
0106          * Start searching for next token immediately after the first
0107          * "whitespace" character that follows this token.
0108          */
0109         m = p + 1;
0110     }
0111 
0112     if (!saw_any_target) {
0113         fprintf(stderr, "fixdep: parse error; no targets found\n");
0114         exit(1);
0115     }
0116 
0117     printf("\n%s: $(deps_%s)\n\n", target, target);
0118     printf("$(deps_%s):\n", target);
0119 }
0120 
0121 static void print_deps(void)
0122 {
0123     struct stat st;
0124     int fd;
0125     void *map;
0126 
0127     fd = open(depfile, O_RDONLY);
0128     if (fd < 0) {
0129         fprintf(stderr, "fixdep: error opening depfile: ");
0130         perror(depfile);
0131         exit(2);
0132     }
0133     if (fstat(fd, &st) < 0) {
0134         fprintf(stderr, "fixdep: error fstat'ing depfile: ");
0135         perror(depfile);
0136         exit(2);
0137     }
0138     if (st.st_size == 0) {
0139         fprintf(stderr, "fixdep: %s is empty\n", depfile);
0140         close(fd);
0141         return;
0142     }
0143     map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
0144     if ((long) map == -1) {
0145         perror("fixdep: mmap");
0146         close(fd);
0147         return;
0148     }
0149 
0150     parse_dep_file(map, st.st_size);
0151 
0152     munmap(map, st.st_size);
0153 
0154     close(fd);
0155 }
0156 
0157 int main(int argc, char **argv)
0158 {
0159     if (argc != 4)
0160         usage();
0161 
0162     depfile = argv[1];
0163     target  = argv[2];
0164     cmdline = argv[3];
0165 
0166     print_cmdline();
0167     print_deps();
0168 
0169     return 0;
0170 }