From: Joel Rosdahl Date: Mon, 15 Aug 2011 06:26:36 +0000 (+0200) Subject: Merge branch 'master' into config X-Git-Tag: v3.2~178 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e764489d87d66cf2f55c96d0de5c6614ebc2a2e0;p=thirdparty%2Fccache.git Merge branch 'master' into config * master: (22 commits) Add the newest contributors Fix potential free() of non-heap memory Plug minor memory leak Minor code-style cleanup Correct win32 ifndefs Don't crash when getcwd() fails rework profile directory handling set output_to_real_object default to false, we get errors handling hardlinks Using hardlinks if requested comment Make sure we only handle known -fprofile flags. Rewrite profile directory to use absolute paths on commandline to increase direct / preprocessed hit rate. Move -fprofile handling into cc_process_args Look for .gcda files in profile directory when using profile Fix profile_use directory, and valgrind warning refactor to handle profile directories Use hash_delimeter before hashing profile data Avoid output_obj being freed by accident Fix comment style Hash the cwd if we're outputting to our object file first handle -fprofile-use ... Conflicts: ccache.c util.c --- e764489d87d66cf2f55c96d0de5c6614ebc2a2e0 diff --cc ccache.c index ddec7d135,339ce5fe6..e8ddf6c01 --- a/ccache.c +++ b/ccache.c @@@ -665,7 -703,20 +680,20 @@@ to_cache(struct args *args } else { tmp_unlink(tmp_stderr); } - if (move_uncompressed_file(tmp_obj, cached_obj, conf->compression) != 0) { + + if (output_to_real_object_first) { + int ret; - if (getenv("CCACHE_HARDLINK") && !enable_compression) { ++ if (getenv("CCACHE_HARDLINK") && !conf->compression) { + ret = link(tmp_obj, cached_obj); + } else { - ret = copy_file(tmp_obj, cached_obj, enable_compression); ++ ret = copy_file(tmp_obj, cached_obj, conf->compression); + } + if (ret != 0) { + cc_log("Failed to copy/link %s to %s: %s", tmp_obj, cached_obj, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } - } else if (move_uncompressed_file(tmp_obj, cached_obj, enable_compression) != 0) { ++ } else if (move_uncompressed_file(tmp_obj, cached_obj, conf->compression) != 0) { cc_log("Failed to move %s to %s: %s", tmp_obj, cached_obj, strerror(errno)); stats_update(STATS_ERROR); failed(); @@@ -972,8 -1027,54 +999,54 @@@ calculate_object_hash(struct args *args hash_string(hash, args->argv[i]); } + /* + * For profile generation (-fprofile-arcs, -fprofile-generate): + * - hash profile directory + * - output to the real file first + * + * For profile usage (-fprofile-use): + * - hash profile data + * + * -fbranch-probabilities and -fvpt usage is covered by + * -fprofile-generate/-fprofile-use. + * + * The profile directory can be specified as an argument to + * -fprofile-generate=, -fprofile-use=, or -fprofile-dir=. + */ + + /* + * We need to output to the real object first here, otherwise runtime + * artifacts will be produced in the wrong place. + */ + if (profile_generate) { + output_to_real_object_first = true; + if (!profile_dir) { + profile_dir = get_cwd(); + } + cc_log("Adding profile directory %s to our hash", profile_dir); + hash_delimiter(hash, "-fprofile-dir"); + hash_string(hash, profile_dir); + } + if (profile_use) { + /* Calculate gcda name */ + char *gcda_name; + char *base_name; + output_to_real_object_first = true; + base_name = remove_extension(output_obj); + if (!profile_dir) { + profile_dir = get_cwd(); + } + gcda_name = format("%s/%s.gcda", profile_dir, base_name); + cc_log("Adding profile data %s to our hash", gcda_name); + /* Add the gcda to our hash */ + hash_delimiter(hash, "-fprofile-use"); + hash_file(hash, gcda_name); + free(base_name); + free(gcda_name); + } + if (direct_mode) { - if (!(sloppiness & SLOPPY_FILE_MACRO)) { + if (!(conf->sloppiness & SLOPPY_FILE_MACRO)) { /* * The source code file or an include file may contain * __FILE__, so make sure that the hash is unique for @@@ -1883,10 -1933,12 +2008,12 @@@ initialize(void void cc_reset(void) { + conf_free(conf); conf = NULL; + 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(profile_dir); profile_dir = NULL; - free(cache_dir); cache_dir = NULL; - cache_logfile = NULL; - base_dir = NULL; + args_free(orig_args); orig_args = NULL; free(input_file); input_file = NULL; free(output_obj); output_obj = NULL; free(output_dep); output_dep = NULL; diff --cc util.c index 9f266348d,e2f6e2169..2ea31b40b --- a/util.c +++ b/util.c @@@ -100,30 -95,10 +100,31 @@@ path_max(const char *path } #endif } + #endif /* !_WIN32 */ +static void +vlog(const char *format, va_list ap, bool log_updated_time) +{ + if (!init_log()) { + return; + } + + log_prefix(log_updated_time); + vfprintf(logfile, format, ap); + fprintf(logfile, "\n"); +} + /* - * Write a message to the CCACHE_LOGFILE location (adding a newline). + * Write a message to the log file (adding a newline) and flush. + */ +void +cc_vlog(const char *format, va_list ap) +{ + vlog(format, ap, true); +} + +/* + * Write a message to the log file (adding a newline) and flush. */ void cc_log(const char *format, ...) @@@ -867,70 -829,34 +868,71 @@@ format_human_readable_size(uint64_t v return s; } -/* return a value in multiples of 1024 give a string that can end - in K, M or G -*/ -size_t -value_units(const char *s) +/* Format a size as a parsable string. Caller frees. */ +char * +format_parsable_size_with_suffix(uint64_t size) { - char m; - double v = atof(s); - m = s[strlen(s)-1]; - switch (m) { - case 'G': - case 'g': - default: - v *= 1024*1024; - break; - case 'M': - case 'm': - v *= 1024; - break; - case 'K': - case 'k': - v *= 1; - break; - } - return (size_t)v; + char *s; + if (size >= 1000*1000*1000) { + s = format("%.1fG", size / ((double)(1000*1000*1000))); + } else if (size >= 1000*1000) { + s = format("%.1fM", size / ((double)(1000*1000))); + } else if (size >= 1000) { + s = format("%.1fk", size / ((double)(1000))); + } else { + s = format("%u", (unsigned)size); + } + return s; +} + +/* + * Parse a "size value", i.e. a string that can end in k, M, G, T (10-based + * suffixes) or Ki, Mi, Gi, Ti (2-based suffixes). For backward compatibility, + * K is also recognized as a synonym of k. + */ +bool +parse_size_with_suffix(const char *str, uint64_t *size) +{ + char *p; + double x; + + errno = 0; + x = strtod(str, &p); + if (errno != 0 || x < 0 || p == str || *str == '\0') { + return false; + } + + while (isspace(*p)) { + ++p; + } + + if (*p != '\0') { + unsigned multiplier; + if (*(p+1) == 'i') { + multiplier = 1024; + } else { + multiplier = 1000; + } + switch (*p) { + case 'T': + x *= multiplier; + case 'G': + x *= multiplier; + case 'M': + x *= multiplier; + case 'K': + case 'k': + x *= multiplier; + break; + default: + return false; + } + } + *size = x; + return true; } + #ifndef _WIN32 /* a sane realpath() function, trying to cope with stupid path limits and a broken API