From: Joel Rosdahl Date: Thu, 23 Nov 2023 20:46:20 +0000 (+0100) Subject: fix: Detect compiler from unresolved symlink with fallback X-Git-Tag: v4.9~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46e9192c3abd9d7fbb75510d1a3a75019061824a;p=thirdparty%2Fccache.git fix: Detect compiler from unresolved symlink with fallback This is a generalization of the fix in PR #1348 for issue #1347. --- diff --git a/src/ccache.cpp b/src/ccache.cpp index cc4449239..833c667d3 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -243,35 +243,35 @@ init_hash_debug(Context& ctx, } } -CompilerType -guess_compiler(std::string_view path) -{ - std::string compiler_path(path); - const auto name_original = - util::to_lowercase(Util::remove_extension(Util::base_name(compiler_path))); - #ifndef _WIN32 +std::string +follow_symlinks(const fs::path& path) +{ // Follow symlinks to the real compiler to learn its name. We're not using // util::real_path in order to save some unnecessary stat calls. + fs::path p = path; while (true) { - auto symlink_target = fs::read_symlink(compiler_path); + auto symlink_target = fs::read_symlink(p); if (!symlink_target) { // Not a symlink. break; } if (symlink_target->is_absolute()) { - compiler_path = *symlink_target; + p = *symlink_target; } else { - compiler_path = - FMT("{}/{}", Util::dir_name(compiler_path), symlink_target->string()); + p = p.parent_path() / *symlink_target; } } + return p; +} #endif +static CompilerType +do_guess_compiler(const fs::path& path) +{ const auto name = - util::to_lowercase(Util::remove_extension(Util::base_name(compiler_path))); - if (name.find("clang-cl") != std::string_view::npos - || name_original.find("clang-cl") != std::string_view::npos) { + util::to_lowercase(path.filename().replace_extension("").string()); + if (name.find("clang-cl") != std::string_view::npos) { return CompilerType::clang_cl; } else if (name.find("clang") != std::string_view::npos) { return CompilerType::clang; @@ -289,6 +289,21 @@ guess_compiler(std::string_view path) } } +CompilerType +guess_compiler(const fs::path& path) +{ + CompilerType type = do_guess_compiler(path); +#ifdef _WIN32 + return type; +#else + if (type == CompilerType::other) { + return do_guess_compiler(follow_symlinks(path)); + } else { + return type; + } +#endif +} + static bool include_file_too_new(const Context& ctx, const std::string& path, diff --git a/src/ccache.hpp b/src/ccache.hpp index c085c02db..771031a0f 100644 --- a/src/ccache.hpp +++ b/src/ccache.hpp @@ -53,7 +53,7 @@ void find_compiler(Context& ctx, const FindExecutableFunction& find_executable_function, bool masquerading_as_compiler); -CompilerType guess_compiler(std::string_view path); +CompilerType guess_compiler(const std::filesystem::path& path); bool is_ccache_executable(const std::filesystem::path& path); diff --git a/unittest/test_ccache.cpp b/unittest/test_ccache.cpp index d2fd04be5..02c6161cb 100644 --- a/unittest/test_ccache.cpp +++ b/unittest/test_ccache.cpp @@ -21,6 +21,7 @@ #include "TestUtil.hpp" #include +#include #include #include #include @@ -35,6 +36,7 @@ # include #endif +namespace fs = util::filesystem; using TestUtil::TestContext; TEST_SUITE_BEGIN("ccache"); @@ -193,14 +195,24 @@ TEST_CASE("guess_compiler") #ifndef _WIN32 SUBCASE("Follow symlink to actual compiler") { - const auto cwd = util::actual_cwd(); - util::write_file(FMT("{}/gcc", cwd), ""); - CHECK(symlink("gcc", FMT("{}/intermediate", cwd).c_str()) == 0); - const auto cc = FMT("{}/cc", cwd); - CHECK(symlink("intermediate", cc.c_str()) == 0); + const auto cwd = fs::path(util::actual_cwd()); + util::write_file(cwd / "gcc", ""); + CHECK(fs::create_symlink("gcc", cwd / "intermediate")); + const auto cc = cwd / "cc"; + CHECK(fs::create_symlink("intermediate", cc)); CHECK(guess_compiler(cc) == CompilerType::gcc); } + + SUBCASE("Classify clang-cl symlink to clang") + { + const auto cwd = fs::path(util::actual_cwd()); + util::write_file(cwd / "clang", ""); + const auto clang_cl = cwd / "clang-cl"; + CHECK(fs::create_symlink("clang", clang_cl)); + + CHECK(guess_compiler(clang_cl) == CompilerType::clang_cl); + } #endif }