This is a generalization of the fix in PR #1348 for issue #1347.
}
}
-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;
}
}
+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,
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);
#include "TestUtil.hpp"
#include <util/file.hpp>
+#include <util/filesystem.hpp>
#include <util/fmtmacros.hpp>
#include <util/path.hpp>
#include <util/wincompat.hpp>
# include <unistd.h>
#endif
+namespace fs = util::filesystem;
using TestUtil::TestContext;
TEST_SUITE_BEGIN("ccache");
#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
}