]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add support for the -x GCC switch (Based on http://www.mail-archive.com/ccache@lists...
authorBernhard Bauer <bauerb@google.com>
Wed, 12 May 2010 11:50:24 +0000 (13:50 +0200)
committerBernhard Bauer <bauerb@google.com>
Mon, 24 May 2010 19:39:17 +0000 (12:39 -0700)
ccache.c

index adcfa2d885c9d9830309fc99d802daae9e8cdada..2150b822201e419b13631352bdb2eaa5ac9f90b3 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -179,27 +179,44 @@ static int nlevels = 2;
 static int compile_preprocessed_source_code;
 
 /* a list of supported file extensions, and the equivalent
-   extension for code that has been through the pre-processor
+   language
 */
 static const struct {
        const char *extension;
-       const char *i_extension;
+       const char *language;
 } extensions[] = {
-       {"c", "i"},
-       {"C", "ii"},
-       {"m", "mi"},
-       {"cc", "ii"},
-       {"CC", "ii"},
-       {"cpp", "ii"},
-       {"CPP", "ii"},
-       {"cxx", "ii"},
-       {"CXX", "ii"},
-       {"c++", "ii"},
-       {"C++", "ii"},
-       {"i", "i"},
-       {"ii", "ii"},
+       {"i", "c-cpp-output"},
+       {"ii", "c++-cpp-output"},
+       {"mi", "objective-c-cpp-output"},
+       {"mii", "objective-c++-cpp-output"},
+       {"c", "c"},
+       {"C", "c++"},
+       {"m", "objective-c"},
+       {"M", "objective-c++"},
+       {"mm", "objective-c++"},
+       {"cc", "c++"},
+       {"CC", "c++"},
+       {"cpp", "c++"},
+       {"CPP", "c++"},
+       {"cxx", "c++"},
+       {"CXX", "c++"},
+       {"c++", "c++"},
+       {"C++", "c++"},
        {NULL, NULL}};
 
+/* A list of languages and the equivalent language
+   after it has been preprocessed.
+*/
+static const struct {
+  const char *language;
+  const char *preprocessed_language;
+} preprocessed_languages[] = {
+  {"c", "c-cpp-output"},
+  {"c++", "c++-cpp-output"},
+  {"objective-c", "objective-c-cpp-output"},
+  {"objective-c++", "objective-c++-cpp-output"},
+  {NULL, NULL}};
+
 enum fromcache_call_mode {
        FROMCACHE_DIRECT_MODE,
        FROMCACHE_CPP_MODE,
@@ -479,6 +496,62 @@ static int process_preprocessed_file(struct mdfour *hash, const char *path)
        return 1;
 }
 
+/* Try to guess the language of a file based on its extension.
+ *  Return NULL if the extension is unknown.
+ */
+static const char *language_for_file(const char *fname)
+{
+       int i;
+       const char *p;
+
+       p = strrchr(fname, '.');
+       if (!p) return NULL;
+       p++;
+       for (i=0; extensions[i].extension; i++) {
+               if (strcmp(p, extensions[i].extension) == 0) {
+                       return extensions[i].language;
+               }
+       }
+       return NULL;
+}
+
+/* For a given language, return the language of the preprocessed file. */
+static const char *preprocessed_language(const char *language, int *direct_i)
+{
+       int i;
+
+       if (direct_i) {
+               *direct_i = 0;
+       }
+       for (i=0; preprocessed_languages[i].language; i++) {
+               if (strcmp(language, preprocessed_languages[i].language) == 0) {
+                       return preprocessed_languages[i].preprocessed_language;
+               }
+               if (strcmp(language, preprocessed_languages[i].preprocessed_language) == 0) {
+                       if (direct_i) {
+                               *direct_i = 1;
+                       }
+                       return preprocessed_languages[i].preprocessed_language;
+    }
+  }
+  return NULL;
+}
+
+/* Return the default file extension for a language */
+static const char *extension_for_language(const char *language)
+{
+       int i;
+       const char *extension = getenv("CCACHE_EXTENSION");
+       if (extension) return extension;
+
+       for (i=0; extensions[i].extension; i++) {
+               if (strcmp(language, extensions[i].language) == 0) {
+                       return extensions[i].extension;
+               }
+       }
+       return NULL;
+}
+
 /* run the real compiler and put the result in cache */
 static void to_cache(ARGS *args)
 {
@@ -486,6 +559,7 @@ static void to_cache(ARGS *args)
        struct stat st;
        int status;
        int compress;
+       int i;
 
        x_asprintf(&tmp_stdout, "%s.tmp.stdout.%s", cached_obj, tmp_string());
        x_asprintf(&tmp_stderr, "%s.tmp.stderr.%s", cached_obj, tmp_string());
@@ -503,6 +577,20 @@ static void to_cache(ARGS *args)
        putenv("DEPENDENCIES_OUTPUT");
 
        if (compile_preprocessed_source_code) {
+               for (i=0; i<args->argc; i++) {
+                       if (strcmp(args->argv[i], "-x") == 0) {
+                               i++;
+                               if (i < args->argc) {
+                                       char* language = args->argv[i];
+                                       const char* prepr_language = preprocessed_language(language, NULL);
+                                       if (prepr_language == NULL) {
+                                               failed();
+                                       }
+                                       args->argv[i] = x_strdup(prepr_language);
+                                       free(language);
+                               }
+                       }
+               }
                args_add(args, i_tmpfile);
        } else {
                args_add(args, input_file);
@@ -1187,35 +1275,6 @@ static void find_compiler(int argc, char **argv)
        orig_args->argv[0] = compiler;
 }
 
-
-/* check a filename for C/C++ extension. Return the pre-processor
-   extension */
-static const char *check_extension(const char *fname, int *direct_i)
-{
-       int i;
-       const char *p;
-
-       if (direct_i) {
-               *direct_i = 0;
-       }
-
-       p = strrchr(fname, '.');
-       if (!p) return NULL;
-       p++;
-       for (i=0; extensions[i].extension; i++) {
-               if (strcmp(p, extensions[i].extension) == 0) {
-                       if (direct_i && strcmp(p, extensions[i].i_extension) == 0) {
-                               *direct_i = 1;
-                       }
-                       p = getenv("CCACHE_EXTENSION");
-                       if (p) return p;
-                       return extensions[i].i_extension;
-               }
-       }
-       return NULL;
-}
-
-
 /*
    process the compiler options to form the correct set of options
    for obtaining the preprocessor output
@@ -1227,6 +1286,8 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
        int found_c_opt = 0;
        int found_S_opt = 0;
        int found_arch_opt = 0;
+       int found_x_opt = 0;
+       const char *input_language = NULL;
        struct stat st;
        /* is the dependency makefile name overridden with -MF? */
        int dependency_filename_specified = 0;
@@ -1257,8 +1318,7 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
                    strcmp(argv[i], "-fprofile-generate") == 0 ||
                    strcmp(argv[i], "-fprofile-use") == 0 ||
                    strcmp(argv[i], "-ftest-coverage") == 0 ||
-                   strcmp(argv[i], "-save-temps") == 0 ||
-                   strncmp(argv[i], "-x", 2) == 0) {
+                   strcmp(argv[i], "-save-temps") == 0) {
                        cc_log("Compiler option %s is unsupported", argv[i]);
                        stats_update(STATS_UNSUPPORTED);
                        failed();
@@ -1300,6 +1360,12 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
                        continue;
                }
 
+               /* -x can change the extension for the next input file */
+               if ((strcmp(argv[i], "-x") == 0) && !input_file) {
+                       found_x_opt = 1;
+                       input_language = argv[i+1];
+               }
+
                /* we need to work out where the output was meant to go */
                if (strcmp(argv[i], "-o") == 0) {
                        if (i == argc-1) {
@@ -1513,7 +1579,7 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
                }
 
                if (input_file) {
-                       if (check_extension(argv[i], NULL)) {
+                       if (language_for_file(argv[i])) {
                                cc_log("Multiple input files: %s and %s",
                                       input_file, argv[i]);
                                stats_update(STATS_MULTIPLE);
@@ -1541,12 +1607,15 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
                failed();
        }
 
-       i_extension = check_extension(input_file, &direct_i_file);
-       if (i_extension == NULL) {
+  if ((input_language == NULL) || (strcmp(input_language, "none") == 0)) {
+    input_language = language_for_file(input_file);
+  }
+  if (input_language == NULL) {
                cc_log("Not a C/C++ file: %s", input_file);
                stats_update(STATS_NOTC);
                failed();
-       }
+  }
+  i_extension = extension_for_language(preprocessed_language(input_language, &direct_i_file));
 
        if (!found_c_opt) {
                cc_log("No -c option found");