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.


Cleanup of linkage issues for non-Linux hosts
[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 #ifdef __minix
265 /* MINIX does not support memory-mapped files;
266  * fortunately we only need to read the file which means we can just
267  * use malloc and read to achieve a similar effect
268  */
269 #define mmap mmap_hack
270 #define munmap munmap_hack
271
272 #include <assert.h>
273
274 static void *mmap(void *start, size_t size, int prot, int flags, int fd, 
275         off_t offset)
276 {
277         void *map;
278         off_t position;
279         ssize_t sizeread;
280
281         /* verify that we can handle this request */
282         assert(start == NULL);
283         assert(prot == PROT_READ);
284         assert(flags == MAP_PRIVATE);
285
286         /* seek to offset, storing old file pointer */
287         if ((position = lseek(fd, 0, SEEK_CUR)) == -1 ||
288                 lseek(fd, offset, SEEK_SET) != offset) {
289                 perror("fixdep: lseek");
290         }
291
292         /* allocate memory for file buffer */
293         map = malloc(size);
294         if (map) {
295                 /* read the file data */
296                 sizeread = read(fd, map, size);
297                 if (sizeread != size) {
298                         /* read failed or file size not as expected, 
299                          * return mmap error code 
300                          */
301                         free(map);
302                         map = (void *) -1L;
303                 }
304         } else {
305                 /* malloc failed, return mmap error code */
306                 map = (void *) -1L;
307         }
308
309         /* restore old file pointer */
310         if (lseek(fd, position, SEEK_SET) != position) {
311                 perror("fixdep: lseek");
312         }
313
314         return map;
315 }
316
317 static int munmap(void *start, size_t length)
318 {
319         free(start);
320         return 0;
321 }
322 #endif
323
324 void do_config_file(char *filename)
325 {
326         struct stat st;
327         int fd;
328         void *map;
329
330         fd = open(filename, O_RDONLY);
331         if (fd < 0) {
332                 fprintf(stderr, "fixdep: ");
333                 perror(filename);
334                 exit(2);
335         }
336         fstat(fd, &st);
337         if (st.st_size == 0) {
338                 close(fd);
339                 return;
340         }
341         map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
342         if ((long) map == -1) {
343                 perror("fixdep: mmap");
344                 close(fd);
345                 return;
346         }
347
348         parse_config_file(map, st.st_size);
349
350         munmap(map, st.st_size);
351
352         close(fd);
353 }
354
355 void parse_dep_file(void *map, size_t len)
356 {
357         char *m = map;
358         char *end = m + len;
359         char *p;
360         char s[PATH_MAX];
361
362         p = strchr(m, ':');
363         if (!p) {
364                 fprintf(stderr, "fixdep: parse error\n");
365                 exit(1);
366         }
367         memcpy(s, m, p-m); s[p-m] = 0;
368         printf("deps_%s := \\\n", target);
369         m = p+1;
370
371         clear_config();
372
373         while (m < end) {
374                 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
375                         m++;
376                 p = m;
377                 while (p < end && *p != ' ') p++;
378                 if (p == end) {
379                         do p--; while (!isalnum(*p));
380                         p++;
381                 }
382                 memcpy(s, m, p-m); s[p-m] = 0;
383                 if (strrcmp(s, "include/linux/autoconf.h") &&
384                     strrcmp(s, "arch/um/include/uml-config.h") &&
385                     strrcmp(s, ".ver")) {
386                         printf("  %s \\\n", s);
387                         do_config_file(s);
388                 }
389                 m = p + 1;
390         }
391         printf("\n%s: $(deps_%s)\n\n", target, target);
392         printf("$(deps_%s):\n", target);
393 }
394
395 void print_deps(void)
396 {
397         struct stat st;
398         int fd;
399         void *map;
400
401         fd = open(depfile, O_RDONLY);
402         if (fd < 0) {
403                 fprintf(stderr, "fixdep: ");
404                 perror(depfile);
405                 exit(2);
406         }
407         fstat(fd, &st);
408         if (st.st_size == 0) {
409                 fprintf(stderr,"fixdep: %s is empty\n",depfile);
410                 close(fd);
411                 return;
412         }
413         map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
414         if ((long) map == -1) {
415                 perror("fixdep: mmap");
416                 close(fd);
417                 return;
418         }
419
420         parse_dep_file(map, st.st_size);
421
422         munmap(map, st.st_size);
423
424         close(fd);
425 }
426
427 void traps(void)
428 {
429         static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
430
431         if (*(int *)test != INT_CONF) {
432                 fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
433                         *(int *)test);
434                 exit(2);
435         }
436 }
437
438 int main(int argc, char *argv[])
439 {
440         traps();
441
442         if (argc != 4)
443                 usage();
444
445         depfile = argv[1];
446         target = argv[2];
447         cmdline = argv[3];
448
449         print_cmdline();
450         print_deps();
451
452         return 0;
453 }