Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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