non_third_party_headers_without_cpp = \
src/Checksum.hpp \
- src/Error.hpp \
src/File.hpp \
src/FormatNonstdStringView.hpp \
src/NonCopyable.hpp \
src/Stat.hpp \
src/StdMakeUnique.hpp \
src/ThreadPool.hpp \
+ src/exceptions.hpp \
src/macroskip.hpp \
src/system.hpp \
unittest/framework.hpp \
#include "AtomicFile.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "Util.hpp"
#include "third_party/fmt/core.h"
#include "CacheEntryReader.hpp"
#include "Compressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "third_party/fmt/core.h"
#include "system.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "Stat.hpp"
#include "third_party/fmt/core.h"
#include "Compression.hpp"
#include "Config.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
namespace Compression {
#include "Config.hpp"
#include "AtomicFile.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "Util.hpp"
#include "ccache.hpp"
+++ /dev/null
-// Copyright (C) 2019 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// 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
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#pragma once
-
-#include "system.hpp"
-
-#include <stdexcept>
-
-class Error : public std::runtime_error
-{
- using std::runtime_error::runtime_error;
-};
#include "NullCompressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
NullCompressor::NullCompressor(FILE* stream) : m_stream(stream)
{
#include "NullDecompressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
NullDecompressor::NullDecompressor(FILE* stream) : m_stream(stream)
{
#include "system.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include <string>
#include "ZstdCompressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "logging.hpp"
const uint8_t k_default_zstd_compression_level = -1;
#include "ZstdDecompressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
ZstdDecompressor::ZstdDecompressor(FILE* stream)
: m_stream(stream),
#include "ccache.hpp"
#include "ArgsInfo.hpp"
-#include "Error.hpp"
#include "FormatNonstdStringView.hpp"
#include "ProgressBar.hpp"
#include "ScopeGuard.hpp"
#include "cleanup.hpp"
#include "compopt.hpp"
#include "compress.hpp"
+#include "exceptions.hpp"
#include "execute.hpp"
#include "exitfn.hpp"
#include "hash.hpp"
args_free(prefix);
}
-static void failed(void) ATTR_NORETURN;
+static void failed(enum stats stat = STATS_NONE) ATTR_NORETURN;
// Something went badly wrong - just execute the real compiler.
static void
-failed(void)
+failed(enum stats stat)
{
- assert(orig_args);
-
- args_strip(orig_args, "--ccache-");
- add_prefix(orig_args, g_config.prefix_command().c_str());
-
- cc_log("Failed; falling back to running the real compiler");
- cc_log_argv("Executing ", orig_args->argv);
- exitfn_call();
- execv(orig_args->argv[0], orig_args->argv);
- fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
+ throw Failure(stat);
}
static const char*
fmt::print("({}) {} = {}\n", origin, key, value);
}
-static void ccache(int argc, char* argv[]) ATTR_NORETURN;
+static void cache_compilation(int argc, char* argv[]) ATTR_NORETURN;
+static void do_cache_compilation(char* argv[]) ATTR_NORETURN;
-// The main ccache driver function.
+// The entry point when invoked to cache a compilation.
static void
-ccache(int argc, char* argv[])
+cache_compilation(int argc, char* argv[])
{
#ifndef _WIN32
set_up_signal_handlers();
orig_args = args_init(argc, argv);
initialize();
+
MTR_BEGIN("main", "find_compiler");
find_compiler(argv);
MTR_END("main", "find_compiler");
+ try {
+ do_cache_compilation(argv);
+ } catch (const Failure& e) {
+ if (e.stat() != STATS_NONE) {
+ stats_update(e.stat());
+ }
+
+ assert(orig_args);
+
+ args_strip(orig_args, "--ccache-");
+ add_prefix(orig_args, g_config.prefix_command().c_str());
+
+ cc_log("Failed; falling back to running the real compiler");
+ cc_log_argv("Executing ", orig_args->argv);
+ exitfn_call();
+ execv(orig_args->argv[0], orig_args->argv);
+ fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
+ }
+}
+
+static void
+do_cache_compilation(char* argv[])
+{
MTR_BEGIN("main", "clean_up_internal_tempdir");
if (g_config.temporary_dir().empty()) {
clean_up_internal_tempdir();
// The main program when not doing a compile.
static int
-ccache_main_options(int argc, char* argv[])
+handle_main_options(int argc, char* argv[])
{
enum longopts {
DUMP_MANIFEST,
// If the first argument isn't an option, then assume we are being passed
// a compiler name and options.
if (argv[1][0] == '-') {
- return ccache_main_options(argc, argv);
+ return handle_main_options(argc, argv);
}
}
- ccache(argc, argv);
- } catch (const Error& e) {
- fmt::print("ccache: error: {}\n", e.what());
- return 1;
+ cache_compilation(argc, argv);
+ } catch (const ErrorBase& e) {
+ fmt::print(stderr, "ccache: error: {}\n", e.what());
+ return EXIT_FAILURE;
}
}
--- /dev/null
+// Copyright (C) 2019-2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// 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
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include "system.hpp"
+
+#include "stats.hpp"
+
+#include <stdexcept>
+
+// Don't throw or catch ErrorBase directly, use a subclass.
+class ErrorBase : public std::runtime_error
+{
+ using std::runtime_error::runtime_error;
+};
+
+// Throw an Error to indicate a potentially non-fatal error that may be caught
+// and handled by callers. An uncaught Error that reaches the top level will be
+// treated similar to FatalError.
+class Error : public ErrorBase
+{
+ using ErrorBase::ErrorBase;
+};
+
+// Throw a FatalError to make ccache print the error message to stderr and exit
+// with a non-zero exit code.
+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.
+class Failure : public std::exception
+{
+public:
+ Failure(enum stats stat = STATS_NONE);
+
+ enum stats stat() const;
+
+private:
+ enum stats m_stat;
+};
+
+inline Failure::Failure(enum stats stat) : m_stat(stat)
+{
+}
+
+inline enum stats
+Failure::stat() const
+{
+ return m_stat;
+}
#include "legacy_util.hpp"
-#include "Error.hpp"
#include "Util.hpp"
+#include "exceptions.hpp"
#include "logging.hpp"
#include "third_party/fmt/core.h"
vsnprintf(msg, sizeof(msg), format, ap);
va_end(ap);
- cc_log("FATAL: %s", msg);
- fprintf(stderr, "ccache: error: %s\n", msg);
-
- x_exit(1);
+ throw FatalError(msg);
}
// Copy all data from fd_in to fd_out.
#include <string>
+void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
+
bool copy_fd(int fd_in, int fd_out);
bool clone_file(const char* src, const char* dest, bool via_tmp_file);
bool copy_file(const char* src, const char* dest, bool via_tmp_file);
#include "logging.hpp"
#include "Config.hpp"
+#include "exceptions.hpp"
#include "execute.hpp"
#ifdef HAVE_SYSLOG_H
void cc_bulklog(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
void cc_log_argv(const char* prefix, char** argv);
void cc_dump_debug_log_buffer(const char* path);
-void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
#include "CacheEntryReader.hpp"
#include "CacheEntryWriter.hpp"
#include "Config.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
#include "File.hpp"
#include "Stat.hpp"
#include "Util.hpp"
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "../src/Config.hpp"
-#include "../src/Error.hpp"
+#include "../src/exceptions.hpp"
#include "../src/Util.hpp"
#include "../src/ccache.hpp"