linux/tools/build/fixdep.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * "Optimize" a list of dependencies as spit out by gcc -MD
   4 * 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 the
  11 * 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 variable
  44 * assignments are parsed not only by make, but also by the rather simple
  45 * 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 file
  80                         * is rewritten into .S or vice versa. Storing
  81                         * it in source_* is needed for modpost to
  82                         * compute srcversions.
  83                         */
  84                        if (is_first_dep) {
  85                                /*
  86                                 * If processing the concatenation of
  87                                 * multiple dependency files, only
  88                                 * process the first target name, which
  89                                 * will be the original source name,
  90                                 * and ignore any other target names,
  91                                 * which will be intermediate temporary
  92                                 * 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                        } else
 103                                printf("  %s \\\n", s);
 104                }
 105                /*
 106                 * Start searching for next token immediately after the first
 107                 * "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