]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Make it possible to run failed() and not execute the real compiler
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 22 Feb 2020 16:12:48 +0000 (17:12 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 22 Feb 2020 20:49:36 +0000 (21:49 +0100)
This removes one of the last x_exit calls deeper into the main ccache
code paths.

src/ccache.cpp
src/exceptions.hpp

index f5f0cf0be3f60c312681be23624fb17bd0b1fa34..c937561969ef4471ddacbd725eedba72459568a8 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "third_party/fmt/core.h"
 #include "third_party/minitrace.h"
+#include "third_party/nonstd/optional.hpp"
 
 #ifdef HAVE_GETOPT_LONG
 #  include <getopt.h>
@@ -55,6 +56,8 @@
 #define STRINGIFY(x) #x
 #define TO_STRING(x) STRINGIFY(x)
 
+using nonstd::nullopt;
+using nonstd::optional;
 using nonstd::string_view;
 
 static const char VERSION_TEXT[] = MYNAME
@@ -186,13 +189,16 @@ add_prefix(const Context& ctx, struct args* args, const char* prefix_command)
   args_free(prefix);
 }
 
-static void failed(enum stats stat = STATS_NONE) ATTR_NORETURN;
+// If `exit_code` is set, just exit with that code directly, otherwise execute
+// the real compiler and exit with its exit code. Also updates statistics
+// counter `stat` if it's not STATS_NONE.
+static void failed(enum stats stat = STATS_NONE,
+                   optional<int> exit_code = nullopt) ATTR_NORETURN;
 
-// Something went badly wrong - just execute the real compiler.
 static void
-failed(enum stats stat)
+failed(enum stats stat, optional<int> exit_code)
 {
-  throw Failure(stat);
+  throw Failure(stat, exit_code);
 }
 
 static const char*
@@ -1267,7 +1273,6 @@ to_cache(Context& ctx,
 
   if (status != 0) {
     cc_log("Compiler gave exit status %d", status);
-    stats_update(ctx, STATS_STATUS);
 
     int fd = open(tmp_stderr, O_RDONLY | O_BINARY);
     if (fd != -1) {
@@ -1276,11 +1281,11 @@ to_cache(Context& ctx,
       close(fd);
       tmp_unlink(tmp_stderr);
 
-      x_exit(status);
+      failed(STATS_STATUS, status);
     }
 
     tmp_unlink(tmp_stderr);
-    failed();
+    failed(STATS_STATUS);
   }
 
   if (ctx.config.depend_mode()) {
@@ -3557,11 +3562,11 @@ configuration_printer(const std::string& key,
   fmt::print("({}) {} = {}\n", origin, key, value);
 }
 
-static void cache_compilation(int argc, char* argv[]) ATTR_NORETURN;
+static int cache_compilation(int argc, char* argv[]);
 static void do_cache_compilation(Context& ctx, char* argv[]) ATTR_NORETURN;
 
 // The entry point when invoked to cache a compilation.
-static void
+static int
 cache_compilation(int argc, char* argv[])
 {
 #ifndef _WIN32
@@ -3584,6 +3589,11 @@ cache_compilation(int argc, char* argv[])
       stats_update(ctx, e.stat());
     }
 
+    if (e.exit_code()) {
+      return *e.exit_code();
+    }
+    // Else: Fall back to running the real compiler.
+
     assert(ctx.orig_args);
 
     args_strip(ctx.orig_args, "--ccache-");
@@ -3606,7 +3616,7 @@ do_cache_compilation(Context& ctx, char* argv[])
   if (ctx.actual_cwd.empty()) {
     cc_log("Unable to determine current working directory: %s",
            strerror(errno));
-    throw Failure(STATS_ERROR);
+    failed(STATS_ERROR);
   }
 
   MTR_BEGIN("main", "clean_up_internal_tempdir");
@@ -4039,7 +4049,7 @@ ccache_main(int argc, char* argv[])
       }
     }
 
-    cache_compilation(argc, argv);
+    return cache_compilation(argc, argv);
   } catch (const ErrorBase& e) {
     fmt::print(stderr, "ccache: error: {}\n", e.what());
     return EXIT_FAILURE;
index f9bb78b6ff6e4969d4d838a60efdff96fc504b13..cb7a32e46ad5a301759aff1bd446edf53c8dd7f5 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "stats.hpp"
 
+#include "third_party/nonstd/optional.hpp"
+
 #include <stdexcept>
 
 // Don't throw or catch ErrorBase directly, use a subclass.
@@ -45,21 +47,32 @@ class FatalError : public ErrorBase
   using ErrorBase::ErrorBase;
 };
 
-// Throw a Failure to make ccache fall back to running the real compiler. Also
-// updates statistics counter `stat` if it's not STATS_NONE.
+// Throw a Failure if ccache did not succeed in getting or putting a result in
+// the cache. If `exit_code` is set, just exit with that code directly,
+// otherwise execute the real compiler and exit with its exit code. Also updates
+// statistics counter `stat` if it's not STATS_NONE.
 class Failure : public std::exception
 {
 public:
-  Failure(enum stats stat = STATS_NONE);
+  Failure(enum stats stat, nonstd::optional<int> exit_code);
 
+  nonstd::optional<int> exit_code() const;
   enum stats stat() const;
 
 private:
   enum stats m_stat;
+  nonstd::optional<int> m_exit_code;
 };
 
-inline Failure::Failure(enum stats stat) : m_stat(stat)
+inline Failure::Failure(enum stats stat, nonstd::optional<int> exit_code)
+  : m_stat(stat), m_exit_code(exit_code)
+{
+}
+
+inline nonstd::optional<int>
+Failure::exit_code() const
 {
+  return m_exit_code;
 }
 
 inline enum stats