comparison lib/swig/swigwin-2.0.11/CCache/ccache.c @ 1899:b3009adc0e2f

Adding swig, gitignore, hgignore
author Nomad
date Mon, 21 Oct 2013 10:42:27 +0200
parents
children
comparison
equal deleted inserted replaced
1867:eb580660bbbb 1899:b3009adc0e2f
1 /*
2 a re-implementation of the compilercache scripts in C
3
4 The idea is based on the shell-script compilercache by Erik Thiele <erikyyy@erikyyy.de>
5
6 Copyright (C) Andrew Tridgell 2002
7 Copyright (C) Martin Pool 2003
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "ccache.h"
25
26 /* verbose mode */
27 int ccache_verbose = 0;
28
29 /* the base cache directory */
30 char *cache_dir = NULL;
31
32 /* the directory for temporary files */
33 static char *temp_dir = NULL;
34
35 /* the debug logfile name, if set */
36 char *cache_logfile = NULL;
37
38 /* the argument list after processing */
39 static ARGS *stripped_args;
40
41 /* the original argument list */
42 static ARGS *orig_args;
43
44 /* the output filename being compiled to */
45 static char *output_file;
46
47 /* the source file */
48 static char *input_file;
49
50 /* the name of the file containing the cached object code */
51 static char *hashname;
52
53 /* the extension of the file after pre-processing */
54 static const char *i_extension;
55
56 /* the name of the temporary pre-processor file */
57 static char *i_tmpfile;
58
59 /* are we compiling a .i or .ii file directly? */
60 static int direct_i_file;
61
62 /* the name of the cpp stderr file */
63 static char *cpp_stderr;
64
65 /* the name of the statistics file */
66 char *stats_file = NULL;
67
68 /* can we safely use the unification hashing backend? */
69 static int enable_unify;
70
71 /* should we strip -c when running the preprocessor only? */
72 static int strip_c_option;
73
74 /* customisation for using the SWIG compiler */
75 static int swig;
76
77 /* a list of supported file extensions, and the equivalent
78 extension for code that has been through the pre-processor
79 */
80 static struct {
81 char *extension;
82 char *i_extension;
83 } extensions[] = {
84 {"c", "i"},
85 {"C", "ii"},
86 {"m", "mi"},
87 {"cc", "ii"},
88 {"CC", "ii"},
89 {"cpp", "ii"},
90 {"CPP", "ii"},
91 {"cxx", "ii"},
92 {"CXX", "ii"},
93 {"c++", "ii"},
94 {"C++", "ii"},
95 {"i", "i"},
96 {"ii", "ii"},
97 {NULL, NULL}};
98
99 /*
100 something went badly wrong - just execute the real compiler
101 */
102 static void failed(void)
103 {
104 char *e;
105
106 /* delete intermediate pre-processor file if needed */
107 if (i_tmpfile) {
108 if (!direct_i_file) {
109 unlink(i_tmpfile);
110 }
111 free(i_tmpfile);
112 i_tmpfile = NULL;
113 }
114
115 /* delete the cpp stderr file if necessary */
116 if (cpp_stderr) {
117 unlink(cpp_stderr);
118 free(cpp_stderr);
119 cpp_stderr = NULL;
120 }
121
122 /* strip any local args */
123 args_strip(orig_args, "--ccache-");
124
125 if ((e=getenv("CCACHE_PREFIX"))) {
126 char *p = find_executable(e, MYNAME);
127 if (!p) {
128 cc_log("could not find executable (%s)\n", e);
129 perror(e);
130 exit(1);
131 }
132 args_add_prefix(orig_args, p);
133 }
134
135 if (ccache_verbose) {
136 display_execute_args(orig_args->argv);
137 }
138
139 if (swig) {
140 putenv("CCACHE_OUTFILES");
141 }
142
143 #ifndef _WIN32
144 execv(orig_args->argv[0], orig_args->argv);
145 cc_log("execv returned (%s)!\n", strerror(errno));
146 perror(orig_args->argv[0]);
147 exit(1);
148 #else
149 /* execv on Windows causes the 'non-regular' testcase to fail, so use Win32 API instead */
150 {
151 PROCESS_INFORMATION pinfo;
152 STARTUPINFO sinfo;
153 BOOL ret;
154 DWORD exitcode;
155 char *args;
156
157 ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION));
158 ZeroMemory(&sinfo, sizeof(STARTUPINFO));
159 sinfo.cb = sizeof(STARTUPINFO);
160 args = argvtos(orig_args->argv);
161 ret = CreateProcessA(orig_args->argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL,
162 &sinfo, &pinfo);
163 if (!ret) {
164 exitcode = 1;
165 cc_log("CreateProcessA failed starting %s\n", orig_args->argv[0]);
166 perror_win32(orig_args->argv[0]);
167 } else {
168 WaitForSingleObject(pinfo.hProcess, INFINITE);
169 GetExitCodeProcess(pinfo.hProcess, &exitcode);
170 CloseHandle(pinfo.hProcess);
171 CloseHandle(pinfo.hThread);
172 }
173 free(args);
174 exit(exitcode);
175 }
176 #endif
177 }
178
179
180 /* return a string to be used to distinguish temporary files
181 this also tries to cope with NFS by adding the local hostname
182 */
183 static const char *tmp_string(void)
184 {
185 static char *ret;
186
187 if (!ret) {
188 char hostname[200];
189 strcpy(hostname, "unknown");
190 #if HAVE_GETHOSTNAME
191 gethostname(hostname, sizeof(hostname)-1);
192 #endif
193 hostname[sizeof(hostname)-1] = 0;
194 if (asprintf(&ret, "%s.%u", hostname, (unsigned)getpid()) == -1) {
195 fatal("could not allocate tmp_string");
196 }
197 }
198
199 return ret;
200 }
201
202 /* update cached file sizes and count helper function for to_cache() */
203 static void to_cache_stats_helper(struct stat *pstat, char *cached_filename, char *tmp_outfiles, int *files_size, int *cached_files_count)
204 {
205 #if ENABLE_ZLIB
206 /* do an extra stat on the cache file for the size statistics */
207 if (stat(cached_filename, pstat) != 0) {
208 cc_log("failed to stat cache files - %s\n", strerror(errno));
209 stats_update(STATS_ERROR);
210 if (tmp_outfiles) {
211 unlink(tmp_outfiles);
212 }
213 failed();
214 }
215 #else
216 (void)cached_filename;
217 (void)tmp_outfiles;
218 #endif
219 (*files_size) += file_size(pstat);
220 (*cached_files_count)++;
221 }
222
223 /* run the real compiler and put the result in cache */
224 static void to_cache(ARGS *args)
225 {
226 char *path_stderr;
227 char *tmp_stdout, *tmp_stderr, *tmp_outfiles;
228 struct stat st1;
229 int status;
230 int cached_files_count = 0;
231 int files_size = 0;
232
233 x_asprintf(&tmp_stdout, "%s/tmp.stdout.%s", temp_dir, tmp_string());
234 x_asprintf(&tmp_stderr, "%s/tmp.stderr.%s", temp_dir, tmp_string());
235 x_asprintf(&tmp_outfiles, "%s/tmp.outfiles.%s", temp_dir, tmp_string());
236
237 if (strip_c_option && !swig) {
238 args_add(stripped_args, "-c");
239 }
240
241 if (output_file) {
242 args_add(args, "-o");
243 args_add(args, output_file);
244 }
245
246 /* Turn off DEPENDENCIES_OUTPUT when running cc1, because
247 * otherwise it will emit a line like
248 *
249 * tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i
250 *
251 * unsetenv() is on BSD and Linux but not portable. */
252 putenv("DEPENDENCIES_OUTPUT");
253
254 /* Give SWIG a filename for it to create and populate with a list of files that it generates */
255 if (swig) {
256 char *ccache_outfiles;
257 x_asprintf(&ccache_outfiles, "CCACHE_OUTFILES=%s", tmp_outfiles);
258 unlink(tmp_outfiles);
259 if (getenv("CCACHE_OUTFILES") || putenv(ccache_outfiles) == -1) {
260 cc_log("CCACHE_OUTFILES env variable already set or could not be set\n");
261 stats_update(STATS_ERROR);
262 failed();
263 }
264 }
265
266 if (getenv("CCACHE_CPP2")) {
267 args_add(args, input_file);
268 } else {
269 if (swig) {
270 args_add(args, "-nopreprocess");
271 }
272 args_add(args, i_tmpfile);
273 }
274 status = execute(args->argv, tmp_stdout, tmp_stderr);
275 args_pop(args, 3);
276
277 if (stat(tmp_stdout, &st1) != 0 || st1.st_size != 0) {
278 cc_log("compiler produced stdout for %s\n", input_file);
279 stats_update(STATS_STDOUT);
280 unlink(tmp_stdout);
281 unlink(tmp_stderr);
282 unlink(tmp_outfiles);
283 if (!swig) unlink(output_file);
284 failed();
285 }
286 unlink(tmp_stdout);
287
288 if (status != 0) {
289 int fd;
290 cc_log("compile of %s gave status = %d\n", input_file, status);
291 stats_update(STATS_STATUS);
292
293 fd = open(tmp_stderr, O_RDONLY | O_BINARY);
294 if (fd != -1) {
295 if (cpp_stderr) {
296 /* we might have some stderr from cpp */
297 int fd2 = open(cpp_stderr, O_RDONLY | O_BINARY);
298 if (fd2 != -1) {
299 copy_fd(fd2, 2);
300 close(fd2);
301 unlink(cpp_stderr);
302 cpp_stderr = NULL;
303 }
304 }
305
306 /* we can use a quick method of
307 getting the failed output */
308 copy_fd(fd, 2);
309 close(fd);
310 unlink(tmp_stderr);
311 if (i_tmpfile && !direct_i_file) {
312 unlink(i_tmpfile);
313 }
314 exit(status);
315 }
316
317 unlink(tmp_stderr);
318 unlink(tmp_outfiles);
319 if (!swig) unlink(output_file);
320 failed();
321 } else {
322 int hardlink = (getenv("CCACHE_NOCOMPRESS") != 0) && (getenv("CCACHE_HARDLINK") != 0);
323 if (swig) {
324 /* read the list of generated files and copy each of them into the cache */
325 FILE *file;
326 file = fopen(tmp_outfiles, "r");
327 if (file) {
328 char out_filename[FILENAME_MAX + 1];
329 char out_filename_cache[FILENAME_MAX + 1];
330 while (fgets(out_filename, FILENAME_MAX, file)) {
331 char *linefeed = strchr(out_filename, '\n');
332 if (linefeed) {
333 char *potential_cr = linefeed - 1;
334 if (potential_cr >= out_filename && *potential_cr == '\r')
335 *potential_cr = 0;
336 *linefeed = 0;
337
338 if (cached_files_count == 0) {
339 strcpy(out_filename_cache, hashname);
340 } else {
341 sprintf(out_filename_cache, "%s.%d", hashname, cached_files_count);
342 }
343
344 if (commit_to_cache(out_filename, out_filename_cache, hardlink) != 0) {
345 fclose(file);
346 unlink(tmp_outfiles);
347 failed();
348 }
349 to_cache_stats_helper(&st1, out_filename_cache, tmp_outfiles, &files_size, &cached_files_count);
350 } else {
351 cached_files_count = 0;
352 break;
353 }
354 }
355 fclose(file);
356 if (cached_files_count == 0) {
357 cc_log("failed to copy output files to cache - internal error\n");
358 stats_update(STATS_ERROR);
359 unlink(tmp_outfiles);
360 failed();
361 }
362
363 /* also copy the (uncompressed) file containing the list of generated files into the cache */
364 sprintf(out_filename_cache, "%s.outfiles", hashname);
365 if (stat(tmp_outfiles, &st1) != 0 ||
366 safe_rename(tmp_outfiles, out_filename_cache) != 0) {
367 cc_log("failed to copy outfiles file to cache - %s\n", strerror(errno));
368 stats_update(STATS_ERROR);
369 unlink(tmp_outfiles);
370 failed();
371 }
372 to_cache_stats_helper(&st1, out_filename_cache, tmp_outfiles, &files_size, &cached_files_count);
373 unlink(tmp_outfiles);
374 } else {
375 cc_log("failed to open temp outfiles file - %s\n", strerror(errno));
376 stats_update(STATS_ERROR);
377 failed();
378 }
379 } else {
380 if (commit_to_cache(output_file, hashname, hardlink) != 0) {
381 failed();
382 }
383 to_cache_stats_helper(&st1, hashname, 0, &files_size, &cached_files_count);
384 }
385 }
386
387 x_asprintf(&path_stderr, "%s.stderr", hashname);
388
389 if (stat(tmp_stderr, &st1) != 0 ||
390 move_file(tmp_stderr, path_stderr) != 0) {
391 cc_log("failed to rename tmp files - %s\n", strerror(errno));
392 stats_update(STATS_ERROR);
393 failed();
394 }
395
396 to_cache_stats_helper(&st1, path_stderr, 0, &files_size, &cached_files_count);
397
398 cc_log("Placed %d files for %s into cache\n", cached_files_count, input_file);
399 stats_tocache(files_size, cached_files_count);
400
401 free(tmp_stderr);
402 free(tmp_stdout);
403 free(tmp_outfiles);
404 free(path_stderr);
405 }
406
407 /* find the hash for a command. The hash includes all argument lists,
408 plus the output from running the compiler with -E */
409 static void find_hash(ARGS *args)
410 {
411 int i;
412 char *path_stdout, *path_stderr;
413 char *hash_dir;
414 char *s;
415 struct stat st;
416 int status;
417 int nlevels = 2;
418 char *input_base;
419 char *tmp;
420
421 if ((s = getenv("CCACHE_NLEVELS"))) {
422 nlevels = atoi(s);
423 if (nlevels < 1) nlevels = 1;
424 if (nlevels > 8) nlevels = 8;
425 }
426
427 hash_start();
428
429 /* when we are doing the unifying tricks we need to include
430 the input file name in the hash to get the warnings right */
431 if (enable_unify || swig) {
432 hash_string(input_file);
433 }
434
435 if (swig) {
436 if (output_file) {
437 hash_string(output_file);
438 }
439 } else {
440 /* we have to hash the extension, as a .i file isn't treated the same
441 by the compiler as a .ii file */
442 hash_string(i_extension);
443 }
444
445 /* first the arguments */
446 for (i=1;i<args->argc;i++) {
447 /* some arguments don't contribute to the hash. The
448 theory is that these arguments will change the
449 output of -E if they are going to have any effect
450 at all, or they only affect linking */
451 if (i < args->argc-1) {
452 if (strcmp(args->argv[i], "-I") == 0 ||
453 strcmp(args->argv[i], "-include") == 0 ||
454 strcmp(args->argv[i], "-L") == 0 ||
455 strcmp(args->argv[i], "-D") == 0 ||
456 strcmp(args->argv[i], "-idirafter") == 0 ||
457 strcmp(args->argv[i], "-isystem") == 0) {
458 i++;
459 continue;
460 }
461 }
462 if (strncmp(args->argv[i], "-I", 2) == 0 ||
463 strncmp(args->argv[i], "-L", 2) == 0 ||
464 strncmp(args->argv[i], "-D", 2) == 0 ||
465 strncmp(args->argv[i], "-idirafter", 10) == 0 ||
466 strncmp(args->argv[i], "-isystem", 8) == 0) {
467 continue;
468 }
469
470 if (strncmp(args->argv[i], "--specs=", 8) == 0 &&
471 stat(args->argv[i]+8, &st) == 0) {
472 /* if given a explicit specs file, then hash that file, but
473 don't include the path to it in the hash */
474 hash_file(args->argv[i]+8);
475 continue;
476 }
477
478 /* all other arguments are included in the hash */
479 hash_string(args->argv[i]);
480 }
481
482 /* the compiler driver size and date. This is a simple minded way
483 to try and detect compiler upgrades. It is not 100% reliable */
484 if (stat(args->argv[0], &st) != 0) {
485 cc_log("Couldn't stat the compiler!? (argv[0]='%s')\n", args->argv[0]);
486 stats_update(STATS_COMPILER);
487 failed();
488 }
489
490 /* also include the hash of the compiler name - as some compilers
491 use hard links and behave differently depending on the real name */
492 if (st.st_nlink > 1) {
493 hash_string(str_basename(args->argv[0]));
494 }
495
496 hash_int(st.st_size);
497 hash_int(st.st_mtime);
498
499 /* possibly hash the current working directory */
500 if (getenv("CCACHE_HASHDIR")) {
501 char *cwd = gnu_getcwd();
502 if (cwd) {
503 hash_string(cwd);
504 free(cwd);
505 }
506 }
507
508 /* ~/hello.c -> tmp.hello.123.i
509 limit the basename to 10
510 characters in order to cope with filesystem with small
511 maximum filename length limits */
512 input_base = str_basename(input_file);
513 tmp = strchr(input_base, '.');
514 if (tmp != NULL) {
515 *tmp = 0;
516 }
517 if (strlen(input_base) > 10) {
518 input_base[10] = 0;
519 }
520
521 /* now the run */
522 x_asprintf(&path_stdout, "%s/%s.tmp.%s.%s", temp_dir,
523 input_base, tmp_string(),
524 i_extension);
525 x_asprintf(&path_stderr, "%s/tmp.cpp_stderr.%s", temp_dir, tmp_string());
526
527 if (!direct_i_file) {
528 /* run cpp on the input file to obtain the .i */
529 args_add(args, "-E");
530 args_add(args, input_file);
531 status = execute(args->argv, path_stdout, path_stderr);
532 args_pop(args, 2);
533 } else {
534 /* we are compiling a .i or .ii file - that means we
535 can skip the cpp stage and directly form the
536 correct i_tmpfile */
537 path_stdout = x_strdup(input_file);
538 if (create_empty_file(path_stderr) != 0) {
539 cc_log("failed to create empty stderr file\n");
540 stats_update(STATS_ERROR);
541 failed();
542 }
543 status = 0;
544 }
545
546 if (status != 0) {
547 if (!direct_i_file) {
548 unlink(path_stdout);
549 }
550 unlink(path_stderr);
551 cc_log("the preprocessor gave %d\n", status);
552 stats_update(STATS_PREPROCESSOR);
553 failed();
554 }
555
556 /* if the compilation is with -g then we have to include the whole of the
557 preprocessor output, which means we are sensitive to line number
558 information. Otherwise we can discard line number info, which makes
559 us less sensitive to reformatting changes
560
561 Note! I have now disabled the unification code by default
562 as it gives the wrong line numbers for warnings. Pity.
563 */
564 if (!enable_unify) {
565 hash_file(path_stdout);
566 } else {
567 if (unify_hash(path_stdout) != 0) {
568 stats_update(STATS_ERROR);
569 failed();
570 }
571 }
572 hash_file(path_stderr);
573
574 i_tmpfile = path_stdout;
575
576 if (!getenv("CCACHE_CPP2")) {
577 /* if we are using the CPP trick then we need to remember this stderr
578 data and output it just before the main stderr from the compiler
579 pass */
580 cpp_stderr = path_stderr;
581 } else {
582 unlink(path_stderr);
583 free(path_stderr);
584 }
585
586 /* we use a N level subdir for the cache path to reduce the impact
587 on filesystems which are slow for large directories
588 */
589 s = hash_result();
590 x_asprintf(&hash_dir, "%s/%c", cache_dir, s[0]);
591 x_asprintf(&stats_file, "%s/stats", hash_dir);
592 for (i=1; i<nlevels; i++) {
593 char *p;
594 if (create_dir(hash_dir) != 0) {
595 cc_log("failed to create %s\n", hash_dir);
596 stats_update(STATS_ERROR);
597 failed();
598 }
599 x_asprintf(&p, "%s/%c", hash_dir, s[i]);
600 free(hash_dir);
601 hash_dir = p;
602 }
603 if (create_dir(hash_dir) != 0) {
604 cc_log("failed to create %s\n", hash_dir);
605 stats_update(STATS_ERROR);
606 failed();
607 }
608 x_asprintf(&hashname, "%s/%s", hash_dir, s+nlevels);
609 free(hash_dir);
610 }
611
612 /*
613 try to return the compile result from cache. If we can return from
614 cache then this function exits with the correct status code,
615 otherwise it returns */
616 static void from_cache(int first)
617 {
618 int fd_stderr, fd_cpp_stderr;
619 char *stderr_file;
620 struct stat st;
621
622 x_asprintf(&stderr_file, "%s.stderr", hashname);
623 fd_stderr = open(stderr_file, O_RDONLY | O_BINARY);
624 if (fd_stderr == -1) {
625 /* it isn't in cache ... */
626 free(stderr_file);
627 return;
628 }
629
630 /* make sure the output is there too */
631 if (stat(hashname, &st) != 0) {
632 close(fd_stderr);
633 unlink(stderr_file);
634 free(stderr_file);
635 return;
636 }
637
638 /* the user might be disabling cache hits */
639 #ifndef ENABLE_ZLIB
640 /* if the cache file is compressed we must recache */
641 if ((first && getenv("CCACHE_RECACHE")) ||
642 test_if_compressed(hashname) == 1)
643 #else
644 if (first && getenv("CCACHE_RECACHE"))
645 #endif
646 {
647 close(fd_stderr);
648 unlink(stderr_file);
649 free(stderr_file);
650 return;
651 }
652
653 if (first) {
654 int hardlink;
655 int passfail = -1;
656
657 /* update timestamps for LRU cleanup
658 also gives output_file a sensible mtime when hard-linking (for make) */
659 x_utimes(stderr_file);
660
661 hardlink = (getenv("CCACHE_HARDLINK") != 0);
662
663 if (swig) {
664 /* read the list of generated files and copy each of them out of the cache */
665 FILE *file;
666 char *outfiles;
667 x_asprintf(&outfiles, "%s.outfiles", hashname);
668 file = fopen(outfiles, "r");
669 if (file) {
670 char out_filename[FILENAME_MAX + 1];
671 char out_filename_cache[FILENAME_MAX + 1];
672 int retrieved_files_count = 0;
673 x_utimes(outfiles);
674 while (fgets(out_filename, FILENAME_MAX, file)) {
675 char *linefeed = strchr(out_filename, '\n');
676 if (linefeed) {
677 char *potential_cr = linefeed - 1;
678 if (potential_cr >= out_filename && *potential_cr == '\r')
679 *potential_cr = 0;
680 *linefeed = 0;
681
682 if (retrieved_files_count == 0) {
683 strcpy(out_filename_cache, hashname);
684 } else {
685 sprintf(out_filename_cache, "%s.%d", hashname, retrieved_files_count);
686 }
687
688 passfail = retrieve_from_cache(out_filename_cache, out_filename, hardlink);
689 if (passfail == -1) {
690 break;
691 }
692
693 retrieved_files_count++;
694 } else {
695 cc_log("failed to copy output files from cache - internal error\n");
696 stats_update(STATS_ERROR);
697 passfail = -1;
698 break;
699 }
700 }
701 if (retrieved_files_count == 0) {
702 cc_log("failed to copy output files from cache - internal error\n");
703 stats_update(STATS_ERROR);
704 passfail = -1;
705 }
706 fclose(file);
707 } else {
708 cc_log("failed to open cached outfiles file - %s\n", strerror(errno));
709 stats_update(STATS_ERROR);
710 }
711 } else {
712 passfail = retrieve_from_cache(hashname, output_file, hardlink);
713 }
714
715 if (passfail == -1) {
716 close(fd_stderr);
717 unlink(stderr_file);
718 free(stderr_file);
719 return;
720 }
721 free(stderr_file);
722 }
723
724 /* get rid of the intermediate preprocessor file */
725 if (i_tmpfile) {
726 if (!direct_i_file) {
727 unlink(i_tmpfile);
728 }
729 free(i_tmpfile);
730 i_tmpfile = NULL;
731 }
732
733 /* send the cpp stderr, if applicable */
734 fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY);
735 if (fd_cpp_stderr != -1) {
736 copy_fd(fd_cpp_stderr, 2);
737 close(fd_cpp_stderr);
738 unlink(cpp_stderr);
739 free(cpp_stderr);
740 cpp_stderr = NULL;
741 }
742
743 /* send the stderr */
744 copy_fd(fd_stderr, 2);
745 close(fd_stderr);
746
747 /* and exit with the right status code */
748 if (first) {
749 cc_log("got cached result for %s\n", input_file);
750 stats_update(STATS_CACHED);
751 }
752
753 exit(0);
754 }
755
756 /* find the real compiler. We just search the PATH to find a executable of the
757 same name that isn't a link to ourselves */
758 static void find_compiler(int argc, char **argv)
759 {
760 char *base;
761 char *path;
762
763 orig_args = args_init(argc, argv);
764
765 base = str_basename(argv[0]);
766
767 /* we might be being invoked like "ccache gcc -c foo.c" */
768 if (strcmp(base, MYNAME) == 0) {
769 args_remove_first(orig_args);
770 free(base);
771 if (strchr(argv[1],'/')
772 #ifdef _WIN32
773 || strchr(argv[1],'\\')
774 #endif
775 ) {
776 /* a full path was given */
777 return;
778 }
779 base = str_basename(argv[1]);
780 }
781
782 /* support user override of the compiler */
783 if ((path=getenv("CCACHE_CC"))) {
784 base = x_strdup(path);
785 }
786
787 orig_args->argv[0] = find_executable(base, MYNAME);
788
789 /* can't find the compiler! */
790 if (!orig_args->argv[0]) {
791 stats_update(STATS_COMPILER);
792 cc_log("could not find compiler (%s)\n", base);
793 perror(base);
794 exit(1);
795 }
796 }
797
798
799 /* check a filename for C/C++ extension. Return the pre-processor
800 extension */
801 static const char *check_extension(const char *fname, int *direct_i)
802 {
803 int i;
804 const char *p;
805
806 if (direct_i) {
807 *direct_i = 0;
808 }
809
810 if (swig) return "ii"; /* any file extension is acceptable as input for SWIG */
811
812 p = strrchr(fname, '.');
813 if (!p) return NULL;
814 p++;
815 for (i=0; extensions[i].extension; i++) {
816 if (strcmp(p, extensions[i].extension) == 0) {
817 if (direct_i && strcmp(p, extensions[i].i_extension) == 0) {
818 *direct_i = 1;
819 }
820 p = getenv("CCACHE_EXTENSION");
821 if (p) return p;
822 return extensions[i].i_extension;
823 }
824 }
825 return NULL;
826 }
827
828
829 /*
830 process the compiler options to form the correct set of options
831 for obtaining the preprocessor output
832 */
833 static void process_args(int argc, char **argv)
834 {
835 int i;
836 int found_c_opt = 0;
837 int found_S_opt = 0;
838 struct stat st;
839 char *e;
840 /* is gcc being asked to output dependencies? */
841 int generating_dependencies = 0;
842 /* is the dependency makefile name overridden with -MF? */
843 int dependency_filename_specified = 0;
844 /* is the dependency makefile target name specified with -MQ or -MF? */
845 int dependency_target_specified = 0;
846
847
848 stripped_args = args_init(0, NULL);
849
850 args_add(stripped_args, argv[0]);
851
852 /* -c not required for SWIG */
853 if (swig) {
854 found_c_opt = 1;
855 }
856
857 for (i=1; i<argc; i++) {
858 /* some options will never work ... */
859 if (strcmp(argv[i], "-E") == 0) {
860 failed();
861 }
862
863 /* these are too hard */
864 if (strcmp(argv[i], "-fbranch-probabilities")==0 ||
865 strcmp(argv[i], "-fprofile-arcs") == 0 ||
866 strcmp(argv[i], "-ftest-coverage") == 0 ||
867 strcmp(argv[i], "--coverage") == 0 ||
868 strcmp(argv[i], "-M") == 0 ||
869 strcmp(argv[i], "-MM") == 0 ||
870 strcmp(argv[i], "-x") == 0) {
871 cc_log("argument %s is unsupported\n", argv[i]);
872 stats_update(STATS_UNSUPPORTED);
873 failed();
874 continue;
875 }
876
877 /* we must have -c */
878 if (strcmp(argv[i], "-c") == 0) {
879 if (!strip_c_option) {
880 args_add(stripped_args, argv[i]);
881 }
882 found_c_opt = 1;
883 continue;
884 }
885
886 /* -S changes the default extension */
887 if (strcmp(argv[i], "-S") == 0) {
888 args_add(stripped_args, argv[i]);
889 found_S_opt = 1;
890 continue;
891 }
892
893 /* we need to work out where the output was meant to go */
894 if (strcmp(argv[i], "-o") == 0) {
895 if (i == argc-1) {
896 cc_log("missing argument to %s\n", argv[i]);
897 stats_update(STATS_ARGS);
898 failed();
899 }
900 output_file = argv[i+1];
901 i++;
902 continue;
903 }
904
905 /* alternate form of -o, with no space */
906 if (!swig) { /* some of SWIG's arguments begin with -o */
907 if (strncmp(argv[i], "-o", 2) == 0) {
908 output_file = &argv[i][2];
909 continue;
910 }
911 }
912
913 /* debugging is handled specially, so that we know if we
914 can strip line number info
915 */
916 if (strncmp(argv[i], "-g", 2) == 0) {
917 args_add(stripped_args, argv[i]);
918 if (strcmp(argv[i], "-g0") != 0) {
919 enable_unify = 0;
920 }
921 continue;
922 }
923
924 /* The user knows best: just swallow the next arg */
925 if (strcmp(argv[i], "--ccache-skip") == 0) {
926 i++;
927 if (i == argc) {
928 failed();
929 }
930 args_add(stripped_args, argv[i]);
931 continue;
932 }
933
934 /* These options require special handling, because they
935 behave differently with gcc -E, when the output
936 file is not specified. */
937
938 if (strcmp(argv[i], "-MD") == 0 || strcmp(argv[i], "-MMD") == 0) {
939 generating_dependencies = 1;
940 } else if (strcmp(argv[i], "-MF") == 0) {
941 dependency_filename_specified = 1;
942 } else if (strcmp(argv[i], "-MQ") == 0 || strcmp(argv[i], "-MT") == 0) {
943 dependency_target_specified = 1;
944 }
945
946 /* the input file is already preprocessed */
947 if (swig && strcmp(argv[i], "-nopreprocess") == 0) {
948 direct_i_file = 1;
949 continue;
950 }
951
952 /* options that take an argument */
953 {
954 const char *opts[] = {"-I", "-include", "-imacros", "-iprefix",
955 "-iwithprefix", "-iwithprefixbefore",
956 "-L", "-D", "-U", "-x", "-MF",
957 "-MT", "-MQ", "-isystem", "-aux-info",
958 "--param", "-A", "-Xlinker", "-u",
959 "-idirafter",
960 NULL};
961 int j;
962 for (j=0;opts[j];j++) {
963 if (strcmp(argv[i], opts[j]) == 0) {
964 if (i == argc-1) {
965 cc_log("missing argument to %s\n",
966 argv[i]);
967 stats_update(STATS_ARGS);
968 failed();
969 }
970
971 args_add(stripped_args, argv[i]);
972 args_add(stripped_args, argv[i+1]);
973 i++;
974 break;
975 }
976 }
977 if (opts[j]) continue;
978 }
979
980 /* other options */
981 if (argv[i][0] == '-') {
982 args_add(stripped_args, argv[i]);
983 continue;
984 }
985
986 /* if an argument isn't a plain file then assume its
987 an option, not an input file. This allows us to
988 cope better with unusual compiler options */
989 if (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode)) {
990 args_add(stripped_args, argv[i]);
991 continue;
992 }
993
994 if (input_file) {
995 if (check_extension(argv[i], NULL)) {
996 cc_log("multiple input files (%s and %s)\n",
997 input_file, argv[i]);
998 stats_update(STATS_MULTIPLE);
999 } else if (!found_c_opt) {
1000 cc_log("called for link with %s\n", argv[i]);
1001 if (strstr(argv[i], "conftest.")) {
1002 stats_update(STATS_CONFTEST);
1003 } else {
1004 stats_update(STATS_LINK);
1005 }
1006 } else {
1007 cc_log("non C/C++ file %s\n", argv[i]);
1008 stats_update(STATS_NOTC);
1009 }
1010 failed();
1011 }
1012
1013 input_file = argv[i];
1014 }
1015
1016 if (!input_file) {
1017 cc_log("No input file found\n");
1018 stats_update(STATS_NOINPUT);
1019 failed();
1020 }
1021
1022 if (swig) {
1023 i_extension = check_extension(input_file, NULL);
1024 } else {
1025 i_extension = check_extension(input_file, &direct_i_file);
1026 }
1027 if (i_extension == NULL) {
1028 cc_log("Not a C/C++ file - %s\n", input_file);
1029 stats_update(STATS_NOTC);
1030 failed();
1031 }
1032
1033 if (!found_c_opt) {
1034 cc_log("No -c option found for %s\n", input_file);
1035 /* I find that having a separate statistic for autoconf tests is useful,
1036 as they are the dominant form of "called for link" in many cases */
1037 if (strstr(input_file, "conftest.")) {
1038 stats_update(STATS_CONFTEST);
1039 } else {
1040 stats_update(STATS_LINK);
1041 }
1042 failed();
1043 }
1044
1045
1046 /* don't try to second guess the compilers heuristics for stdout handling */
1047 if (output_file && strcmp(output_file, "-") == 0) {
1048 stats_update(STATS_OUTSTDOUT);
1049 failed();
1050 }
1051
1052 if (!swig && !output_file) {
1053 char *p;
1054 output_file = x_strdup(input_file);
1055 if ((p = strrchr(output_file, '/'))) {
1056 output_file = p+1;
1057 }
1058 p = strrchr(output_file, '.');
1059 if (!p || !p[1]) {
1060 cc_log("badly formed output_file %s\n", output_file);
1061 stats_update(STATS_ARGS);
1062 failed();
1063 }
1064 p[1] = found_S_opt ? 's' : 'o';
1065 p[2] = 0;
1066 }
1067
1068 /* If dependencies are generated, configure the preprocessor */
1069
1070 if (generating_dependencies && output_file) {
1071 if (!dependency_filename_specified) {
1072 char *default_depfile_name = x_strdup(output_file);
1073 char *p = strrchr(default_depfile_name, '.');
1074
1075 if (p) {
1076 if (strlen(p) < 2) {
1077 cc_log("badly formed dependency file %s\n", output_file);
1078 stats_update(STATS_ARGS);
1079 failed();
1080 return;
1081 }
1082 *p = 0;
1083 }
1084 else {
1085 int len = p - default_depfile_name;
1086
1087 p = x_malloc(len + 3);
1088 strncpy(default_depfile_name, p, len - 1);
1089 free(default_depfile_name);
1090 default_depfile_name = p;
1091 }
1092
1093 strcat(default_depfile_name, ".d");
1094 args_add(stripped_args, "-MF");
1095 args_add(stripped_args, default_depfile_name);
1096 }
1097
1098 if (!dependency_target_specified) {
1099 args_add(stripped_args, "-MT");
1100 args_add(stripped_args, output_file);
1101 }
1102 }
1103
1104 /* cope with -o /dev/null */
1105 if (output_file && strcmp(output_file,"/dev/null") != 0 && stat(output_file, &st) == 0 && !S_ISREG(st.st_mode)) {
1106 cc_log("Not a regular file %s\n", output_file);
1107 stats_update(STATS_DEVICE);
1108 failed();
1109 }
1110
1111 if ((e=getenv("CCACHE_PREFIX"))) {
1112 char *p = find_executable(e, MYNAME);
1113 if (!p) {
1114 cc_log("could not find executable (%s)\n", e);
1115 stats_update(STATS_ENVIRONMMENT);
1116 perror(e);
1117 exit(1);
1118 }
1119 args_add_prefix(stripped_args, p);
1120 }
1121 }
1122
1123 static void detect_swig()
1124 {
1125 char *basename = str_basename(orig_args->argv[0]);
1126 if (strstr(basename, "swig") || getenv("CCACHE_SWIG")) {
1127 swig = 1;
1128 }
1129 free(basename);
1130 }
1131
1132 /* the main ccache driver function */
1133 static void ccache(int argc, char *argv[])
1134 {
1135 /* find the real compiler */
1136 find_compiler(argc, argv);
1137
1138 /* use the real compiler if HOME is not set */
1139 if (!cache_dir) {
1140 cc_log("Unable to determine home directory\n");
1141 cc_log("ccache is disabled\n");
1142 failed();
1143 }
1144
1145 /* we might be disabled */
1146 if (getenv("CCACHE_DISABLE")) {
1147 cc_log("ccache is disabled\n");
1148 failed();
1149 }
1150
1151 if (getenv("CCACHE_STRIPC")) {
1152 strip_c_option = 1;
1153 }
1154
1155 if (getenv("CCACHE_UNIFY")) {
1156 enable_unify = 1;
1157 }
1158
1159 detect_swig();
1160
1161 /* process argument list, returning a new set of arguments for pre-processing */
1162 process_args(orig_args->argc, orig_args->argv);
1163
1164 /* run with -E to find the hash */
1165 find_hash(stripped_args);
1166
1167 /* if we can return from cache at this point then do */
1168 from_cache(1);
1169
1170 if (getenv("CCACHE_READONLY")) {
1171 cc_log("read-only set - doing real compile\n");
1172 failed();
1173 }
1174
1175 /* run real compiler, sending output to cache */
1176 to_cache(stripped_args);
1177
1178 /* return from cache */
1179 from_cache(0);
1180
1181 /* oh oh! */
1182 cc_log("secondary from_cache failed!\n");
1183 stats_update(STATS_ERROR);
1184 failed();
1185 }
1186
1187
1188 static void usage(void)
1189 {
1190 printf("%s, a compiler cache including support for SWIG. Version %s\n", MYNAME, CCACHE_VERSION);
1191 printf("Copyright Andrew Tridgell, 2002\n\n");
1192
1193 printf("Usage:\n");
1194 printf("\t" MYNAME " [options]\n");
1195 printf("\t" MYNAME " compiler [compile options]\n");
1196 printf("\tcompiler [compile options] (via symbolic link)\n");
1197 printf("\nOptions:\n");
1198
1199 printf("-s show statistics summary\n");
1200 printf("-z zero statistics\n");
1201 printf("-c run a cache cleanup\n");
1202 printf("-C clear the cache completely\n");
1203 printf("-F <maxfiles> set maximum files in cache\n");
1204 printf("-M <maxsize> set maximum size of cache (use G, M or K)\n");
1205 printf("-h this help page\n");
1206 printf("-V print version number\n");
1207 }
1208
1209 static void check_cache_dir(void)
1210 {
1211 if (!cache_dir) {
1212 fatal("Unable to determine home directory");
1213 }
1214 }
1215
1216 /* the main program when not doing a compile */
1217 static int ccache_main(int argc, char *argv[])
1218 {
1219 int c;
1220 size_t v;
1221
1222 while ((c = getopt(argc, argv, "hszcCF:M:V")) != -1) {
1223 switch (c) {
1224 case 'V':
1225 printf("%s version %s\n", MYNAME, CCACHE_VERSION);
1226 printf("Copyright Andrew Tridgell 2002\n");
1227 printf("Released under the GNU GPL v2 or later\n");
1228 exit(0);
1229
1230 case 'h':
1231 usage();
1232 exit(0);
1233
1234 case 's':
1235 check_cache_dir();
1236 stats_summary();
1237 break;
1238
1239 case 'c':
1240 check_cache_dir();
1241 cleanup_all(cache_dir);
1242 printf("Cleaned cache\n");
1243 break;
1244
1245 case 'C':
1246 check_cache_dir();
1247 wipe_all(cache_dir);
1248 printf("Cleared cache\n");
1249 break;
1250
1251 case 'z':
1252 check_cache_dir();
1253 stats_zero();
1254 printf("Statistics cleared\n");
1255 break;
1256
1257 case 'F':
1258 check_cache_dir();
1259 v = atoi(optarg);
1260 if (stats_set_limits(v, -1) == 0) {
1261 printf("Set cache file limit to %u\n", (unsigned)v);
1262 } else {
1263 printf("Could not set cache file limit.\n");
1264 exit(1);
1265 }
1266 break;
1267
1268 case 'M':
1269 check_cache_dir();
1270 v = value_units(optarg);
1271 if (stats_set_limits(-1, v) == 0) {
1272 printf("Set cache size limit to %uk\n", (unsigned)v);
1273 } else {
1274 printf("Could not set cache size limit.\n");
1275 exit(1);
1276 }
1277 break;
1278
1279 default:
1280 usage();
1281 exit(1);
1282 }
1283 }
1284
1285 return 0;
1286 }
1287
1288
1289 /* Make a copy of stderr that will not be cached, so things like
1290 distcc can send networking errors to it. */
1291 static void setup_uncached_err(void)
1292 {
1293 char *buf;
1294 int uncached_fd;
1295
1296 uncached_fd = dup(2);
1297 if (uncached_fd == -1) {
1298 cc_log("dup(2) failed\n");
1299 stats_update(STATS_ERROR);
1300 failed();
1301 }
1302
1303 /* leak a pointer to the environment */
1304 x_asprintf(&buf, "UNCACHED_ERR_FD=%d", uncached_fd);
1305
1306 if (putenv(buf) == -1) {
1307 cc_log("putenv failed\n");
1308 stats_update(STATS_ERROR);
1309 failed();
1310 }
1311 }
1312
1313
1314 int main(int argc, char *argv[])
1315 {
1316 char *p;
1317
1318 cache_dir = getenv("CCACHE_DIR");
1319 if (!cache_dir) {
1320 const char *home_directory = get_home_directory();
1321 if (home_directory) {
1322 x_asprintf(&cache_dir, "%s/.ccache", home_directory);
1323 }
1324 }
1325
1326 cache_logfile = getenv("CCACHE_LOGFILE");
1327
1328 if (getenv("CCACHE_VERBOSE")) {
1329 ccache_verbose = 1;
1330 }
1331
1332 setup_uncached_err();
1333
1334
1335 /* the user might have set CCACHE_UMASK */
1336 p = getenv("CCACHE_UMASK");
1337 if (p) {
1338 mode_t mask;
1339 errno = 0;
1340 mask = strtol(p, NULL, 8);
1341 if (errno == 0) {
1342 umask(mask);
1343 }
1344 }
1345
1346
1347 /* check if we are being invoked as "ccache" */
1348 if (strlen(argv[0]) >= strlen(MYNAME) &&
1349 strcmp(argv[0] + strlen(argv[0]) - strlen(MYNAME), MYNAME) == 0) {
1350 if (argc < 2) {
1351 usage();
1352 exit(1);
1353 }
1354 /* if the first argument isn't an option, then assume we are
1355 being passed a compiler name and options */
1356 if (argv[1][0] == '-') {
1357 return ccache_main(argc, argv);
1358 }
1359 }
1360
1361 /* make sure the cache dir exists */
1362 if (cache_dir && (create_dir(cache_dir) != 0)) {
1363 fprintf(stderr,"ccache: failed to create %s (%s)\n",
1364 cache_dir, strerror(errno));
1365 exit(1);
1366 }
1367
1368 temp_dir = getenv("CCACHE_TEMPDIR");
1369 if (!temp_dir) {
1370 x_asprintf(&temp_dir, "%s/temp", cache_dir);
1371 /* make sure temp dir exists if not supplied by user */
1372 if (temp_dir && create_dir(temp_dir) != 0) {
1373 fprintf(stderr,"ccache: failed to create %s (%s)\n",
1374 temp_dir, strerror(errno));
1375 exit(1);
1376 }
1377 }
1378
1379 if (!getenv("CCACHE_READONLY")) {
1380 if (create_cachedirtag(cache_dir) != 0) {
1381 fprintf(stderr,"ccache: failed to create %s/CACHEDIR.TAG (%s)\n",
1382 cache_dir, strerror(errno));
1383 exit(1);
1384 }
1385 }
1386
1387 ccache(argc, argv);
1388 return 1;
1389 }