From: David Givone Date: Fri, 21 Sep 2012 07:19:55 +0000 (-0700) Subject: Store clang diagnostic file to cache X-Git-Tag: v3.2~70 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=19c344bb1c43d1d1f77ef5c48db03f4dcb23cc64;p=thirdparty%2Fccache.git Store clang diagnostic file to cache Added support for clang's --serialize-diagnostic parameter. The diagnostics file is now stored in the cache. Xcode uses this option when building. --- diff --git a/ccache.c b/ccache.c index f899bf906..db8786542 100644 --- a/ccache.c +++ b/ccache.c @@ -95,6 +95,9 @@ static char *output_obj; /* The path to the dependency file (implicit or specified with -MF). */ static char *output_dep; +/* diagnostic generation information (clang) */ +static char *output_dia = NULL; + /* * Name (represented as a struct file_hash) of the file containing the cached * object code. @@ -119,6 +122,12 @@ static char *cached_stderr; */ static char *cached_dep; +/* + * Full path to the file containing the diagnostic information (for clang) + * (cachedir/a/b/cdef[...]-size.dia). + */ +static char *cached_dia; + /* * Full path to the file containing the manifest * (cachedir/a/b/cdef[...]-size.manifest). @@ -571,7 +580,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path) static void to_cache(struct args *args) { - char *tmp_stdout, *tmp_stderr, *tmp_obj; + char *tmp_stdout, *tmp_stderr, *tmp_obj, *tmp_dia; struct stat st; int status; size_t added_bytes = 0; @@ -594,6 +603,19 @@ to_cache(struct args *args) args_add(args, "-o"); args_add(args, tmp_obj); + if( output_dia != 0 ) { + if( output_to_real_object_first ) { + tmp_dia = x_strdup(output_dia); + cc_log("Outputting to final destination: %s", tmp_dia); + } else { + tmp_dia = format("%s.tmp.dia.%s", cached_obj, tmp_string()); + } + args_add(args, "--serialize-diagnostics"); + args_add(args, tmp_dia); + } else { + tmp_dia = NULL; + } + /* Turn off DEPENDENCIES_OUTPUT when running cc1, because * otherwise it will emit a line like * @@ -621,6 +643,9 @@ to_cache(struct args *args) tmp_unlink(tmp_stdout); tmp_unlink(tmp_stderr); tmp_unlink(tmp_obj); + if( tmp_dia != 0 ) { + tmp_unlink(tmp_dia); + } failed(); } tmp_unlink(tmp_stdout); @@ -687,6 +712,9 @@ to_cache(struct args *args) tmp_unlink(tmp_stderr); tmp_unlink(tmp_obj); + if( tmp_dia != 0 ) { + tmp_unlink(tmp_dia); + } failed(); } @@ -729,6 +757,39 @@ to_cache(struct args *args) } } + if( tmp_dia != 0 ) { + if (stat(tmp_dia, &st) != 0) { + cc_log("Failed to stat %s: %s", tmp_dia, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } + if (st.st_size > 0) { + if (output_to_real_object_first) { + int ret; + if (conf->hard_link && !conf->compression) { + ret = link(tmp_dia, cached_dia); + } else { + ret = copy_file(tmp_dia, cached_dia, conf->compression); + } + if (ret != 0) { + cc_log("Failed to copy/link %s to %s: %s", + tmp_dia, cached_dia, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } + } else if (move_uncompressed_file( tmp_dia, cached_dia, + conf->compression ? conf->compression_level : 0) != 0) { + cc_log("Failed to move %s to %s: %s", tmp_dia, cached_dia, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } + cc_log("Stored in cache: %s", cached_dia); + stat(cached_dia, &st); + added_bytes += file_size(&st); + added_files += 1; + } + } + if (output_to_real_object_first) { int ret; if (conf->hard_link && !conf->compression) { @@ -780,6 +841,7 @@ to_cache(struct args *args) free(tmp_obj); free(tmp_stderr); free(tmp_stdout); + free(tmp_dia); } /* @@ -904,12 +966,12 @@ static void update_cached_result_globals(struct file_hash *hash) { char *object_name; - object_name = format_hash_as_string(hash->hash, hash->size); cached_obj_hash = hash; cached_obj = get_path_in_cache(object_name, ".o"); cached_stderr = get_path_in_cache(object_name, ".stderr"); cached_dep = get_path_in_cache(object_name, ".d"); + cached_dia = get_path_in_cache(object_name, ".dia"); stats_file = format("%s/%c/stats", conf->cache_dir, object_name[0]); free(object_name); } @@ -1211,6 +1273,12 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) return; } + /* Check if the diagnostic file is there. */ + if ((output_dia != 0) && (stat(cached_dia, &st) != 0)) { + cc_log("Diagnostic file %s not in cache", cached_dia); + return; + } + /* * (If mode != FROMCACHE_DIRECT_MODE, the dependency file is created by * gcc.) @@ -1250,6 +1318,7 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) x_unlink(cached_stderr); x_unlink(cached_obj); x_unlink(cached_dep); + x_unlink(cached_dia); return; } else { cc_log("Created %s from %s", output_obj, cached_obj); @@ -1282,12 +1351,52 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) x_unlink(cached_stderr); x_unlink(cached_obj); x_unlink(cached_dep); + x_unlink(cached_dia); return; } else { cc_log("Created %s from %s", output_dep, cached_dep); } } + if ( output_dia != 0 ) { + cc_log("[from_cache]: output_dia: %s", output_dia); + x_unlink(output_dia); + /* only make a hardlink if the cache file is uncompressed */ + if (conf->hard_link && !file_is_compressed(cached_dia)) { + ret = link(cached_dia, output_dia); + } else { + ret = copy_file(cached_dia, output_dia, 0); + } + cc_log("[from_cache]: ret: %d", ret); + + if (ret == -1) { + if (errno == ENOENT) { + /* + * Someone removed the file just before we + * began copying? + */ + cc_log("Diagnostic file %s just disappeared from cache", output_dia); + stats_update(STATS_MISSING); + } else { + cc_log("Failed to copy/link %s to %s: %s", + cached_dia, output_dia, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } + x_unlink(output_obj); + x_unlink(output_dep); + x_unlink(output_dia); + x_unlink(cached_stderr); + x_unlink(cached_obj); + x_unlink(cached_dep); + x_unlink(cached_dia); + return; + } else { + cc_log("Created %s from %s", output_dia, cached_dia); + } + } + + /* Update modification timestamps to save files from LRU cleanup. Also gives files a sensible mtime when hard-linking. */ update_mtime(cached_obj); @@ -1295,6 +1404,9 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) if (produce_dep_file) { update_mtime(cached_dep); } + if(output_dia != 0) { + update_mtime(cached_dia); + } if (generating_dependencies && mode != FROMCACHE_DIRECT_MODE) { /* Store the dependency file in the cache. */ @@ -1716,6 +1828,18 @@ cc_process_args(struct args *args, struct args **preprocessor_args, continue; } + if (str_eq(argv[i], "--serialize-diagnostics")) { + if (i >= argc - 1) { + cc_log("Missing argument to %s", argv[i]); + stats_update(STATS_ARGS); + result = false; + goto out; + } + output_dia = make_relative_path(x_strdup(argv[i+1])); + i++; + continue; + } + if (str_startswith(argv[i], "-fprofile-")) { const char *arg_profile_dir = strchr(argv[i], '='); char *arg = x_strdup(argv[i]); @@ -2232,10 +2356,12 @@ cc_reset(void) free(input_file); input_file = NULL; free(output_obj); output_obj = NULL; free(output_dep); output_dep = NULL; + free(output_dia); output_dia = NULL; free(cached_obj_hash); cached_obj_hash = NULL; free(cached_obj); cached_obj = NULL; free(cached_stderr); cached_stderr = NULL; free(cached_dep); cached_dep = NULL; + free(cached_dia); cached_dia = NULL; free(manifest_path); manifest_path = NULL; time_of_compilation = 0; if (included_files) { @@ -2331,6 +2457,9 @@ ccache(int argc, char *argv[]) if (generating_dependencies) { cc_log("Dependency file: %s", output_dep); } + if (output_dia != 0) { + cc_log("Diagnostic file: %s", output_dia); + } cc_log("Object file: %s", output_obj); hash_start(&common_hash); diff --git a/cleanup.c b/cleanup.c index a33bd2b28..8e5e6cde1 100644 --- a/cleanup.c +++ b/cleanup.c @@ -147,6 +147,7 @@ sort_and_clean(void) ext = get_extension(files[i]->fname); if (str_eq(ext, ".o") || str_eq(ext, ".d") + || str_eq(ext, ".dia") || str_eq(ext, ".stderr") || str_eq(ext, "")) { char *base = remove_extension(files[i]->fname); @@ -160,6 +161,7 @@ sort_and_clean(void) */ delete_sibling_file(base, ".o"); delete_sibling_file(base, ".d"); + delete_sibling_file(base, ".dia"); delete_sibling_file(base, ".stderr"); delete_sibling_file(base, ""); /* Object file from ccache 2.4. */ } diff --git a/compopt.c b/compopt.c index 6f7642517..3a05d0203 100644 --- a/compopt.c +++ b/compopt.c @@ -34,6 +34,7 @@ struct compopt { static const struct compopt compopts[] = { {"--coverage", TOO_HARD}, /* implies -ftest-coverage */ {"--param", TAKES_ARG}, + {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH}, {"-A", TAKES_ARG}, {"-D", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG}, {"-E", TOO_HARD}, diff --git a/test.sh b/test.sh index 64443460e..ed34dbddb 100755 --- a/test.sh +++ b/test.sh @@ -612,6 +612,21 @@ EOF ################################################################## + if [ $COMPILER_TYPE_CLANG -eq 1 ]; then + $CCACHE -Cz > /dev/null + testname="serialize-diagnostics" + $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + checkstat 'files in cache' 2 + $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null + checkstat 'cache hit (preprocessed)' 1 + checkstat 'cache miss' 1 + checkstat 'files in cache' 2 + fi + + ################################################################## + rm -f test1.c } @@ -1518,6 +1533,31 @@ EOF checkstat 'cache miss' 1 cd .. done + + ################################################################## + # Check that clang's --serialize-diagnostics arguments with absolute paths are rewritten + # to relative. + if [ $COMPILER_TYPE_CLANG -eq 1 ]; then + testname="serialize-diagnostics" + $CCACHE -Cz >/dev/null + cd dir1 + CCACHE_BASEDIR=`pwd` $CCACHE $COMPILER -w -MD -MF `pwd`/test.d -I`pwd`/include --serialize-diagnostics `pwd`/test.dia -c src/test.c -o `pwd`/test.o + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + checkstat 'files in cache' 4 + cd .. + + cd dir2 + CCACHE_BASEDIR=`pwd` $CCACHE $COMPILER -w -MD -MF `pwd`/test.d -I`pwd`/include --serialize-diagnostics `pwd`/test.dia -c src/test.c -o `pwd`/test.o + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + checkstat 'files in cache' 4 + cd .. + fi + + } compression_suite() {