X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ccache.c;h=f72a9bda2fa35e9793b1a608208be1bdb50ba9af;hb=e70429725122fbca9e7113996e852da2369d7181;hp=de2b1e3d53670762b206dd2eb8c3b2b2478716f7;hpb=a7be860f52a56c78f554a67df380bda4990d5bab;p=platform%2Fupstream%2Fccache.git diff --git a/ccache.c b/ccache.c index de2b1e3..f72a9bd 100644 --- a/ccache.c +++ b/ccache.c @@ -1,7 +1,7 @@ // ccache -- a fast C/C++ compiler cache // // Copyright (C) 2002-2007 Andrew Tridgell -// Copyright (C) 2009-2017 Joel Rosdahl +// Copyright (C) 2009-2018 Joel Rosdahl // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free @@ -37,7 +37,7 @@ static const char VERSION_TEXT[] = MYNAME " version %s\n" "\n" "Copyright (C) 2002-2007 Andrew Tridgell\n" - "Copyright (C) 2009-2017 Joel Rosdahl\n" + "Copyright (C) 2009-2018 Joel Rosdahl\n" "\n" "This program is free software; you can redistribute it and/or modify it under\n" "the terms of the GNU General Public License as published by the Free Software\n" @@ -172,7 +172,10 @@ static bool generating_dependencies; static bool generating_coverage; // Relocating debuginfo in the format old=new. -static char *debug_prefix_map = NULL; +static char **debug_prefix_maps = NULL; + +// Size of debug_prefix_maps list. +static size_t debug_prefix_maps_len = 0; // Is the compiler being asked to output coverage data (.gcda) at runtime? static bool profile_arcs; @@ -194,7 +197,7 @@ static char *cpp_stderr; char *stats_file = NULL; // Whether the output is a precompiled header. -static bool output_is_precompiled_header = false; +bool output_is_precompiled_header = false; // Profile generation / usage information. static char *profile_dir = NULL; @@ -557,12 +560,16 @@ remember_include_file(char *path, struct mdfour *cpp_hash, bool system) } } + // The comparison using >= is intentional, due to a possible race between + // starting compilation and writing the include file. See also the notes + // under "Performance" in MANUAL.txt. if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_MTIME) && st.st_mtime >= time_of_compilation) { cc_log("Include file %s too new", path); goto failure; } + // The same >= logic as above applies to the change time of the file. if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_CTIME) && st.st_ctime >= time_of_compilation) { cc_log("Include file %s ctime too new", path); @@ -1548,8 +1555,8 @@ calculate_common_hash(struct args *args, struct mdfour *hash) // Possibly hash the current working directory. if (generating_debuginfo && conf->hash_dir) { char *cwd = gnu_getcwd(); - if (debug_prefix_map) { - char *map = debug_prefix_map; + for (size_t i = 0; i < debug_prefix_maps_len; i++) { + char *map = debug_prefix_maps[i]; char *sep = strchr(map, '='); if (sep) { char *old = x_strndup(map, sep - map); @@ -1632,19 +1639,23 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) hash_int(hash, MANIFEST_VERSION); } + // clang will emit warnings for unused linker flags, so we shouldn't skip + // those arguments. + int is_clang = compiler_is_clang(args); + // First the arguments. for (int i = 1; i < args->argc; i++) { - // -L doesn't affect compilation. - if (i < args->argc-1 && str_eq(args->argv[i], "-L")) { + // -L doesn't affect compilation (except for clang). + if (i < args->argc-1 && str_eq(args->argv[i], "-L") && !is_clang) { i++; continue; } - if (str_startswith(args->argv[i], "-L")) { + if (str_startswith(args->argv[i], "-L") && !is_clang) { continue; } - // -Wl,... doesn't affect compilation. - if (str_startswith(args->argv[i], "-Wl,")) { + // -Wl,... doesn't affect compilation (except for clang). + if (str_startswith(args->argv[i], "-Wl,") && !is_clang) { continue; } @@ -1662,7 +1673,9 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) if (!direct_mode && !output_is_precompiled_header && !using_precompiled_header) { if (compopt_affects_cpp(args->argv[i])) { - i++; + if (compopt_takes_arg(args->argv[i])) { + i++; + } continue; } if (compopt_short(compopt_affects_cpp, args->argv[i])) { @@ -1863,15 +1876,19 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) return; } - struct stat st; - if (stat(cached_obj, &st) != 0) { - cc_log("Object file %s not in cache", cached_obj); + // We can't trust the objects based on running the preprocessor + // when the output is precompiled headers, as the hash does not + // include the mtime of each included header, breaking compilation + // with clang when the precompiled header is used after touching + // one of the included files. + if (output_is_precompiled_header && mode == FROMCACHE_CPP_MODE) { + cc_log("Not using preprocessed cached object for precompiled header"); return; } - // Check if the diagnostic file is there. - if (output_dia && stat(cached_dia, &st) != 0) { - cc_log("Diagnostic file %s not in cache", cached_dia); + struct stat st; + if (stat(cached_obj, &st) != 0) { + cc_log("Object file %s not in cache", cached_obj); return; } @@ -1910,6 +1927,12 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) return; } + // Check if the diagnostic file is there. + if (output_dia && stat(cached_dia, &st) != 0) { + cc_log("Diagnostic file %s not in cache", cached_dia); + return; + } + // Copy object file from cache. Do so also for FissionDwarf file, cached_dwo, // when -gsplit-dwarf is specified. if (!str_eq(output_obj, "/dev/null")) { @@ -1947,11 +1970,6 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) update_mtime(cached_dwo); } - if (generating_dependencies && mode == FROMCACHE_CPP_MODE - && !conf->read_only && !conf->read_only_direct) { - put_file_in_cache(output_dep, cached_dep); - } - send_cached_stderr(); if (put_object_in_manifest) { @@ -2110,8 +2128,6 @@ cc_process_args(struct args *args, struct args **preprocessor_args, struct args *dep_args = args_init(0, NULL); bool found_color_diagnostics = false; - int debug_level = 0; - const char *debug_argument = NULL; int argc = expanded_args->argc; char **argv = expanded_args->argv; @@ -2162,8 +2178,8 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // Handle cuda "-optf" and "--options-file" argument. if (str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file")) { - if (i > argc) { - cc_log("Expected argument after -optf/--options-file"); + if (i == argc - 1) { + cc_log("Expected argument after %s", argv[i]); stats_update(STATS_ARGS); result = false; goto out; @@ -2264,7 +2280,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // Special handling for -x: remember the last specified language before the // input file and strip all -x options from the arguments. if (str_eq(argv[i], "-x")) { - if (i == argc-1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2285,7 +2301,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // We need to work out where the output was meant to go. if (str_eq(argv[i], "-o")) { - if (i == argc-1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2309,7 +2325,10 @@ cc_process_args(struct args *args, struct args **preprocessor_args, continue; } if (str_startswith(argv[i], "-fdebug-prefix-map=")) { - debug_prefix_map = x_strdup(argv[i] + 19); + debug_prefix_maps = x_realloc( + debug_prefix_maps, + (debug_prefix_maps_len + 1) * sizeof(char *)); + debug_prefix_maps[debug_prefix_maps_len++] = x_strdup(argv[i] + 19); args_add(stripped_args, argv[i]); continue; } @@ -2317,32 +2336,17 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // Debugging is handled specially, so that we know if we can strip line // number info. if (str_startswith(argv[i], "-g")) { - const char *pLevel = argv[i] + 2; - if (str_startswith(argv[i], "-ggdb")) { - pLevel = argv[i] + 5; - } else if (str_startswith(argv[i], "-gstabs")) { - pLevel = argv[i] + 7; - } else if (str_startswith(argv[i], "-gcoff")) { - pLevel = argv[i] + 6; - } else if (str_startswith(argv[i], "-gxcoff")) { - pLevel = argv[i] + 7; - } else if (str_startswith(argv[i], "-gvms")) { - pLevel = argv[i] + 5; - } - - // Deduce level from argument, default is 2. - int foundlevel = -1; - if (pLevel[0] == '\0') { - foundlevel = 2; - } else if (pLevel[0] >= '0' && pLevel[0] <= '9') { - foundlevel = atoi(pLevel); - } - - if (foundlevel >= 0) { - debug_level = foundlevel; - debug_argument = argv[i]; - continue; + generating_debuginfo = true; + args_add(stripped_args, argv[i]); + if (conf->unify && !str_eq(argv[i], "-g0")) { + cc_log("%s used; disabling unify mode", argv[i]); + conf->unify = false; } + if (str_eq(argv[i], "-g3")) { + cc_log("%s used; not compiling preprocessed code", argv[i]); + conf->run_second_cpp = true; + } + continue; } // These options require special handling, because they behave differently @@ -2360,7 +2364,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, bool separate_argument = (strlen(argv[i]) == 3); if (separate_argument) { // -MF arg - if (i >= argc - 1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2390,7 +2394,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, char *relpath; if (strlen(argv[i]) == 3) { // -MQ arg or -MT arg - if (i >= argc - 1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2507,7 +2511,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, } if (str_eq(argv[i], "--serialize-diagnostics")) { - if (i >= argc - 1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2597,7 +2601,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // to get better hit rate. A secondary effect is that paths in the standard // error output produced by the compiler will be normalized. if (compopt_takes_path(argv[i])) { - if (i == argc-1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2649,7 +2653,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, // Options that take an argument. if (compopt_takes_arg(argv[i])) { - if (i == argc-1) { + if (i == argc - 1) { cc_log("Missing argument to %s", argv[i]); stats_update(STATS_ARGS); result = false; @@ -2726,19 +2730,6 @@ cc_process_args(struct args *args, struct args **preprocessor_args, } } // for - if (debug_level > 0) { - generating_debuginfo = true; - args_add(stripped_args, debug_argument); - if (conf->unify) { - cc_log("%s used; disabling unify mode", debug_argument); - conf->unify = false; - } - if (debug_level >= 3 && !conf->run_second_cpp) { - cc_log("%s used; not compiling preprocessed code", debug_argument); - conf->run_second_cpp = true; - } - } - if (found_S_opt) { // Even if -gsplit-dwarf is given, the .dwo file is not generated when -S // is also given. @@ -3092,7 +3083,12 @@ cc_reset(void) free(primary_config_path); primary_config_path = NULL; free(secondary_config_path); secondary_config_path = NULL; free(current_working_dir); current_working_dir = NULL; - free(debug_prefix_map); debug_prefix_map = NULL; + for (size_t i = 0; i < debug_prefix_maps_len; i++) { + free(debug_prefix_maps[i]); + debug_prefix_maps[i] = NULL; + } + free(debug_prefix_maps); debug_prefix_maps = NULL; + debug_prefix_maps_len = 0; free(profile_dir); profile_dir = NULL; free(included_pch_file); included_pch_file = NULL; args_free(orig_args); orig_args = NULL; @@ -3142,6 +3138,7 @@ static void setup_uncached_err(void) { int uncached_fd = dup(2); + set_cloexec_flag(uncached_fd); if (uncached_fd == -1) { cc_log("dup(2) failed: %s", strerror(errno)); failed(); @@ -3352,7 +3349,7 @@ ccache_main_options(int argc, char *argv[]) case 'c': // --cleanup initialize(); - cleanup_all(conf); + clean_up_all(conf); printf("Cleaned cache\n"); break;