OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [scripts/] [basic/] [fixdep.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * "Optimize" a list of dependencies as spit out by gcc -MD
3
 * for the kernel build
4
 * ===========================================================================
5
 *
6
 * Author       Kai Germaschewski
7
 * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
8
 *
9
 * This software may be used and distributed according to the terms
10
 * of the GNU General Public License, incorporated herein by reference.
11
 *
12
 *
13
 * Introduction:
14
 *
15
 * gcc produces a very nice and correct list of dependencies which
16
 * tells make when to remake a file.
17
 *
18
 * To use this list as-is however has the drawback that virtually
19
 * every file in the kernel includes <linux/config.h> which then again
20
 * includes <linux/autoconf.h>
21
 *
22
 * If the user re-runs make *config, linux/autoconf.h will be
23
 * regenerated.  make notices that and will rebuild every file which
24
 * includes autoconf.h, i.e. basically all files. This is extremely
25
 * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
26
 *
27
 * So we play the same trick that "mkdep" played before. We replace
28
 * the dependency on linux/autoconf.h by a dependency on every config
29
 * option which is mentioned in any of the listed prequisites.
30
 *
31
 * kconfig populates a tree in include/config/ with an empty file
32
 * for each config symbol and when the configuration is updated
33
 * the files representing changed config options are touched
34
 * which then let make pick up the changes and the files that use
35
 * the config symbols are rebuilt.
36
 *
37
 * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
38
 * which depend on "include/linux/config/his/driver.h" will be rebuilt,
39
 * so most likely only his driver ;-)
40
 *
41
 * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
42
 *
43
 * So to get dependencies right, there are two issues:
44
 * o if any of the files the compiler read changed, we need to rebuild
45
 * o if the command line given to the compile the file changed, we
46
 *   better rebuild as well.
47
 *
48
 * The former is handled by using the -MD output, the later by saving
49
 * the command line used to compile the old object and comparing it
50
 * to the one we would now use.
51
 *
52
 * Again, also this idea is pretty old and has been discussed on
53
 * kbuild-devel a long time ago. I don't have a sensibly working
54
 * internet connection right now, so I rather don't mention names
55
 * without double checking.
56
 *
57
 * This code here has been based partially based on mkdep.c, which
58
 * says the following about its history:
59
 *
60
 *   Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
61
 *   This is a C version of syncdep.pl by Werner Almesberger.
62
 *
63
 *
64
 * It is invoked as
65
 *
66
 *   fixdep <depfile> <target> <cmdline>
67
 *
68
 * and will read the dependency file <depfile>
69
 *
70
 * The transformed dependency snipped is written to stdout.
71
 *
72
 * It first generates a line
73
 *
74
 *   cmd_<target> = <cmdline>
75
 *
76
 * and then basically copies the .<target>.d file to stdout, in the
77
 * process filtering out the dependency on linux/autoconf.h and adding
78
 * dependencies on include/config/my/option.h for every
79
 * CONFIG_MY_OPTION encountered in any of the prequisites.
80
 *
81
 * It will also filter out all the dependencies on *.ver. We need
82
 * to make sure that the generated version checksum are globally up
83
 * to date before even starting the recursive build, so it's too late
84
 * at this point anyway.
85
 *
86
 * The algorithm to grep for "CONFIG_..." is bit unusual, but should
87
 * be fast ;-) We don't even try to really parse the header files, but
88
 * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
89
 * be picked up as well. It's not a problem with respect to
90
 * correctness, since that can only give too many dependencies, thus
91
 * we cannot miss a rebuild. Since people tend to not mention totally
92
 * unrelated CONFIG_ options all over the place, it's not an
93
 * efficiency problem either.
94
 *
95
 * (Note: it'd be easy to port over the complete mkdep state machine,
96
 *  but I don't think the added complexity is worth it)
97
 */
98
/*
99
 * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
100
 * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
101
 * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
102
 * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
103
 * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
104
 * those files will have correct dependencies.
105
 */
106
 
107
#include <sys/types.h>
108
#include <sys/stat.h>
109
#include <sys/mman.h>
110
#include <unistd.h>
111
#include <fcntl.h>
112
#include <string.h>
113
#include <stdlib.h>
114
#include <stdio.h>
115
#include <limits.h>
116
#include <ctype.h>
117
#include <arpa/inet.h>
118
 
119
#define INT_CONF ntohl(0x434f4e46)
120
#define INT_ONFI ntohl(0x4f4e4649)
121
#define INT_NFIG ntohl(0x4e464947)
122
#define INT_FIG_ ntohl(0x4649475f)
123
 
124
char *target;
125
char *depfile;
126
char *cmdline;
127
 
128
void usage(void)
129
 
130
{
131
        fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
132
        exit(1);
133
}
134
 
135
/*
136
 * Print out the commandline prefixed with cmd_<target filename> :=
137
 */
138
void print_cmdline(void)
139
{
140
        printf("cmd_%s := %s\n\n", target, cmdline);
141
}
142
 
143
char * str_config  = NULL;
144
int    size_config = 0;
145
int    len_config  = 0;
146
 
147
/*
148
 * Grow the configuration string to a desired length.
149
 * Usually the first growth is plenty.
150
 */
151
void grow_config(int len)
152
{
153
        while (len_config + len > size_config) {
154
                if (size_config == 0)
155
                        size_config = 2048;
156
                str_config = realloc(str_config, size_config *= 2);
157
                if (str_config == NULL)
158
                        { perror("fixdep:malloc"); exit(1); }
159
        }
160
}
161
 
162
 
163
 
164
/*
165
 * Lookup a value in the configuration string.
166
 */
167
int is_defined_config(const char * name, int len)
168
{
169
        const char * pconfig;
170
        const char * plast = str_config + len_config - len;
171
        for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
172
                if (pconfig[ -1] == '\n'
173
                &&  pconfig[len] == '\n'
174
                &&  !memcmp(pconfig, name, len))
175
                        return 1;
176
        }
177
        return 0;
178
}
179
 
180
/*
181
 * Add a new value to the configuration string.
182
 */
183
void define_config(const char * name, int len)
184
{
185
        grow_config(len + 1);
186
 
187
        memcpy(str_config+len_config, name, len);
188
        len_config += len;
189
        str_config[len_config++] = '\n';
190
}
191
 
192
/*
193
 * Clear the set of configuration strings.
194
 */
195
void clear_config(void)
196
{
197
        len_config = 0;
198
        define_config("", 0);
199
}
200
 
201
/*
202
 * Record the use of a CONFIG_* word.
203
 */
204
void use_config(char *m, int slen)
205
{
206
        char s[PATH_MAX];
207
        char *p;
208
 
209
        if (is_defined_config(m, slen))
210
            return;
211
 
212
        define_config(m, slen);
213
 
214
        memcpy(s, m, slen); s[slen] = 0;
215
 
216
        for (p = s; p < s + slen; p++) {
217
                if (*p == '_')
218
                        *p = '/';
219
                else
220
                        *p = tolower((int)*p);
221
        }
222
        printf("    $(wildcard include/config/%s.h) \\\n", s);
223
}
224
 
225
void parse_config_file(char *map, size_t len)
226
{
227
        int *end = (int *) (map + len);
228
        /* start at +1, so that p can never be < map */
229
        int *m   = (int *) map + 1;
230
        char *p, *q;
231
 
232
        for (; m < end; m++) {
233
                if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
234
                if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
235
                if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
236
                if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
237
                continue;
238
        conf:
239
                if (p > map + len - 7)
240
                        continue;
241
                if (memcmp(p, "CONFIG_", 7))
242
                        continue;
243
                for (q = p + 7; q < map + len; q++) {
244
                        if (!(isalnum(*q) || *q == '_'))
245
                                goto found;
246
                }
247
                continue;
248
 
249
        found:
250
                if (!memcmp(q - 7, "_MODULE", 7))
251
                        q -= 7;
252
                if( (q-p-7) < 0 )
253
                        continue;
254
                use_config(p+7, q-p-7);
255
        }
256
}
257
 
258
/* test is s ends in sub */
259
int strrcmp(char *s, char *sub)
260
{
261
        int slen = strlen(s);
262
        int sublen = strlen(sub);
263
 
264
        if (sublen > slen)
265
                return 1;
266
 
267
        return memcmp(s + slen - sublen, sub, sublen);
268
}
269
 
270
void do_config_file(char *filename)
271
{
272
        struct stat st;
273
        int fd;
274
        void *map;
275
 
276
        fd = open(filename, O_RDONLY);
277
        if (fd < 0) {
278
                fprintf(stderr, "fixdep: ");
279
                perror(filename);
280
                exit(2);
281
        }
282
        fstat(fd, &st);
283
        if (st.st_size == 0) {
284
                close(fd);
285
                return;
286
        }
287
        map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
288
        if ((long) map == -1) {
289
                perror("fixdep: mmap");
290
                close(fd);
291
                return;
292
        }
293
 
294
        parse_config_file(map, st.st_size);
295
 
296
        munmap(map, st.st_size);
297
 
298
        close(fd);
299
}
300
 
301
void parse_dep_file(void *map, size_t len)
302
{
303
        char *m = map;
304
        char *end = m + len;
305
        char *p;
306
        char s[PATH_MAX];
307
 
308
        p = strchr(m, ':');
309
        if (!p) {
310
                fprintf(stderr, "fixdep: parse error\n");
311
                exit(1);
312
        }
313
        memcpy(s, m, p-m); s[p-m] = 0;
314
        printf("deps_%s := \\\n", target);
315
        m = p+1;
316
 
317
        clear_config();
318
 
319
        while (m < end) {
320
                while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
321
                        m++;
322
                p = m;
323
                while (p < end && *p != ' ') p++;
324
                if (p == end) {
325
                        do p--; while (!isalnum(*p));
326
                        p++;
327
                }
328
                memcpy(s, m, p-m); s[p-m] = 0;
329
                if (strrcmp(s, "include/linux/autoconf.h") &&
330
                    strrcmp(s, "arch/um/include/uml-config.h") &&
331
                    strrcmp(s, ".ver")) {
332
                        printf("  %s \\\n", s);
333
                        do_config_file(s);
334
                }
335
                m = p + 1;
336
        }
337
        printf("\n%s: $(deps_%s)\n\n", target, target);
338
        printf("$(deps_%s):\n", target);
339
}
340
 
341
void print_deps(void)
342
{
343
        struct stat st;
344
        int fd;
345
        void *map;
346
 
347
        fd = open(depfile, O_RDONLY);
348
        if (fd < 0) {
349
                fprintf(stderr, "fixdep: ");
350
                perror(depfile);
351
                exit(2);
352
        }
353
        fstat(fd, &st);
354
        if (st.st_size == 0) {
355
                fprintf(stderr,"fixdep: %s is empty\n",depfile);
356
                close(fd);
357
                return;
358
        }
359
        map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
360
        if ((long) map == -1) {
361
                perror("fixdep: mmap");
362
                close(fd);
363
                return;
364
        }
365
 
366
        parse_dep_file(map, st.st_size);
367
 
368
        munmap(map, st.st_size);
369
 
370
        close(fd);
371
}
372
 
373
void traps(void)
374
{
375
        static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
376
 
377
        if (*(int *)test != INT_CONF) {
378
                fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
379
                        *(int *)test);
380
                exit(2);
381
        }
382
}
383
 
384
int main(int argc, char *argv[])
385
{
386
        traps();
387
 
388
        if (argc != 4)
389
                usage();
390
 
391
        depfile = argv[1];
392
        target = argv[2];
393
        cmdline = argv[3];
394
 
395
        print_cmdline();
396
        print_deps();
397
 
398
        return 0;
399
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.