]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add debug_dir setting for specifying a directory for debug files
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 4 Jan 2021 13:30:32 +0000 (14:30 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 6 Jan 2021 18:32:50 +0000 (19:32 +0100)
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.

doc/MANUAL.adoc
src/Config.cpp
src/Config.hpp
src/ccache.cpp
unittest/test_Config.cpp

index 062f041c55b07183228217de15eeba6e8e5c311f..1862985617b69cd7083b330e1dc27e73a9d52f5d 100644 (file)
@@ -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 _<<config_debug,debug
+    mode>>_ 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 <<config_debug_dir,*config_dir*>> (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.
index a2e09ca1ebc5f0dcd786f347528326b1170b549b..4866294c798d40201f312fda5076d097b5833449 100644 (file)
@@ -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<std::string, ConfigItem> 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<std::string, std::string> 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;
index 1d8a8e85e5e9e3f7e11bbe011e99184c10b18935..95a1b68a8395b034c179abb272b7fd6b99fa8bcf 100644 (file)
@@ -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
 {
index 11d6164498adec7d511df0336b32d8a0125904aa..d18ba0f91616556ee360f7646b5dc83dcf201040 100644 (file)
@@ -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(
index 3661c692d569de36ff26536e7e88f3d770c6fa1d..46e56a33b601c1f6a0ec05b5602955a5dcd6cd5e 100644 (file)
@@ -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",