2
a re-implementation of the compilercache scripts in C
4
The idea is based on the shell-script compilercache by Erik Thiele <erikyyy@erikyyy.de>
6
Copyright (C) Andrew Tridgell 2002
7
Copyright (C) Martin Pool 2003
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.
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.
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.
26
/* the base cache directory */
27
char *cache_dir = NULL;
29
/* the debug logfile name, if set */
30
char *cache_logfile = NULL;
32
/* the argument list after processing */
33
static ARGS *stripped_args;
35
/* the original argument list */
36
static ARGS *orig_args;
38
/* the output filename being compiled to */
39
static char *output_file;
42
static char *input_file;
44
/* the name of the file containing the cached object code */
45
static char *hashname;
47
/* the extension of the file after pre-processing */
48
static const char *i_extension;
50
/* the name of the temporary pre-processor file */
51
static char *i_tmpfile;
53
/* are we compiling a .i or .ii file directly? */
54
static int direct_i_file;
56
/* the name of the cpp stderr file */
57
static char *cpp_stderr;
59
/* the name of the statistics file */
60
char *stats_file = NULL;
62
/* can we safely use the unification hashing backend? */
63
static int enable_unify;
65
/* a list of supported file extensions, and the equivalent
66
extension for code that has been through the pre-processor
88
something went badly wrong - just execute the real compiler
90
static void failed(void)
94
/* delete intermediate pre-processor file if needed */
103
/* delete the cpp stderr file if necessary */
110
/* strip any local args */
111
args_strip(orig_args, "--ccache-");
113
if ((e=getenv("CCACHE_PREFIX"))) {
114
char *p = find_executable(e, MYNAME);
119
args_add_prefix(orig_args, p);
122
execv(orig_args->argv[0], orig_args->argv);
123
cc_log("execv returned (%s)!\n", strerror(errno));
124
perror(orig_args->argv[0]);
129
/* return a string to be used to distinguish temporary files
130
this also tries to cope with NFS by adding the local hostname
132
static const char *tmp_string(void)
138
strcpy(hostname, "unknown");
140
gethostname(hostname, sizeof(hostname)-1);
142
hostname[sizeof(hostname)-1] = 0;
143
asprintf(&ret, "%s.%u", hostname, (unsigned)getpid());
150
/* run the real compiler and put the result in cache */
151
static void to_cache(ARGS *args)
154
char *tmp_stdout, *tmp_stderr, *tmp_hashname;
155
struct stat st1, st2;
158
x_asprintf(&tmp_stdout, "%s/tmp.stdout.%s", cache_dir, tmp_string());
159
x_asprintf(&tmp_stderr, "%s/tmp.stderr.%s", cache_dir, tmp_string());
160
x_asprintf(&tmp_hashname, "%s/tmp.hash.%s.o", cache_dir, tmp_string());
162
args_add(args, "-o");
163
args_add(args, tmp_hashname);
165
/* Turn off DEPENDENCIES_OUTPUT when running cc1, because
166
* otherwise it will emit a line like
168
* tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i
170
* unsetenv() is on BSD and Linux but not portable. */
171
putenv("DEPENDENCIES_OUTPUT");
173
if (getenv("CCACHE_CPP2")) {
174
args_add(args, input_file);
176
args_add(args, i_tmpfile);
178
status = execute(args->argv, tmp_stdout, tmp_stderr);
181
if (stat(tmp_stdout, &st1) != 0 || st1.st_size != 0) {
182
cc_log("compiler produced stdout for %s\n", output_file);
183
stats_update(STATS_STDOUT);
186
unlink(tmp_hashname);
193
cc_log("compile of %s gave status = %d\n", output_file, status);
194
stats_update(STATS_STATUS);
196
fd = open(tmp_stderr, O_RDONLY);
198
if (strcmp(output_file, "/dev/null") == 0 ||
199
rename(tmp_hashname, output_file) == 0 || errno == ENOENT) {
201
/* we might have some stderr from cpp */
202
int fd2 = open(cpp_stderr, O_RDONLY);
211
/* we can use a quick method of
212
getting the failed output */
216
if (i_tmpfile && !direct_i_file) {
224
unlink(tmp_hashname);
228
x_asprintf(&path_stderr, "%s.stderr", hashname);
230
if (stat(tmp_stderr, &st1) != 0 ||
231
stat(tmp_hashname, &st2) != 0 ||
232
rename(tmp_hashname, hashname) != 0 ||
233
rename(tmp_stderr, path_stderr) != 0) {
234
cc_log("failed to rename tmp files - %s\n", strerror(errno));
235
stats_update(STATS_ERROR);
239
cc_log("Placed %s into cache\n", output_file);
240
stats_tocache(file_size(&st1) + file_size(&st2));
248
/* find the hash for a command. The hash includes all argument lists,
249
plus the output from running the compiler with -E */
250
static void find_hash(ARGS *args)
253
char *path_stdout, *path_stderr;
262
if ((s = getenv("CCACHE_NLEVELS"))) {
264
if (nlevels < 1) nlevels = 1;
265
if (nlevels > 8) nlevels = 8;
270
/* when we are doing the unifying tricks we need to include
271
the input file name in the hash to get the warnings right */
273
hash_string(input_file);
276
/* we have to hash the extension, as a .i file isn't treated the same
277
by the compiler as a .ii file */
278
hash_string(i_extension);
280
/* first the arguments */
281
for (i=1;i<args->argc;i++) {
282
/* some arguments don't contribute to the hash. The
283
theory is that these arguments will change the
284
output of -E if they are going to have any effect
285
at all, or they only affect linking */
286
if (i < args->argc-1) {
287
if (strcmp(args->argv[i], "-I") == 0 ||
288
strcmp(args->argv[i], "-include") == 0 ||
289
strcmp(args->argv[i], "-L") == 0 ||
290
strcmp(args->argv[i], "-D") == 0 ||
291
strcmp(args->argv[i], "-idirafter") == 0 ||
292
strcmp(args->argv[i], "-isystem") == 0) {
297
if (strncmp(args->argv[i], "-I", 2) == 0 ||
298
strncmp(args->argv[i], "-L", 2) == 0 ||
299
strncmp(args->argv[i], "-D", 2) == 0 ||
300
strncmp(args->argv[i], "-idirafter", 10) == 0 ||
301
strncmp(args->argv[i], "-isystem", 8) == 0) {
305
if (strncmp(args->argv[i], "--specs=", 8) == 0 &&
306
stat(args->argv[i]+8, &st) == 0) {
307
/* if given a explicit specs file, then hash that file, but
308
don't include the path to it in the hash */
309
hash_file(args->argv[i]+8);
313
/* all other arguments are included in the hash */
314
hash_string(args->argv[i]);
317
/* the compiler driver size and date. This is a simple minded way
318
to try and detect compiler upgrades. It is not 100% reliable */
319
if (stat(args->argv[0], &st) != 0) {
320
cc_log("Couldn't stat the compiler!? (argv[0]='%s')\n", args->argv[0]);
321
stats_update(STATS_COMPILER);
324
hash_int(st.st_size);
325
hash_int(st.st_mtime);
327
/* possibly hash the current working directory */
328
if (getenv("CCACHE_HASHDIR")) {
329
char *cwd = gnu_getcwd();
336
/* ~/hello.c -> tmp.hello.123.i
337
limit the basename to 10
338
characters in order to cope with filesystem with small
339
maximum filename length limits */
340
input_base = str_basename(input_file);
341
tmp = strchr(input_base, '.');
345
if (strlen(input_base) > 10) {
350
x_asprintf(&path_stdout, "%s/%s.tmp.%s.%s", cache_dir,
351
input_base, tmp_string(),
353
x_asprintf(&path_stderr, "%s/tmp.cpp_stderr.%s", cache_dir, tmp_string());
355
if (!direct_i_file) {
356
/* run cpp on the input file to obtain the .i */
357
args_add(args, "-E");
358
args_add(args, input_file);
359
status = execute(args->argv, path_stdout, path_stderr);
362
/* we are compiling a .i or .ii file - that means we
363
can skip the cpp stage and directly form the
365
path_stdout = input_file;
366
if (create_empty_file(path_stderr) != 0) {
367
stats_update(STATS_ERROR);
368
cc_log("failed to create empty stderr file\n");
375
if (!direct_i_file) {
379
cc_log("the preprocessor gave %d\n", status);
380
stats_update(STATS_PREPROCESSOR);
384
/* if the compilation is with -g then we have to include the whole of the
385
preprocessor output, which means we are sensitive to line number
386
information. Otherwise we can discard line number info, which makes
387
us less sensitive to reformatting changes
389
Note! I have now disabled the unification code by default
390
as it gives the wrong line numbers for warnings. Pity.
393
hash_file(path_stdout);
395
if (unify_hash(path_stdout) != 0) {
396
stats_update(STATS_ERROR);
400
hash_file(path_stderr);
402
i_tmpfile = path_stdout;
404
if (!getenv("CCACHE_CPP2")) {
405
/* if we are using the CPP trick then we need to remember this stderr
406
data and output it just before the main stderr from the compiler
408
cpp_stderr = path_stderr;
414
/* we use a N level subdir for the cache path to reduce the impact
415
on filesystems which are slow for large directories
418
x_asprintf(&hash_dir, "%s/%c", cache_dir, s[0]);
419
x_asprintf(&stats_file, "%s/stats", hash_dir);
420
for (i=1; i<nlevels; i++) {
422
if (create_dir(hash_dir) != 0) {
423
cc_log("failed to create %s\n", hash_dir);
426
x_asprintf(&p, "%s/%c", hash_dir, s[i]);
430
if (create_dir(hash_dir) != 0) {
431
cc_log("failed to create %s\n", hash_dir);
434
x_asprintf(&hashname, "%s/%s", hash_dir, s+nlevels);
440
try to return the compile result from cache. If we can return from
441
cache then this function exits with the correct status code,
442
otherwise it returns */
443
static void from_cache(int first)
445
int fd_stderr, fd_cpp_stderr;
450
x_asprintf(&stderr_file, "%s.stderr", hashname);
451
fd_stderr = open(stderr_file, O_RDONLY);
452
if (fd_stderr == -1) {
453
/* it isn't in cache ... */
458
/* make sure the output is there too */
459
if (stat(hashname, &st) != 0) {
466
/* the user might be disabling cache hits */
467
if (first && getenv("CCACHE_RECACHE")) {
474
utime(stderr_file, NULL);
476
if (strcmp(output_file, "/dev/null") == 0) {
480
if (getenv("CCACHE_HARDLINK")) {
481
ret = link(hashname, output_file);
483
ret = copy_file(hashname, output_file);
487
/* the hash file might have been deleted by some external process */
488
if (ret == -1 && errno == ENOENT) {
489
cc_log("hashfile missing for %s\n", output_file);
490
stats_update(STATS_MISSING);
498
ret = copy_file(hashname, output_file);
500
cc_log("failed to copy %s -> %s (%s)\n",
501
hashname, output_file, strerror(errno));
502
stats_update(STATS_ERROR);
507
/* update the mtime on the file so that make doesn't get confused */
508
utime(output_file, NULL);
511
/* get rid of the intermediate preprocessor file */
513
if (!direct_i_file) {
520
/* send the cpp stderr, if applicable */
521
fd_cpp_stderr = open(cpp_stderr, O_RDONLY);
522
if (fd_cpp_stderr != -1) {
523
copy_fd(fd_cpp_stderr, 2);
524
close(fd_cpp_stderr);
530
/* send the stderr */
531
copy_fd(fd_stderr, 2);
534
/* and exit with the right status code */
536
cc_log("got cached result for %s\n", output_file);
537
stats_update(STATS_CACHED);
543
/* find the real compiler. We just search the PATH to find a executable of the
544
same name that isn't a link to ourselves */
545
static void find_compiler(int argc, char **argv)
550
orig_args = args_init(argc, argv);
552
base = str_basename(argv[0]);
554
/* we might be being invoked like "ccache gcc -c foo.c" */
555
if (strcmp(base, MYNAME) == 0) {
556
args_remove_first(orig_args);
558
if (strchr(argv[1],'/')) {
559
/* a full path was given */
562
base = str_basename(argv[1]);
565
/* support user override of the compiler */
566
if ((path=getenv("CCACHE_CC"))) {
570
orig_args->argv[0] = find_executable(base, MYNAME);
572
/* can't find the compiler! */
573
if (!orig_args->argv[0]) {
574
stats_update(STATS_COMPILER);
581
/* check a filename for C/C++ extension. Return the pre-processor
583
static const char *check_extension(const char *fname, int *direct_i)
592
p = strrchr(fname, '.');
595
for (i=0; extensions[i].extension; i++) {
596
if (strcmp(p, extensions[i].extension) == 0) {
597
if (direct_i && strcmp(p, extensions[i].i_extension) == 0) {
600
p = getenv("CCACHE_EXTENSION");
602
return extensions[i].i_extension;
610
process the compiler options to form the correct set of options
611
for obtaining the preprocessor output
613
static void process_args(int argc, char **argv)
621
stripped_args = args_init(0, NULL);
623
args_add(stripped_args, argv[0]);
625
for (i=1; i<argc; i++) {
626
/* some options will never work ... */
627
if (strcmp(argv[i], "-E") == 0) {
631
/* these are too hard */
632
if (strcmp(argv[i], "-fbranch-probabilities")==0 ||
633
strcmp(argv[i], "-M") == 0 ||
634
strcmp(argv[i], "-MM") == 0 ||
635
strcmp(argv[i], "-x") == 0) {
636
cc_log("argument %s is unsupported\n", argv[i]);
637
stats_update(STATS_UNSUPPORTED);
642
/* we must have -c */
643
if (strcmp(argv[i], "-c") == 0) {
644
args_add(stripped_args, argv[i]);
649
/* -S changes the default extension */
650
if (strcmp(argv[i], "-S") == 0) {
651
args_add(stripped_args, argv[i]);
656
/* we need to work out where the output was meant to go */
657
if (strcmp(argv[i], "-o") == 0) {
659
cc_log("missing argument to %s\n", argv[i]);
660
stats_update(STATS_ARGS);
663
output_file = argv[i+1];
668
/* alternate form of -o, with no space */
669
if (strncmp(argv[i], "-o", 2) == 0) {
670
output_file = &argv[i][2];
674
/* debugging is handled specially, so that we know if we
675
can strip line number info
677
if (strncmp(argv[i], "-g", 2) == 0) {
678
args_add(stripped_args, argv[i]);
679
if (strcmp(argv[i], "-g0") != 0) {
685
/* The user knows best: just swallow the next arg */
686
if (strcmp(argv[i], "--ccache-skip") == 0) {
691
args_add(stripped_args, argv[i]);
695
/* options that take an argument */
697
const char *opts[] = {"-I", "-include", "-imacros", "-iprefix",
698
"-iwithprefix", "-iwithprefixbefore",
699
"-L", "-D", "-U", "-x", "-MF",
700
"-MT", "-MQ", "-isystem", "-aux-info",
701
"--param", "-A", "-Xlinker", "-u",
705
for (j=0;opts[j];j++) {
706
if (strcmp(argv[i], opts[j]) == 0) {
708
cc_log("missing argument to %s\n",
710
stats_update(STATS_ARGS);
714
args_add(stripped_args, argv[i]);
715
args_add(stripped_args, argv[i+1]);
720
if (opts[j]) continue;
724
if (argv[i][0] == '-') {
725
args_add(stripped_args, argv[i]);
729
/* if an argument isn't a plain file then assume its
730
an option, not an input file. This allows us to
731
cope better with unusual compiler options */
732
if (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode)) {
733
args_add(stripped_args, argv[i]);
738
if (check_extension(argv[i], NULL)) {
739
cc_log("multiple input files (%s and %s)\n",
740
input_file, argv[i]);
741
stats_update(STATS_MULTIPLE);
742
} else if (!found_c_opt) {
743
cc_log("called for link with %s\n", argv[i]);
744
if (strstr(argv[i], "conftest.")) {
745
stats_update(STATS_CONFTEST);
747
stats_update(STATS_LINK);
750
cc_log("non C/C++ file %s\n", argv[i]);
751
stats_update(STATS_NOTC);
756
input_file = argv[i];
760
cc_log("No input file found\n");
761
stats_update(STATS_NOINPUT);
765
i_extension = check_extension(input_file, &direct_i_file);
766
if (i_extension == NULL) {
767
cc_log("Not a C/C++ file - %s\n", input_file);
768
stats_update(STATS_NOTC);
773
cc_log("No -c option found for %s\n", input_file);
774
/* I find that having a separate statistic for autoconf tests is useful,
775
as they are the dominant form of "called for link" in many cases */
776
if (strstr(input_file, "conftest.")) {
777
stats_update(STATS_CONFTEST);
779
stats_update(STATS_LINK);
785
/* don't try to second guess the compilers heuristics for stdout handling */
786
if (output_file && strcmp(output_file, "-") == 0) {
787
stats_update(STATS_OUTSTDOUT);
793
output_file = x_strdup(input_file);
794
if ((p = strrchr(output_file, '/'))) {
797
p = strrchr(output_file, '.');
799
cc_log("badly formed output_file %s\n", output_file);
800
stats_update(STATS_ARGS);
803
p[1] = found_S_opt ? 's' : 'o';
807
/* cope with -o /dev/null */
808
if (strcmp(output_file,"/dev/null") != 0 && stat(output_file, &st) == 0 && !S_ISREG(st.st_mode)) {
809
cc_log("Not a regular file %s\n", output_file);
810
stats_update(STATS_DEVICE);
814
if ((e=getenv("CCACHE_PREFIX"))) {
815
char *p = find_executable(e, MYNAME);
820
args_add_prefix(stripped_args, p);
824
/* the main ccache driver function */
825
static void ccache(int argc, char *argv[])
827
/* find the real compiler */
828
find_compiler(argc, argv);
830
/* we might be disabled */
831
if (getenv("CCACHE_DISABLE")) {
832
cc_log("ccache is disabled\n");
836
if (getenv("CCACHE_UNIFY")) {
840
/* process argument list, returning a new set of arguments for pre-processing */
841
process_args(orig_args->argc, orig_args->argv);
843
/* run with -E to find the hash */
844
find_hash(stripped_args);
846
/* if we can return from cache at this point then do */
849
/* run real compiler, sending output to cache */
850
to_cache(stripped_args);
852
/* return from cache */
856
cc_log("secondary from_cache failed!\n");
857
stats_update(STATS_ERROR);
862
static void usage(void)
864
printf("ccache, a compiler cache. Version %s\n", CCACHE_VERSION);
865
printf("Copyright Andrew Tridgell, 2002\n\n");
868
printf("\tccache [options]\n");
869
printf("\tccache compiler [compile options]\n");
870
printf("\tcompiler [compile options] (via symbolic link)\n");
871
printf("\nOptions:\n");
873
printf("-s show statistics summary\n");
874
printf("-z zero statistics\n");
875
printf("-c run a cache cleanup\n");
876
printf("-C clear the cache completely\n");
877
printf("-F <maxfiles> set maximum files in cache\n");
878
printf("-M <maxsize> set maximum size of cache (use G, M or K)\n");
879
printf("-h this help page\n");
880
printf("-V print version number\n");
883
/* the main program when not doing a compile */
884
static int ccache_main(int argc, char *argv[])
890
while ((c = getopt(argc, argv, "hszcCF:M:V")) != -1) {
893
printf("ccache version %s\n", CCACHE_VERSION);
894
printf("Copyright Andrew Tridgell 2002\n");
895
printf("Released under the GNU GPL v2 or later\n");
907
cleanup_all(cache_dir);
908
printf("Cleaned cache\n");
913
printf("Cleared cache\n");
918
printf("Statistics cleared\n");
923
stats_set_limits(v, -1);
924
printf("Set cache file limit to %u\n", (unsigned)v);
928
v = value_units(optarg);
929
stats_set_limits(-1, v);
930
printf("Set cache size limit to %uk\n", (unsigned)v);
943
/* Make a copy of stderr that will not be cached, so things like
944
distcc can send networking errors to it. */
945
static void setup_uncached_err(void)
950
uncached_fd = dup(2);
951
if (uncached_fd == -1) {
952
cc_log("dup(2) failed\n");
956
/* leak a pointer to the environment */
957
x_asprintf(&buf, "UNCACHED_ERR_FD=%d", uncached_fd);
959
if (putenv(buf) == -1) {
960
cc_log("putenv failed\n");
966
int main(int argc, char *argv[])
970
cache_dir = getenv("CCACHE_DIR");
972
x_asprintf(&cache_dir, "%s/.ccache", getenv("HOME"));
975
cache_logfile = getenv("CCACHE_LOGFILE");
977
setup_uncached_err();
980
/* the user might have set CCACHE_UMASK */
981
p = getenv("CCACHE_UMASK");
985
mask = strtol(p, NULL, 8);
992
/* check if we are being invoked as "ccache" */
993
if (strlen(argv[0]) >= strlen(MYNAME) &&
994
strcmp(argv[0] + strlen(argv[0]) - strlen(MYNAME), MYNAME) == 0) {
999
/* if the first argument isn't an option, then assume we are
1000
being passed a compiler name and options */
1001
if (argv[1][0] == '-') {
1002
return ccache_main(argc, argv);
1006
/* make sure the cache dir exists */
1007
if (create_dir(cache_dir) != 0) {
1008
fprintf(stderr,"ccache: failed to create %s (%s)\n",
1009
cache_dir, strerror(errno));