From: Joel Rosdahl Date: Mon, 4 Jan 2021 13:30:32 +0000 (+0100) Subject: Add debug_dir setting for specifying a directory for debug files X-Git-Tag: v4.2~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a181d44d19e6cd35d186eb5c61cd183fcfb3f9e5;p=thirdparty%2Fccache.git Add debug_dir setting for specifying a directory for debug files This makes it possible to store debug files outside a transient build directory. As a bonus, it also allows for getting debug files when the object file is /dev/null. --- diff --git a/doc/MANUAL.adoc b/doc/MANUAL.adoc index 062f041c5..186298561 100644 --- a/doc/MANUAL.adoc +++ b/doc/MANUAL.adoc @@ -550,6 +550,19 @@ See the http://zstd.net[Zstandard documentation] for more information. _<<_cache_debugging,Cache debugging>>_ for more information. The default is false. +[[config_debug_dir]] *debug_dir* (*CCACHE_DEBUGDIR*):: + + Specifies where to write per-object debug files if the _<>_ is enabled. If set to the empty string, the files will be written + next to the object file. If set to a directory, the debug files will be + written with full absolute paths in that directory, creating it if needed. + The default is the empty string. + + For example, if *debug_dir* is set to `/example`, the current working + directory is `/home/user` and the object file is `build/output.o` then the + debug log will be written to `/example/home/user/build/output.o.ccache-log`. + See also _<<_cache_debugging,Cache debugging>>_. + [[config_depend_mode]] *depend_mode* (*CCACHE_DEPEND* or *CCACHE_NODEPEND*, see _<<_boolean_values,Boolean values>>_ above):: If true, the depend mode will be used. The default is false. See @@ -1243,6 +1256,10 @@ Log for this object file. |============================================================================== +If <> (environment variable *CCACHE_DEBUGDIR*) is +set, the files above will be written to that directory with full absolute paths +instead of next to the object file. + In the direct mode, ccache uses the 160 bit BLAKE3 hash of the *ccache-input-c* + *ccache-input-d* data (where *+* means concatenation), while the *ccache-input-c* + *ccache-input-p* data is used in the preprocessor mode. diff --git a/src/Config.cpp b/src/Config.cpp index a2e09ca1e..4866294c7 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2020 Joel Rosdahl and other contributors +// Copyright (C) 2019-2021 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -52,6 +52,7 @@ enum class ConfigItem { compression_level, cpp_extension, debug, + debug_dir, depend_mode, direct_mode, disable, @@ -92,6 +93,7 @@ const std::unordered_map k_config_key_table = { {"compression_level", ConfigItem::compression_level}, {"cpp_extension", ConfigItem::cpp_extension}, {"debug", ConfigItem::debug}, + {"debug_dir", ConfigItem::debug_dir}, {"depend_mode", ConfigItem::depend_mode}, {"direct_mode", ConfigItem::direct_mode}, {"disable", ConfigItem::disable}, @@ -133,6 +135,7 @@ const std::unordered_map k_env_variable_table = { {"COMPRESSLEVEL", "compression_level"}, {"CPP2", "run_second_cpp"}, {"DEBUG", "debug"}, + {"DEBUGDIR", "debug_dir"}, {"DEPEND", "depend_mode"}, {"DIR", "cache_dir"}, {"DIRECT", "direct_mode"}, @@ -546,6 +549,9 @@ Config::get_string_value(const std::string& key) const case ConfigItem::debug: return format_bool(m_debug); + case ConfigItem::debug_dir: + return m_debug_dir; + case ConfigItem::depend_mode: return format_bool(m_depend_mode); @@ -756,6 +762,10 @@ Config::set_item(const std::string& key, m_debug = parse_bool(value, env_var_key, negate); break; + case ConfigItem::debug_dir: + m_debug_dir = value; + break; + case ConfigItem::depend_mode: m_depend_mode = parse_bool(value, env_var_key, negate); break; diff --git a/src/Config.hpp b/src/Config.hpp index 1d8a8e85e..95a1b68a8 100644 --- a/src/Config.hpp +++ b/src/Config.hpp @@ -51,6 +51,7 @@ public: int8_t compression_level() const; const std::string& cpp_extension() const; bool debug() const; + const std::string& debug_dir() const; bool depend_mode() const; bool direct_mode() const; bool disable() const; @@ -142,6 +143,7 @@ private: int8_t m_compression_level = 0; // Use default level std::string m_cpp_extension; bool m_debug = false; + std::string m_debug_dir; bool m_depend_mode = false; bool m_direct_mode = true; bool m_disable = false; @@ -243,6 +245,12 @@ Config::debug() const return m_debug; } +inline const std::string& +Config::debug_dir() const +{ + return m_debug_dir; +} + inline bool Config::depend_mode() const { diff --git a/src/ccache.cpp b/src/ccache.cpp index 11d616449..d18ba0f91 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2002-2007 Andrew Tridgell -// Copyright (C) 2009-2020 Joel Rosdahl and other contributors +// Copyright (C) 2009-2021 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -232,10 +232,25 @@ clean_up_internal_tempdir(const Config& config) }); } +static std::string +prepare_debug_path(const std::string& debug_dir, + const std::string& output_obj, + string_view suffix) +{ + const std::string prefix = + debug_dir.empty() ? output_obj : debug_dir + Util::real_path(output_obj); + try { + Util::ensure_dir_exists(Util::dir_name(prefix)); + } catch (Error&) { + // Ignore since we can't handle an error in another way in this context. The + // caller takes care of logging when trying to open the path for writing. + } + return FMT("{}.ccache-{}", prefix, suffix); +} + static void init_hash_debug(Context& ctx, Hash& hash, - string_view obj_path, char type, string_view section_name, FILE* debug_text_file) @@ -244,7 +259,8 @@ init_hash_debug(Context& ctx, return; } - std::string path = FMT("{}.ccache-input-{}", obj_path, type); + const auto path = prepare_debug_path( + ctx.config.debug_dir(), ctx.args_info.output_obj, FMT("input-{}", type)); File debug_binary_file(path, "wb"); if (debug_binary_file) { hash.enable_debug(section_name, debug_binary_file.get(), debug_text_file); @@ -2172,8 +2188,8 @@ finalize_at_exit(Context& ctx) // Dump log buffer last to not lose any logs. if (ctx.config.debug() && !ctx.args_info.output_obj.empty()) { - const auto path = FMT("{}.ccache-log", ctx.args_info.output_obj); - Logging::dump_log(path); + Logging::dump_log(prepare_debug_path( + ctx.config.debug_dir(), ctx.args_info.output_obj, "log")); } } @@ -2321,7 +2337,8 @@ do_cache_compilation(Context& ctx, const char* const* argv) MTR_META_THREAD_NAME(ctx.args_info.output_obj.c_str()); if (ctx.config.debug()) { - std::string path = FMT("{}.ccache-input-text", ctx.args_info.output_obj); + const auto path = prepare_debug_path( + ctx.config.debug_dir(), ctx.args_info.output_obj, "input-text"); File debug_text_file(path, "w"); if (debug_text_file) { ctx.hash_debug_files.push_back(std::move(debug_text_file)); @@ -2335,8 +2352,7 @@ do_cache_compilation(Context& ctx, const char* const* argv) : nullptr; Hash common_hash; - init_hash_debug( - ctx, common_hash, ctx.args_info.output_obj, 'c', "COMMON", debug_text_file); + init_hash_debug(ctx, common_hash, 'c', "COMMON", debug_text_file); MTR_BEGIN("hash", "common_hash"); hash_common_info( @@ -2345,12 +2361,7 @@ do_cache_compilation(Context& ctx, const char* const* argv) // Try to find the hash using the manifest. Hash direct_hash = common_hash; - init_hash_debug(ctx, - direct_hash, - ctx.args_info.output_obj, - 'd', - "DIRECT MODE", - debug_text_file); + init_hash_debug(ctx, direct_hash, 'd', "DIRECT MODE", debug_text_file); Args args_to_hash = processed.preprocessor_args; args_to_hash.push_back(processed.extra_args_to_hash); @@ -2394,12 +2405,7 @@ do_cache_compilation(Context& ctx, const char* const* argv) // Find the hash using the preprocessed output. Also updates // ctx.included_files. Hash cpp_hash = common_hash; - init_hash_debug(ctx, - cpp_hash, - ctx.args_info.output_obj, - 'p', - "PREPROCESSOR MODE", - debug_text_file); + init_hash_debug(ctx, cpp_hash, 'p', "PREPROCESSOR MODE", debug_text_file); MTR_BEGIN("hash", "cpp_hash"); result_name = calculate_result_name( diff --git a/unittest/test_Config.cpp b/unittest/test_Config.cpp index 3661c692d..46e56a33b 100644 --- a/unittest/test_Config.cpp +++ b/unittest/test_Config.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2020 Joel Rosdahl and other contributors +// Copyright (C) 2011-2021 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -48,6 +48,7 @@ TEST_CASE("Config: default values") CHECK(config.compression_level() == 0); CHECK(config.cpp_extension().empty()); CHECK(!config.debug()); + CHECK(config.debug_dir().empty()); CHECK(!config.depend_mode()); CHECK(config.direct_mode()); CHECK(!config.disable()); @@ -375,6 +376,7 @@ TEST_CASE("Config::visit_items") "compression_level = 8\n" "cpp_extension = ce\n" "debug = false\n" + "debug_dir = /dd\n" "depend_mode = true\n" "direct_mode = false\n" "disable = true\n" @@ -431,6 +433,7 @@ TEST_CASE("Config::visit_items") "(test.conf) compression_level = 8", "(test.conf) cpp_extension = ce", "(test.conf) debug = false", + "(test.conf) debug_dir = /dd", "(test.conf) depend_mode = true", "(test.conf) direct_mode = false", "(test.conf) disable = true",