diff --git a/README b/README index 91f0ee5..cf0775f 100644 --- a/README +++ b/README @@ -29,11 +29,6 @@ This will work as long as /usr/local/bin comes before the path to gcc (which is usually in /usr/bin). After installing you may wish to run "rehash; type gcc" to make sure that the correct link is being used. -If you are installing on a system that doesn't have a /proc/self/exe -link (ie. most non-Linux systems) then you also also need to set the -CCACHE_PATH environment variable. - - Configuration ------------- @@ -56,12 +51,10 @@ will be fine. CCACHE_PATH - You need to set the CCACHE_PATH environment variable on systems - that don't have a Linux-like /proc filesystem. It should be set to - a colon separated list of directories where ccache will look for - the real compilers. On Linux this is not needed because ccache can - use /proc/self/exe and the normal PATH variable to find the - compiler. + You can optionally set CCACHE_PATH to a colon separated path where ccache will + look for the real compilers. If you don't do this then ccache will + look for the first executable in the normal PATH that isn't a link + to ccache itself. Differences diff --git a/ccache.c b/ccache.c index 87c17a0..7b30ff2 100644 --- a/ccache.c +++ b/ccache.c @@ -57,14 +57,6 @@ static void to_cache(ARGS *args) status = execute(args->argv, tmp_stdout, tmp_stderr); args->argc -= 2; - if (status != 0) { - cc_log("compile of %s gave status = %d\n", output_file, status); - unlink(tmp_stdout); - unlink(tmp_stderr); - unlink(tmp_hashname); - failed(); - } - if (stat(tmp_stdout, &st) != 0 || st.st_size != 0) { cc_log("compiler produced stdout for %s\n", output_file); unlink(tmp_stdout); @@ -72,9 +64,27 @@ static void to_cache(ARGS *args) unlink(tmp_hashname); failed(); } - unlink(tmp_stdout); + if (status != 0) { + int fd; + cc_log("compile of %s gave status = %d\n", output_file, status); + + fd = open(tmp_stderr, O_RDONLY); + if (fd != -1 && + (rename(tmp_hashname, output_file) == 0 || errno == ENOENT)) { + /* we can use a quick method of getting the failed output */ + copy_fd(fd, 2); + close(fd); + unlink(tmp_stderr); + exit(status); + } + + unlink(tmp_stderr); + unlink(tmp_hashname); + failed(); + } + x_asprintf(&path_stderr, "%s.stderr", hashname); if (rename(tmp_hashname, hashname) != 0 || @@ -253,6 +263,7 @@ static char *find_compiler(const char *argv0) char *base; char *path, *tok; struct stat st1, st2; + int found_one = 0; p = strrchr(argv0, '/'); if (p) { @@ -261,16 +272,14 @@ static char *find_compiler(const char *argv0) base = x_strdup(argv0); } - /* we compare size, device and inode. On non-Linux systems - we rely on CCACHE_PATH being set and end up just using the first - executable we find in the path - */ - if (stat("/proc/self/exe", &st1) != 0) { - if (!getenv("CCACHE_PATH")) { - cc_log("You must set CCACHE_PATH\n"); - exit(1); - } - memset(&st1, 0, sizeof(st1)); + /* try to find ourselves the linux way */ + if (stat("/proc/self/exe", &st1) == 0) { + found_one = 1; + } + + /* they might have given a full path ... */ + if (!found_one && strchr(argv0, '/') && stat(argv0, &st1) == 0) { + found_one = 1; } path = getenv("CCACHE_PATH"); @@ -293,6 +302,13 @@ static char *find_compiler(const char *argv0) if (access(fname, X_OK) == 0 && stat(fname, &st2) == 0 && S_ISREG(st2.st_mode)) { + /* we have a candidate */ + if (!found_one) { + st1 = st2; + found_one = 1; + continue; + } + if (st1.st_size != st2.st_size || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { diff --git a/ccache.h b/ccache.h index 285b219..4720a2a 100644 --- a/ccache.h +++ b/ccache.h @@ -54,5 +54,3 @@ typedef struct { ARGS *args_init(void); void args_add(ARGS *args, const char *s); - -