]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
added support for CCACHE_PREFIX option
authorAndrew Tridgell <tridge@samba.org>
Sun, 16 Feb 2003 02:28:35 +0000 (03:28 +0100)
committerAndrew Tridgell <tridge@samba.org>
Sun, 16 Feb 2003 02:28:35 +0000 (03:28 +0100)
args.c
ccache.c
ccache.h
execute.c

diff --git a/args.c b/args.c
index 3dd71e9c5d2af9cea399cf5f9ecb04661c8ad870..fbbfe80bd70686e03b3bc7776b5239594524666e 100644 (file)
--- a/args.c
+++ b/args.c
 
 #include "ccache.h"
 
-ARGS *args_init(void)
+ARGS *args_init(int init_argc, char **init_args)
 {
        ARGS *args;
+       int i;
        args = (ARGS *)malloc(sizeof(ARGS));
        args->argc = 0;
        args->argv = (char **)malloc(sizeof(char *));
        args->argv[0] = NULL;
+       for (i=0;i<init_argc;i++) {
+               args_add(args, init_args[i]);
+       }
        return args;
 }
 
@@ -39,6 +43,7 @@ void args_add(ARGS *args, const char *s)
        args->argv[args->argc] = NULL;
 }
 
+/* pop the last element off the args list */
 void args_pop(ARGS *args, int n)
 {
        while (n--) {
@@ -48,20 +53,36 @@ void args_pop(ARGS *args, int n)
        }
 }
 
+/* remove the first element of the argument list */
+void args_remove_first(ARGS *args)
+{
+       free(args->argv[0]);
+       memmove(&args->argv[0], 
+               &args->argv[1],
+               args->argc * sizeof(args->argv[0]));
+       args->argc--;
+}
+
+/* add an argument into the front of the argument list */
+void args_add_prefix(ARGS *args, const char *s)
+{
+       args->argv = (char**)realloc(args->argv, (args->argc + 2) * sizeof(char *));
+       memmove(&args->argv[1], &args->argv[0], 
+               (args->argc+1) * sizeof(args->argv[0]));
+       args->argv[0] = strdup(s);
+       args->argc++;
+}
+
 /* strip any arguments beginning with the specified prefix */
 void args_strip(ARGS *args, const char *prefix)
 {
        int i;
        for (i=0; i<args->argc; ) {
                if (strncmp(args->argv[i], prefix, strlen(prefix)) == 0) {
-                       if (i < args->argc-1) {
-                               /* note that we can't free the entry we are removing
-                                  as it may be part of the original argc/argv passed
-                                  to main() */
-                               memmove(&args->argv[i], 
-                                       &args->argv[i+1], 
-                                       (args->argc-1) * sizeof(args->argv[i]));
-                       }
+                       free(args->argv[i]);
+                       memmove(&args->argv[i], 
+                               &args->argv[i+1], 
+                               args->argc * sizeof(args->argv[i]));
                        args->argc--;
                } else {
                        i++;
index d048c08e20f858f7a87d7c8ac50aa2d23bb5e530..a050a5f3486f8155d1da1e3630cc9f18649473d2 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -83,6 +83,8 @@ static struct {
 */
 static void failed(void)
 {
+       char *e;
+
        /* delete intermediate pre-processor file if needed */
        if (i_tmpfile) {
                unlink(i_tmpfile);
@@ -100,6 +102,15 @@ static void failed(void)
        /* strip any local args */
        args_strip(orig_args, "--ccache-");
 
+       if ((e=getenv("CCACHE_PREFIX"))) {
+               char *p = find_executable(e, MYNAME);
+               if (!p) {
+                       perror(e);
+                       exit(1);
+               }
+               args_add_prefix(orig_args, p);
+       }
+
        execv(orig_args->argv[0], orig_args->argv);
        cc_log("execv returned (%s)!\n", strerror(errno));
        perror(orig_args->argv[0]);
@@ -280,7 +291,7 @@ static void find_hash(ARGS *args)
        /* the compiler driver size and date. This is a simple minded way
           to try and detect compiler upgrades. It is not 100% reliable */
        if (stat(args->argv[0], &st) != 0) {
-               cc_log("Couldn't stat the compiler!?\n");
+               cc_log("Couldn't stat the compiler!? (argv[0]='%s')\n", args->argv[0]);
                stats_update(STATS_COMPILER);
                failed();
        }
@@ -476,21 +487,15 @@ static void from_cache(int first)
 static void find_compiler(int argc, char **argv)
 {
        char *base;
-       char *path, *tok;
-       struct stat st1, st2;
-
-       orig_args = args_init();
-       free(orig_args->argv);
+       char *path;
 
-       orig_args->argv = argv;
-       orig_args->argc = argc;
+       orig_args = args_init(argc, argv);
 
        base = basename(argv[0]);
 
        /* we might be being invoked like "ccache gcc -c foo.c" */
        if (strcmp(base, MYNAME) == 0) {
-               orig_args->argv++;
-               orig_args->argc--;
+               args_remove_first(orig_args);
                free(base);
                if (strchr(argv[1],'/')) {
                        /* a full path was given */
@@ -504,57 +509,13 @@ static void find_compiler(int argc, char **argv)
                base = strdup(path);
        }
 
-       path = getenv("CCACHE_PATH");
-       if (!path) {
-               path = getenv("PATH");
-       }
-       if (!path) {
-               cc_log("no PATH variable!?\n");
-               failed();
-       }
-
-       path = x_strdup(path);
-       
-       /* search the path looking for the first compiler of the right name
-          that isn't us */
-       for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) {
-               char *fname;
-               x_asprintf(&fname, "%s/%s", tok, base);
-               /* look for a normal executable file */
-               if (access(fname, X_OK) == 0 &&
-                   lstat(fname, &st1) == 0 &&
-                   stat(fname, &st2) == 0 &&
-                   S_ISREG(st2.st_mode)) {
-                       /* if its a symlink then ensure it doesn't
-                           point at something called "ccache" */
-                       if (S_ISLNK(st1.st_mode)) {
-                               char *buf = x_realpath(fname);
-                               if (buf) {
-                                       char *p = basename(buf);
-                                       if (strcmp(p, MYNAME) == 0) {
-                                               /* its a link to "ccache" ! */
-                                               free(p);
-                                               free(buf);
-                                               continue;
-                                       }
-                                       free(buf);
-                                       free(p);
-                               }
-                       }
-
-
-                       /* found it! */
-                       free(path);
-                       orig_args->argv[0] = fname;
-                       free(base);
-                       return;
-               }
-               free(fname);
-       }
+       orig_args->argv[0] = find_executable(base, MYNAME);
 
        /* can't find the compiler! */
-       perror(base);
-       exit(1);
+       if (!argv[0]) {
+               perror(base);
+               exit(1);
+       }
 }
 
 
@@ -589,8 +550,9 @@ static void process_args(int argc, char **argv)
        int found_c_opt = 0;
        int found_S_opt = 0;
        struct stat st;
+       char *e;
 
-       stripped_args = args_init();
+       stripped_args = args_init(0, NULL);
 
        args_add(stripped_args, argv[0]);
 
@@ -770,10 +732,6 @@ static void process_args(int argc, char **argv)
                }
                p[1] = found_S_opt ? 's' : 'o';
                p[2] = 0;
-#if 0
-               cc_log("Formed output file %s from input_file %s\n", 
-                      output_file, input_file);
-#endif
        }
 
        /* cope with -o /dev/null */
@@ -782,6 +740,15 @@ static void process_args(int argc, char **argv)
                stats_update(STATS_DEVICE);
                failed();
        }
+
+       if ((e=getenv("CCACHE_PREFIX"))) {
+               char *p = find_executable(e, MYNAME);
+               if (!p) {
+                       perror(e);
+                       exit(1);
+               }
+               args_add_prefix(stripped_args, p);
+       }
 }
 
 /* the main ccache driver function */
index e1e43bd805335977a394ba9b05ca0acfc2b94ad9..7cdca6648830120d5e7e7db134f2b9724234a3e2 100644 (file)
--- a/ccache.h
+++ b/ccache.h
@@ -118,6 +118,7 @@ void wipe_all(const char *dir);
 int execute(char **argv, 
            const char *path_stdout,
            const char *path_stderr);
+char *find_executable(const char *name, const char *exclude_name);
 
 typedef struct {
        char **argv;
@@ -125,10 +126,12 @@ typedef struct {
 } ARGS;
 
 
-ARGS *args_init(void);
+ARGS *args_init(int , char **);
 void args_add(ARGS *args, const char *s);
+void args_add_prefix(ARGS *args, const char *s);
 void args_pop(ARGS *args, int n);
 void args_strip(ARGS *args, const char *prefix);
+void args_remove_first(ARGS *args);
 
 #if HAVE_COMPAR_FN_T
 #define COMPAR_FN_T __compar_fn_t
index d36df63dd77c54a5a6203f3f4d54ce1421663857..97a29c1a7f1fb7136afb0051faa174753464b0d7 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -65,3 +65,61 @@ int execute(char **argv,
 
        return WEXITSTATUS(status);
 }
+
+
+/*
+  find an executable by name in $PATH. Exclude any that are links to exclude_name 
+*/
+char *find_executable(const char *name, const char *exclude_name)
+{
+       char *path;
+       char *tok;
+       struct stat st1, st2;
+
+       path = getenv("CCACHE_PATH");
+       if (!path) {
+               path = getenv("PATH");
+       }
+       if (!path) {
+               cc_log("no PATH variable!?\n");
+               return NULL;
+       }
+
+       path = x_strdup(path);
+       
+       /* search the path looking for the first compiler of the right name
+          that isn't us */
+       for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) {
+               char *fname;
+               x_asprintf(&fname, "%s/%s", tok, name);
+               /* look for a normal executable file */
+               if (access(fname, X_OK) == 0 &&
+                   lstat(fname, &st1) == 0 &&
+                   stat(fname, &st2) == 0 &&
+                   S_ISREG(st2.st_mode)) {
+                       /* if its a symlink then ensure it doesn't
+                           point at something called exclude_name */
+                       if (S_ISLNK(st1.st_mode)) {
+                               char *buf = x_realpath(fname);
+                               if (buf) {
+                                       char *p = basename(buf);
+                                       if (strcmp(p, exclude_name) == 0) {
+                                               /* its a link to "ccache" ! */
+                                               free(p);
+                                               free(buf);
+                                               continue;
+                                       }
+                                       free(buf);
+                                       free(p);
+                               }
+                       }
+
+                       /* found it! */
+                       free(path);
+                       return fname;
+               }
+               free(fname);
+       }
+
+       return NULL;
+}