From 4a0f8035045408d3e5ce202be7874258d5ca87a2 Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Thu, 27 Feb 2025 18:09:01 -0800 Subject: [PATCH] deps, Diag: add spdlog, new file from Logger (#1144) --- .github/actions/setup-macos-deps/action.yml | 1 + .github/actions/setup-ubuntu-deps/action.yml | 1 + Dockerfile | 16 +- Makefile | 10 +- cabin.toml | 1 + src/Algos.cc | 6 +- src/BuildConfig.cc | 23 +- src/Cabin.cc | 27 +- src/Cli.cc | 8 +- src/Cmd/Add.cc | 8 +- src/Cmd/Build.cc | 8 +- src/Cmd/Clean.cc | 4 +- src/Cmd/Fmt.cc | 13 +- src/Cmd/Init.cc | 4 +- src/Cmd/Lint.cc | 11 +- src/Cmd/New.cc | 9 +- src/Cmd/Remove.cc | 8 +- src/Cmd/Run.cc | 4 +- src/Cmd/Search.cc | 6 +- src/Cmd/Test.cc | 14 +- src/Cmd/Tidy.cc | 8 +- src/Cmd/Version.cc | 2 +- src/Dependency.cc | 9 +- src/Diag.hpp | 171 +++++++++++++ src/Logger.hpp | 256 ------------------- src/Manifest.cc | 6 +- src/Parallelism.cc | 4 +- src/TermColor.cc | 4 +- 28 files changed, 297 insertions(+), 345 deletions(-) create mode 100644 src/Diag.hpp delete mode 100644 src/Logger.hpp diff --git a/.github/actions/setup-macos-deps/action.yml b/.github/actions/setup-macos-deps/action.yml index 009c8c893..51a6a2098 100644 --- a/.github/actions/setup-macos-deps/action.yml +++ b/.github/actions/setup-macos-deps/action.yml @@ -9,6 +9,7 @@ runs: brew install \ curl \ fmt \ + spdlog \ libgit2 \ nlohmann-json \ tbb diff --git a/.github/actions/setup-ubuntu-deps/action.yml b/.github/actions/setup-ubuntu-deps/action.yml index f1d2bc5aa..31ccd5966 100644 --- a/.github/actions/setup-ubuntu-deps/action.yml +++ b/.github/actions/setup-ubuntu-deps/action.yml @@ -10,6 +10,7 @@ runs: sudo apt-get install -y \ libcurl4-openssl-dev \ libfmt-dev \ + libspdlog-dev \ libgit2-dev \ nlohmann-json3-dev \ libtbb-dev diff --git a/Dockerfile b/Dockerfile index a1f1fd7e1..c1ac1fc75 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,9 +3,11 @@ ARG base=ubuntu:24.04 FROM $base AS builder -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential ca-certificates git pkg-config libfmt-dev libgit2-dev libcurl4-openssl-dev nlohmann-json3-dev libtbb-dev \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential ca-certificates git pkg-config \ + libfmt-dev libspdlog-dev libgit2-dev libcurl4-openssl-dev nlohmann-json3-dev libtbb-dev \ + && rm -rf /var/lib/apt/lists/* WORKDIR /app @@ -21,9 +23,11 @@ RUN make RELEASE=1 install FROM $base -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential clang libfmt-dev libgit2-dev libcurl4-openssl-dev nlohmann-json3-dev libtbb-dev \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential clang \ + libfmt-dev libspdlog-dev libgit2-dev libcurl4-openssl-dev nlohmann-json3-dev libtbb-dev \ + && rm -rf /var/lib/apt/lists/* COPY --from=builder /usr/local/bin/cabin /usr/local/bin/cabin diff --git a/Makefile b/Makefile index 7256ce33d..dda90b2e7 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,8 @@ LIBGIT2_VERREQ := libgit2 >= 1.7.0, libgit2 < 1.10.0 LIBCURL_VERREQ := libcurl >= 7.79.1, libcurl < 9.0.0 NLOHMANN_JSON_VERREQ := nlohmann_json >= 3.10.5, nlohmann_json < 4.0.0 TBB_VERREQ := tbb >= 2021.5.0, tbb < 2023.0.0 -FMT_VERREQ := fmt >= 9, fmt < 12.0.0 +FMT_VERREQ := fmt >= 9.0.0, fmt < 12.0.0 +SPDLOG_VERREQ := spdlog >= 1.8.0, spdlog < 2.0.0 TOML11_VER := $(shell grep -m1 toml11 cabin.toml | sed 's/.*rev = \(.*\)}/\1/' | tr -d '"') RESULT_VER := $(shell grep -m1 cpp-result cabin.toml | sed 's/.*tag = \(.*\)}/\1/' | tr -d '"') @@ -40,11 +41,13 @@ INCLUDES := -isystem $(O)/DEPS/toml11/include \ $(shell pkg-config --cflags '$(LIBCURL_VERREQ)') \ $(shell pkg-config --cflags '$(NLOHMANN_JSON_VERREQ)') \ $(shell pkg-config --cflags '$(TBB_VERREQ)') \ - $(shell pkg-config --cflags '$(FMT_VERREQ)') + $(shell pkg-config --cflags '$(FMT_VERREQ)') \ + $(shell pkg-config --cflags '$(SPDLOG_VERREQ)') LIBS := $(shell pkg-config --libs '$(LIBGIT2_VERREQ)') \ $(shell pkg-config --libs '$(LIBCURL_VERREQ)') \ $(shell pkg-config --libs '$(TBB_VERREQ)') \ - $(shell pkg-config --libs '$(FMT_VERREQ)') + $(shell pkg-config --libs '$(FMT_VERREQ)') \ + $(shell pkg-config --libs '$(SPDLOG_VERREQ)') SRCS := $(shell find src -name '*.cc') OBJS := $(patsubst src/%,$(O)/%,$(SRCS:.cc=.o)) @@ -71,6 +74,7 @@ check_deps: @pkg-config '$(NLOHMANN_JSON_VERREQ)' || (echo "Error: $(NLOHMANN_JSON_VERREQ) not found" && exit 1) @pkg-config '$(TBB_VERREQ)' || (echo "Error: $(TBB_VERREQ) not found" && exit 1) @pkg-config '$(FMT_VERREQ)' || (echo "Error: $(FMT_VERREQ) not found" && exit 1) + @pkg-config '$(SPDLOG_VERREQ)' || (echo "Error: $(SPDLOG_VERREQ) not found" && exit 1) $(PROJECT): $(OBJS) $(CXX) $(CXXFLAGS) $^ $(LIBS) $(LDFLAGS) -o $@ diff --git a/cabin.toml b/cabin.toml index a50e00992..e5d46d135 100644 --- a/cabin.toml +++ b/cabin.toml @@ -14,6 +14,7 @@ version = "0.12.0-dev" toml11 = {git = "https://github.com/ToruNiina/toml11.git", rev = "fdd5e29f78eb9e58cc02736f2dc4263ed0058662"} mitama-cpp-result = {git = "https://github.com/loliGothicK/mitama-cpp-result.git", tag = "v11.0.0"} fmt = {version = ">=9 && <12", system = true} +spdlog = {version = ">=1.8 && <2", system = true} libcurl = {version = ">=7.79.1 && <9", system = true} libgit2 = {version = ">=1.7 && <1.10", system = true} nlohmann_json = {version = "3.10.5", system = true} diff --git a/src/Algos.cc b/src/Algos.cc index 8b811e542..f21c227a3 100644 --- a/src/Algos.cc +++ b/src/Algos.cc @@ -1,13 +1,13 @@ #include "Algos.hpp" #include "Command.hpp" -#include "Logger.hpp" #include "Rustify/Result.hpp" #include #include #include #include +#include #include #include #include @@ -49,13 +49,13 @@ replaceAll( Result execCmd(const Command& cmd) noexcept { - logger::debug("Running `{}`", cmd.toString()); + spdlog::debug("Running `{}`", cmd.toString()); return Try(cmd.spawn()).wait(); } Result getCmdOutput(const Command& cmd, const std::size_t retry) noexcept { - logger::trace("Running `{}`", cmd.toString()); + spdlog::trace("Running `{}`", cmd.toString()); ExitStatus exitStatus; std::string stdErr; diff --git a/src/BuildConfig.cc b/src/BuildConfig.cc index 9fb8cd4d8..3742e6955 100644 --- a/src/BuildConfig.cc +++ b/src/BuildConfig.cc @@ -3,8 +3,8 @@ #include "Algos.hpp" #include "Command.hpp" #include "Compiler.hpp" +#include "Diag.hpp" #include "Git2.hpp" -#include "Logger.hpp" #include "Manifest.hpp" #include "Parallelism.hpp" #include "Semver.hpp" @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -447,7 +448,7 @@ BuildConfig::containsTestCode(const std::string& sourceFile) const { // file. const bool containsTest = src != testSrc; if (containsTest) { - logger::trace("Found test code: {}", sourceFile); + spdlog::trace("Found test code: {}", sourceFile); } return Ok(containsTest); } @@ -622,7 +623,7 @@ BuildConfig::setVariables() { commitShortHash = commitHash.substr(0, git2::SHORT_HASH_LEN); commitDate = git2::Commit().lookup(repo, oid).time().toString(); } catch (const git2::Exception& e) { - logger::trace("No git repository found"); + spdlog::trace("No git repository found"); } // Variables Cabin sets for the user. @@ -883,7 +884,7 @@ BuildConfig::configureBuild() { std::string srcs; for (const fs::path& sourceFilePath : sourceFilePaths) { if (sourceFilePath != mainSource && isMainSource(sourceFilePath)) { - logger::warn( + Diag::warn( "source file `{}` is named `main` but is not located directly in the " "`src/` directory. " "This file will not be treated as the program's entry point. " @@ -891,7 +892,7 @@ BuildConfig::configureBuild() { sourceFilePath.string() ); } else if (sourceFilePath != libSource && isLibSource(sourceFilePath)) { - logger::warn( + Diag::warn( "source file `{}` is named `lib` but is not located directly in the " "`src/` directory. " "This file will not be treated as a hasLibraryTarget. " @@ -982,16 +983,16 @@ emitMakefile( bool buildProj = false; bool buildCompDb = false; if (config.makefileIsUpToDate()) { - logger::debug("Makefile is up to date"); + spdlog::debug("Makefile is up to date"); } else { - logger::debug("Makefile is NOT up to date"); + spdlog::debug("Makefile is NOT up to date"); buildProj = true; } if (profile.compDb) { if (config.compdbIsUpToDate()) { - logger::debug("compile_commands.json is up to date"); + spdlog::debug("compile_commands.json is up to date"); } else { - logger::debug("compile_commands.json is NOT up to date"); + spdlog::debug("compile_commands.json is NOT up to date"); buildCompDb = true; } } @@ -1024,10 +1025,10 @@ emitCompdb( Try(config.installDeps(includeDevDeps)); if (config.compdbIsUpToDate()) { - logger::debug("compile_commands.json is up to date"); + spdlog::debug("compile_commands.json is up to date"); return Ok(config.outBasePath); } - logger::debug("compile_commands.json is NOT up to date"); + spdlog::debug("compile_commands.json is NOT up to date"); Try(config.configureBuild()); std::ofstream ofs(config.outBasePath / "compile_commands.json"); diff --git a/src/Cabin.cc b/src/Cabin.cc index 304a7f922..ef52996f4 100644 --- a/src/Cabin.cc +++ b/src/Cabin.cc @@ -3,10 +3,12 @@ #include "Algos.hpp" #include "Cli.hpp" #include "Cmd.hpp" -#include "Logger.hpp" +#include "Diag.hpp" #include "Rustify/Result.hpp" #include "TermColor.hpp" +#include +#include #include #include @@ -76,12 +78,33 @@ colorizeAnyhowError(std::string s) { return s; } +static void +warnUnusedLogEnv() { +#if SPDLOG_VERSION > 11500 + if (std::getenv("SPDLOG_LEVEL")) { + logger::warn("SPDLOG_LEVEL is set but not used. Use CABIN_LOG instead."); + } +#else + if (std::getenv("CABIN_LOG")) { + Diag::warn("CABIN_LOG is set but not used. Use SPDLOG_LEVEL instead."); + } +#endif +} + Result cabinMain(int argc, char* argv[]) noexcept { // NOLINT(*-avoid-c-arrays) + // Set up logger + spdlog::cfg::load_env_levels( +#if SPDLOG_VERSION > 11500 + "CABIN_LOG" +#endif + ); + warnUnusedLogEnv(); + return getCli() .parseArgs(argc, argv) .map_err([](const auto& e) { return colorizeAnyhowError(e->what()); }) - .map_err([](std::string e) { logger::error("{}", std::move(e)); }); + .map_err([](std::string e) { Diag::error("{}", std::move(e)); }); } } // namespace cabin diff --git a/src/Cli.cc b/src/Cli.cc index bc7bd6402..b6cb5bb0b 100644 --- a/src/Cli.cc +++ b/src/Cli.cc @@ -1,7 +1,7 @@ #include "Cli.hpp" #include "Algos.hpp" -#include "Logger.hpp" +#include "Diag.hpp" #include "Rustify/Result.hpp" #include "TermColor.hpp" @@ -387,13 +387,13 @@ Cli::handleGlobalOpts( return getCli().printHelp({}).map([] { return Return; }); } } else if (arg == "-v" || arg == "--verbose") { - logger::setLevel(logger::Level::Debug); + setDiagLevel(DiagLevel::Verbose); return Ok(Continue); } else if (arg == "-vv") { - logger::setLevel(logger::Level::Trace); + setDiagLevel(DiagLevel::VeryVerbose); return Ok(Continue); } else if (arg == "-q" || arg == "--quiet") { - logger::setLevel(logger::Level::Off); + setDiagLevel(DiagLevel::Off); return Ok(Continue); } else if (arg == "--color") { Ensure(itr + 1 < end, "missing argument for `--color`"); diff --git a/src/Cmd/Add.cc b/src/Cmd/Add.cc index 1b846a273..95f40d933 100644 --- a/src/Cmd/Add.cc +++ b/src/Cmd/Add.cc @@ -1,7 +1,7 @@ #include "Add.hpp" #include "../Cli.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" @@ -59,7 +59,7 @@ handleDependency( std::unordered_set& newDeps, const std::string_view dep ) { if (newDeps.contains(dep)) { - logger::warn("The dependency `{}` is already in the cabin.toml", dep); + Diag::warn("The dependency `{}` is already in the cabin.toml", dep); return; } newDeps.insert(dep); @@ -70,7 +70,7 @@ getDependencyGitUrl(const std::string_view dep) { if (dep.find("://") == std::string_view::npos) { // Check if at least in "user/repo" format. if (dep.find('/') == std::string_view::npos) { - logger::error("Invalid dependency: {}", dep); + Diag::error("Invalid dependency: {}", dep); return ""; } @@ -160,7 +160,7 @@ addDependencyToManifest( std::ofstream ofs(manifestPath); ofs << data; - logger::info("Added", "to the cabin.toml"); + Diag::info("Added", "to the cabin.toml"); return Ok(); } diff --git a/src/Cmd/Build.cc b/src/Cmd/Build.cc index eaa6dc0b9..c881aad9a 100644 --- a/src/Cmd/Build.cc +++ b/src/Cmd/Build.cc @@ -4,7 +4,7 @@ #include "../BuildConfig.hpp" #include "../Cli.hpp" #include "../Command.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Parallelism.hpp" #include "Common.hpp" @@ -49,7 +49,7 @@ runBuildCommand( ExitStatus exitStatus = Try(execCmd(checkUpToDateCmd)); if (!exitStatus.success()) { // If `targetName` is not up-to-date, compile it. - logger::info( + Diag::info( "Compiling", "{} v{} ({})", targetName, manifest.package.version.toString(), manifest.path.parent_path().string() @@ -85,7 +85,7 @@ buildImpl(const Manifest& manifest, std::string& outDir, const bool isDebug) { const Profile& profile = isDebug ? manifest.profiles.at("dev") : manifest.profiles.at("release"); - logger::info( + Diag::info( "Finished", "`{}` profile [{}] target(s) in {:.2f}s", modeToProfile(isDebug), profile.toString(), elapsed.count() ); @@ -141,7 +141,7 @@ buildMain(const CliArgsView args) { // Build compilation database const std::string outDir = Try(emitCompdb(manifest, isDebug, /*includeDevDeps=*/false)); - logger::info("Generated", "{}/compile_commands.json", outDir); + Diag::info("Generated", "{}/compile_commands.json", outDir); return Ok(); } diff --git a/src/Cmd/Clean.cc b/src/Cmd/Clean.cc index 4f51da5ba..eb81f2d68 100644 --- a/src/Cmd/Clean.cc +++ b/src/Cmd/Clean.cc @@ -1,7 +1,7 @@ #include "Clean.hpp" #include "../Cli.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" @@ -53,7 +53,7 @@ cleanMain(CliArgsView args) noexcept { } if (fs::exists(outDir)) { - logger::info("Removing", "{}", fs::canonical(outDir).string()); + Diag::info("Removing", "{}", fs::canonical(outDir).string()); fs::remove_all(outDir); } return Ok(); diff --git a/src/Cmd/Fmt.cc b/src/Cmd/Fmt.cc index 58cb46b07..85920e11a 100644 --- a/src/Cmd/Fmt.cc +++ b/src/Cmd/Fmt.cc @@ -3,15 +3,16 @@ #include "../Algos.hpp" #include "../BuildConfig.hpp" #include "../Cli.hpp" +#include "../Diag.hpp" #include "../Git2/Exception.hpp" #include "../Git2/Repository.hpp" -#include "../Logger.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ collectFormatTargets( repo.open(manifestDir.string()); hasGitRepo = true; } catch (const git2::Exception& e) { - logger::debug("No git repository found"); + spdlog::debug("No git repository found"); } const auto isExcluded = [&](std::string_view path) -> bool { @@ -62,7 +63,7 @@ collectFormatTargets( const std::string path = fs::relative(entry->path(), manifestDir).string(); if ((hasGitRepo && repo.isIgnored(path)) || isExcluded(path)) { - logger::debug("Ignore: {}", path); + spdlog::debug("Ignore: {}", path); entry.disable_recursion_pending(); continue; } @@ -70,7 +71,7 @@ collectFormatTargets( const fs::path path = fs::relative(entry->path(), manifestDir); if ((hasGitRepo && repo.isIgnored(path.string())) || isExcluded(path.string())) { - logger::debug("Ignore: {}", path.string()); + spdlog::debug("Ignore: {}", path.string()); continue; } @@ -126,7 +127,7 @@ fmtMain(const CliArgsView args) { const std::vector sources = collectFormatTargets(projectPath, excludes); if (sources.empty()) { - logger::warn("no files to format"); + Diag::warn("no files to format"); return Ok(); } @@ -137,7 +138,7 @@ fmtMain(const CliArgsView args) { clangFormatArgs.emplace_back("--dry-run"); } else { clangFormatArgs.emplace_back("-i"); - logger::info("Formatting", "{}", manifest.package.name); + Diag::info("Formatting", "{}", manifest.package.name); } clangFormatArgs.insert(clangFormatArgs.end(), sources.begin(), sources.end()); diff --git a/src/Cmd/Init.cc b/src/Cmd/Init.cc index 9b934b1b5..4bcd96e47 100644 --- a/src/Cmd/Init.cc +++ b/src/Cmd/Init.cc @@ -1,7 +1,7 @@ #include "Init.hpp" #include "../Cli.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" #include "Common.hpp" @@ -54,7 +54,7 @@ initMain(const CliArgsView args) { std::ofstream ofs("cabin.toml"); ofs << createCabinToml(packageName); - logger::info( + Diag::info( "Created", "{} `{}` package", isBin ? "binary (application)" : "library", packageName ); diff --git a/src/Cmd/Lint.cc b/src/Cmd/Lint.cc index 735bfb441..89daae49d 100644 --- a/src/Cmd/Lint.cc +++ b/src/Cmd/Lint.cc @@ -3,13 +3,14 @@ #include "../Algos.hpp" #include "../Cli.hpp" #include "../Command.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" #include #include #include +#include #include #include #include @@ -31,7 +32,7 @@ struct LintArgs { static Result lint(const std::string_view name, const std::vector& cpplintArgs) { - logger::info("Linting", "{}", name); + Diag::info("Linting", "{}", name); Command cpplintCmd("cpplint", cpplintArgs); if (!isVerbose()) { @@ -95,7 +96,7 @@ lintMain(const CliArgsView args) { std::vector cpplintArgs = lintArgs.excludes; if (fs::exists("CPPLINT.cfg")) { - logger::debug("Using CPPLINT.cfg for lint ..."); + spdlog::debug("Using CPPLINT.cfg for lint ..."); return lint(manifest.package.name, cpplintArgs); } @@ -108,7 +109,7 @@ lintMain(const CliArgsView args) { const std::vector& cpplintFilters = manifest.lint.cpplint.filters; if (!cpplintFilters.empty()) { - logger::debug("Using Cabin manifest file for lint ..."); + spdlog::debug("Using Cabin manifest file for lint ..."); std::string filterArg = "--filter="; for (const std::string_view filter : cpplintFilters) { filterArg += filter; @@ -119,7 +120,7 @@ lintMain(const CliArgsView args) { cpplintArgs.push_back(filterArg); return lint(manifest.package.name, cpplintArgs); } else { - logger::debug("Using default arguments for lint ..."); + spdlog::debug("Using default arguments for lint ..."); if (Edition::Cpp11 < manifest.package.edition) { // Disable C++11-related lints cpplintArgs.emplace_back("--filter=-build/c++11"); diff --git a/src/Cmd/New.cc b/src/Cmd/New.cc index e80761244..b3415abe6 100644 --- a/src/Cmd/New.cc +++ b/src/Cmd/New.cc @@ -2,14 +2,15 @@ #include "../Algos.hpp" #include "../Cli.hpp" +#include "../Diag.hpp" #include "../Git2.hpp" -#include "../Logger.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" #include "Common.hpp" #include #include +#include #include #include @@ -40,7 +41,7 @@ getAuthor() noexcept { return config.getString("user.name") + " <" + config.getString("user.email") + ">"; } catch (const git2::Exception& e) { - logger::debug("{}", e.what()); + spdlog::debug("{}", e.what()); return ""; } } @@ -105,7 +106,7 @@ createTemplateFiles(const bool isBin, const std::string_view projectName) { Try(writeToFile(ofs, projectName / fs::path(".gitignore"), "/cabin-out")); Try(writeToFile(ofs, projectName / fs::path("src") / "main.cc", MAIN_CC)); - logger::info("Created", "binary (application) `{}` package", projectName); + Diag::info("Created", "binary (application) `{}` package", projectName); } else { fs::create_directories(projectName / fs::path("include") / projectName); Try(writeToFile( @@ -121,7 +122,7 @@ createTemplateFiles(const bool isBin, const std::string_view projectName) { getHeader(projectName) )); - logger::info("Created", "library `{}` package", projectName); + Diag::info("Created", "library `{}` package", projectName); } return Ok(); } diff --git a/src/Cmd/Remove.cc b/src/Cmd/Remove.cc index 7b1895e47..5e31b4ddd 100644 --- a/src/Cmd/Remove.cc +++ b/src/Cmd/Remove.cc @@ -1,7 +1,7 @@ #include "Remove.hpp" #include "../Cli.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Rustify/Result.hpp" @@ -44,16 +44,14 @@ removeMain(const CliArgsView args) { } else { // manifestPath needs to be converted to string // or it adds extra quotes around the path - logger::warn( - "Dependency `{}` not found in {}", dep, manifestPath.string() - ); + Diag::warn("Dependency `{}` not found in {}", dep, manifestPath.string()); } } if (!removedDeps.empty()) { std::ofstream out(manifestPath); out << data; - logger::info( + Diag::info( "Removed", "{} from {}", fmt::join(removedDeps, ", "), manifestPath.string() ); diff --git a/src/Cmd/Run.cc b/src/Cmd/Run.cc index 115b59a04..70d1867f1 100644 --- a/src/Cmd/Run.cc +++ b/src/Cmd/Run.cc @@ -3,7 +3,7 @@ #include "../Algos.hpp" #include "../Cli.hpp" #include "../Command.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Parallelism.hpp" #include "../Rustify/Result.hpp" @@ -83,7 +83,7 @@ runMain(const CliArgsView args) { std::string outDir; Try(buildImpl(manifest, outDir, isDebug)); - logger::info( + Diag::info( "Running", "`{}/{}`", fs::relative(outDir, manifest.path.parent_path()).string(), manifest.package.name diff --git a/src/Cmd/Search.cc b/src/Cmd/Search.cc index fb99d4586..ab633b19e 100644 --- a/src/Cmd/Search.cc +++ b/src/Cmd/Search.cc @@ -1,7 +1,7 @@ #include "Search.hpp" #include "../Cli.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Rustify/Result.hpp" #include @@ -60,7 +60,7 @@ searchPackages(const SearchArgs& args) { CURL* curl = curl_easy_init(); if (!curl) { - logger::error("curl_easy_init() failed"); + Diag::error("curl_easy_init() failed"); return EXIT_FAILURE; } @@ -124,7 +124,7 @@ searchMain(const CliArgsView args) { const nlohmann::json packages = searchPackages(searchArgs); if (packages.empty()) { - logger::warn("no packages found"); + Diag::warn("no packages found"); return Ok(); } diff --git a/src/Cmd/Test.cc b/src/Cmd/Test.cc index ff9f2ae40..42c92c973 100644 --- a/src/Cmd/Test.cc +++ b/src/Cmd/Test.cc @@ -4,7 +4,7 @@ #include "../BuildConfig.hpp" #include "../Cli.hpp" #include "../Command.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Manifest.hpp" #include "../Parallelism.hpp" #include "../Rustify/Result.hpp" @@ -68,7 +68,7 @@ Test::parseArgs(const CliArgsView cliArgs) { } else if (arg == "-d" || arg == "--debug") { args.isDebug = true; } else if (arg == "-r" || arg == "--release") { - logger::warn("Tests in release mode possibly disables assert macros."); + Diag::warn("Tests in release mode possibly disables assert macros."); args.isDebug = false; } else if (arg == "-j" || arg == "--jobs") { if (itr + 1 == cliArgs.end()) { @@ -113,7 +113,7 @@ Test::compileTestTargets() { } if (unittestTargets.empty()) { - logger::warn("No test targets found"); + Diag::warn("No test targets found"); return Ok(); } @@ -130,7 +130,7 @@ Test::compileTestTargets() { if (!Try(execCmd(checkUpToDateCmd)).success()) { // This test target is not up-to-date. if (!alreadyEmitted) { - logger::info( + Diag::info( "Compiling", "{} v{} ({})", manifest.package.name, manifest.package.version.toString(), manifest.path.parent_path().string() @@ -154,7 +154,7 @@ Test::compileTestTargets() { const Profile& profile = args.isDebug ? manifest.profiles.at("dev") : manifest.profiles.at("release"); - logger::info( + Diag::info( "Finished", "`{}` profile [{}] target(s) in {:.2f}s", modeToProfile(args.isDebug), profile.toString(), elapsed.count() ); @@ -181,7 +181,7 @@ Test::runTestTargets() { const std::string testBinPath = fs::relative(target, manifest.path.parent_path()).string(); - logger::info("Running", "unittests {} ({})", sourcePath, testBinPath); + Diag::info("Running", "unittests {} ({})", sourcePath, testBinPath); const ExitStatus curExitStatus = Try(execCmd(Command(target))); if (curExitStatus.success()) { @@ -203,7 +203,7 @@ Test::runTestTargets() { if (!exitStatus.success()) { return Err(anyhow::anyhow(summary)); } - logger::info("Ok", "{}", summary); + Diag::info("Ok", "{}", summary); return Ok(); } diff --git a/src/Cmd/Tidy.cc b/src/Cmd/Tidy.cc index a6cf00bb3..0190141aa 100644 --- a/src/Cmd/Tidy.cc +++ b/src/Cmd/Tidy.cc @@ -4,7 +4,7 @@ #include "../BuildConfig.hpp" #include "../Cli.hpp" #include "../Command.hpp" -#include "../Logger.hpp" +#include "../Diag.hpp" #include "../Parallelism.hpp" #include "../Rustify/Result.hpp" #include "Common.hpp" @@ -38,7 +38,7 @@ tidyImpl(const Command& makeCmd) { const std::chrono::duration elapsed = end - start; if (exitStatus.success()) { - logger::info("Finished", "clang-tidy in {}s", elapsed.count()); + Diag::info("Finished", "clang-tidy in {}s", elapsed.count()); return Ok(); } Bail("clang-tidy {}", exitStatus); @@ -80,7 +80,7 @@ tidyMain(const CliArgsView args) { Ensure(commandExists("clang-tidy"), "clang-tidy is required"); if (fix && isParallel()) { - logger::warn("`--fix` implies `--jobs 1` to avoid race conditions"); + Diag::warn("`--fix` implies `--jobs 1` to avoid race conditions"); setParallelism(1); } @@ -110,7 +110,7 @@ tidyMain(const CliArgsView args) { makeCmd.addArg("--keep-going"); } - logger::info("Running", "clang-tidy"); + Diag::info("Running", "clang-tidy"); return tidyImpl(makeCmd); } diff --git a/src/Cmd/Version.cc b/src/Cmd/Version.cc index 2a7b4b954..15cd292a0 100644 --- a/src/Cmd/Version.cc +++ b/src/Cmd/Version.cc @@ -2,8 +2,8 @@ #include "../Cli.hpp" #include "../CurlVersion.hpp" +#include "../Diag.hpp" #include "../Git2/Version.hpp" -#include "../Logger.hpp" #include "../Rustify/Result.hpp" #include diff --git a/src/Dependency.cc b/src/Dependency.cc index d0af6b923..2e92181d6 100644 --- a/src/Dependency.cc +++ b/src/Dependency.cc @@ -3,11 +3,12 @@ #include "Algos.hpp" #include "Command.hpp" #include "Compiler.hpp" +#include "Diag.hpp" #include "Git2.hpp" -#include "Logger.hpp" #include #include +#include #include namespace cabin { @@ -35,7 +36,7 @@ GitDependency::install() const { } if (fs::exists(installDir) && !fs::is_empty(installDir)) { - logger::debug("{} is already installed", name); + spdlog::debug("{} is already installed", name); } else { git2::Repository repo; repo.clone(url, installDir.string()); @@ -48,7 +49,7 @@ GitDependency::install() const { repo.checkoutHead(true); } - logger::info( + Diag::info( "Downloaded", "{} {}", name, target.has_value() ? target.value() : url ); } @@ -74,7 +75,7 @@ Result PathDependency::install() const { const fs::path installDir = fs::weakly_canonical(path); if (fs::exists(installDir) && !fs::is_empty(installDir)) { - logger::debug("{} is already installed", name); + spdlog::debug("{} is already installed", name); } else { Bail("{} can't be accessible as directory", installDir.string()); } diff --git a/src/Diag.hpp b/src/Diag.hpp new file mode 100644 index 000000000..a80da1cf2 --- /dev/null +++ b/src/Diag.hpp @@ -0,0 +1,171 @@ +#pragma once + +#include "TermColor.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace cabin { + +enum class DiagLevel : uint8_t { + Off = 0, // --quiet, -q + Error = 1, + Warn = 2, + Info = 3, // default + Verbose = 4, // --verbose, -v + VeryVerbose = 5, // -vv +}; + +template +concept HeadProcessor = + std::is_nothrow_invocable_v + && fmt::is_formattable>::value; + +class Diag { + DiagLevel level = DiagLevel::Info; + + constexpr Diag() noexcept = default; + +public: + // Diag is a singleton + constexpr Diag(const Diag&) = delete; + constexpr Diag& operator=(const Diag&) = delete; + constexpr Diag(Diag&&) noexcept = delete; + constexpr Diag& operator=(Diag&&) noexcept = delete; + constexpr ~Diag() noexcept = default; + + static Diag& instance() noexcept { + static Diag instance; + return instance; + } + static void setLevel(DiagLevel level) noexcept { + instance().level = level; + } + static DiagLevel getLevel() noexcept { + return instance().level; + } + + template + static void error(fmt::format_string fmt, Args&&... args) noexcept { + logln( + DiagLevel::Error, + [](const std::string_view head) noexcept { + return Bold(Red(head)).toErrStr(); + }, + "Error: ", fmt, std::forward(args)... + ); + } + template + static void warn(fmt::format_string fmt, Args&&... args) noexcept { + logln( + DiagLevel::Warn, + [](const std::string_view head) noexcept { + return Bold(Yellow(head)).toErrStr(); + }, + "Warning: ", fmt, std::forward(args)... + ); + } + template + static void info( + const std::string_view header, fmt::format_string fmt, + Args&&... args + ) noexcept { + constexpr int infoHeaderMaxLength = 12; + constexpr int infoHeaderEscapeSequenceOffset = 11; + logln( + DiagLevel::Info, + [](const std::string_view head) noexcept { + return fmt::format( + "{:>{}} ", Bold(Green(head)).toErrStr(), + shouldColorStderr() + ? infoHeaderMaxLength + infoHeaderEscapeSequenceOffset + : infoHeaderMaxLength + ); + }, + header, fmt, std::forward(args)... + ); + } + template + static void + verbose(fmt::format_string fmt, Arg1&& a1, Args&&... args) noexcept { + logln( + DiagLevel::Verbose, + [](const std::string_view head) noexcept { return head; }, + std::forward(a1), fmt, std::forward(args)... + ); + } + template + static void veryVerbose( + fmt::format_string fmt, Arg1&& a1, Args&&... args + ) noexcept { + logln( + DiagLevel::Verbose, + [](const std::string_view head) noexcept { return head; }, + std::forward(a1), fmt, std::forward(args)... + ); + } + +private: + template + static void logln( + DiagLevel level, HeadProcessor auto&& processHead, auto&& head, + fmt::format_string fmt, Args&&... args + ) noexcept { + loglnImpl( + level, std::forward(processHead), + std::forward(head), fmt, std::forward(args)... + ); + } + + template + static void loglnImpl( + DiagLevel level, HeadProcessor auto&& processHead, auto&& head, + fmt::format_string fmt, Args&&... args + ) noexcept { + instance().log( + level, std::forward(processHead), + std::forward(head), fmt, std::forward(args)... + ); + } + + template + void + log(DiagLevel level, HeadProcessor auto&& processHead, auto&& head, + fmt::format_string fmt, Args&&... args) noexcept { + if (level <= this->level) { + fmt::print( + stderr, "{}{}\n", + std::invoke( + std::forward(processHead), + std::forward(head) + ), + fmt::format(fmt, std::forward(args)...) + ); + } + } +}; + +inline void +setDiagLevel(DiagLevel level) noexcept { + Diag::setLevel(level); +} +inline DiagLevel +getDiagLevel() noexcept { + return Diag::getLevel(); +} + +inline bool +isVerbose() noexcept { + return getDiagLevel() >= DiagLevel::Verbose; +} +inline bool +isQuiet() noexcept { + return getDiagLevel() == DiagLevel::Off; +} + +} // namespace cabin diff --git a/src/Logger.hpp b/src/Logger.hpp deleted file mode 100644 index 263f49a6b..000000000 --- a/src/Logger.hpp +++ /dev/null @@ -1,256 +0,0 @@ -#pragma once - -#include "TermColor.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace cabin::logger { - -enum class Level : uint8_t { - Off = 0, // --quiet, -q - Error = 1, - Warn = 2, - Info = 3, // default - Debug = 4, // --verbose, -v - Trace = 5, // -vv -}; - -// FIXME: duplicate code in Rustify/Tests.hpp but don't want to include it here. -// Maybe wait for modules to be stable? -constexpr std::string_view -prettifyFuncName(std::string_view func) noexcept { - if (func.empty()) { - return func; - } - - const std::size_t end = func.find_last_of('('); - if (end == std::string_view::npos) { - return func; - } - func = func.substr(0, end); - - const std::size_t start = func.find_last_of(' '); - if (start == std::string_view::npos) { - return func; - } - return func.substr(start + 1); -} - -template -concept HeadProcessor = - std::is_nothrow_invocable_v - && fmt::is_formattable>::value; - -class Logger { - Level level = Level::Info; - - constexpr Logger() noexcept = default; - -public: - // Logger is a singleton - constexpr Logger(const Logger&) = delete; - constexpr Logger& operator=(const Logger&) = delete; - constexpr Logger(Logger&&) noexcept = delete; - constexpr Logger& operator=(Logger&&) noexcept = delete; - constexpr ~Logger() noexcept = default; - - static Logger& instance() noexcept { - static Logger instance; - return instance; - } - static void setLevel(Level level) noexcept { - instance().level = level; - } - static Level getLevel() noexcept { - return instance().level; - } - - template - static void error(fmt::format_string fmt, Args&&... args) noexcept { - logln( - Level::Error, - [](const std::string_view head) noexcept { - return Bold(Red(head)).toErrStr(); - }, - "Error: ", fmt, std::forward(args)... - ); - } - template - static void warn(fmt::format_string fmt, Args&&... args) noexcept { - logln( - Level::Warn, - [](const std::string_view head) noexcept { - return Bold(Yellow(head)).toErrStr(); - }, - "Warning: ", fmt, std::forward(args)... - ); - } - template - static void info( - const std::string_view header, fmt::format_string fmt, - Args&&... args - ) noexcept { - constexpr int infoHeaderMaxLength = 12; - constexpr int infoHeaderEscapeSequenceOffset = 11; - logln( - Level::Info, - [](const std::string_view head) noexcept { - return fmt::format( - "{:>{}} ", Bold(Green(head)).toErrStr(), - shouldColorStderr() - ? infoHeaderMaxLength + infoHeaderEscapeSequenceOffset - : infoHeaderMaxLength - ); - }, - header, fmt, std::forward(args)... - ); - } - template - static void debug( - const std::string_view func, fmt::format_string fmt, - Args&&... args - ) noexcept { - debuglike( - Level::Debug, Blue("DEBUG"), func, fmt, std::forward(args)... - ); - } - template - static void trace( - const std::string_view func, fmt::format_string fmt, - Args&&... args - ) noexcept { - debuglike( - Level::Trace, Cyan("TRACE"), func, fmt, std::forward(args)... - ); - } - -private: - template - static void debuglike( - Level level, ColorStr lvl, const std::string_view func, - fmt::format_string fmt, Args&&... args - ) noexcept { - logln( - level, - [lvl = std::move(lvl)](const std::string_view func) noexcept { - return fmt::format( - "{}Cabin {} {}{} ", Gray("[").toErrStr(), lvl.toErrStr(), - prettifyFuncName(func), Gray("]").toErrStr() - ); - }, - func, fmt, std::forward(args)... - ); - } - - template - static void logln( - Level level, HeadProcessor auto&& processHead, auto&& head, - fmt::format_string fmt, Args&&... args - ) noexcept { - loglnImpl( - level, std::forward(processHead), - std::forward(head), fmt, std::forward(args)... - ); - } - - template - static void loglnImpl( - Level level, HeadProcessor auto&& processHead, auto&& head, - fmt::format_string fmt, Args&&... args - ) noexcept { - instance().log( - level, std::forward(processHead), - std::forward(head), fmt, std::forward(args)... - ); - } - - template - void - log(Level level, HeadProcessor auto&& processHead, auto&& head, - fmt::format_string fmt, Args&&... args) noexcept { - if (level <= this->level) { - fmt::print( - stderr, "{}{}\n", - std::invoke( - std::forward(processHead), - std::forward(head) - ), - fmt::format(fmt, std::forward(args)...) - ); - } - } -}; - -template -inline void -error(fmt::format_string fmt, Args&&... args) noexcept { - Logger::error(fmt, std::forward(args)...); -} -template -inline void -warn(fmt::format_string fmt, Args&&... args) noexcept { - Logger::warn(fmt, std::forward(args)...); -} -template -inline void -info( - const std::string_view header, fmt::format_string fmt, - Args&&... args -) noexcept { - Logger::info(header, fmt, std::forward(args)...); -} - -template -struct debug { // NOLINT(readability-identifier-naming) - explicit debug( - fmt::format_string fmt, Args&&... args, - const std::source_location& loc = std::source_location::current() - ) noexcept { - Logger::debug(loc.function_name(), fmt, std::forward(args)...); - } -}; -template -debug(fmt::format_string, Args&&...) -> debug; - -template -struct trace { // NOLINT(readability-identifier-naming) - explicit trace( - fmt::format_string fmt, Args&&... args, - const std::source_location& loc = std::source_location::current() - ) noexcept { - Logger::trace(loc.function_name(), fmt, std::forward(args)...); - } -}; -template -trace(fmt::format_string, Args&&...) -> trace; - -inline void -setLevel(Level level) noexcept { - Logger::setLevel(level); -} -inline Level -getLevel() noexcept { - return Logger::getLevel(); -} - -} // namespace cabin::logger - -namespace cabin { - -inline bool -isVerbose() noexcept { - return logger::getLevel() >= logger::Level::Debug; -} -inline bool -isQuiet() noexcept { - return logger::getLevel() == logger::Level::Off; -} - -} // namespace cabin diff --git a/src/Manifest.cc b/src/Manifest.cc index cc0e181c2..fee30ab7f 100644 --- a/src/Manifest.cc +++ b/src/Manifest.cc @@ -1,7 +1,6 @@ #include "Manifest.hpp" #include "Compiler.hpp" -#include "Logger.hpp" #include "Rustify/Result.hpp" #include "Semver.hpp" #include "VersionReq.hpp" @@ -12,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -339,7 +339,7 @@ static Result> parseDependencies(const toml::value& val, const char* key) noexcept { const auto tomlDeps = toml::try_find(val, key); if (tomlDeps.is_err()) { - logger::debug("[{}] not found or not a table", key); + spdlog::debug("[{}] not found or not a table", key); return Ok(std::vector{}); } @@ -397,7 +397,7 @@ Manifest::findPath(fs::path candidateDir) noexcept { const fs::path origCandDir = candidateDir; while (true) { const fs::path configPath = candidateDir / FILE_NAME; - logger::trace("Finding manifest: {}", configPath.string()); + spdlog::trace("Finding manifest: {}", configPath.string()); if (fs::exists(configPath)) { return Ok(configPath); } diff --git a/src/Parallelism.cc b/src/Parallelism.cc index 6695e3538..eccdb5fbf 100644 --- a/src/Parallelism.cc +++ b/src/Parallelism.cc @@ -1,6 +1,6 @@ #include "Parallelism.hpp" -#include "Logger.hpp" +#include "Diag.hpp" #include #include @@ -28,7 +28,7 @@ struct ParallelismState { void set(std::size_t numThreads) noexcept { if (numThreads == 0) { - logger::warn("requested parallelism of 0, capping at 1"); + Diag::warn("requested parallelism of 0, capping at 1"); numThreads = 1; } diff --git a/src/TermColor.cc b/src/TermColor.cc index 6f9952c11..b64d2a920 100644 --- a/src/TermColor.cc +++ b/src/TermColor.cc @@ -1,6 +1,6 @@ #include "TermColor.hpp" -#include "Logger.hpp" +#include "Diag.hpp" #include #include @@ -24,7 +24,7 @@ getColorMode(const std::string_view str) noexcept { } else if (str == "never") { return ColorMode::Never; } else { - logger::warn("unknown color mode `{}`; falling back to auto", str); + Diag::warn("unknown color mode `{}`; falling back to auto", str); return ColorMode::Auto; } }