#include <string>
#include <unordered_map>
-enum class CompilerType { auto_guess, clang, gcc, msvc, nvcc, other };
+enum class CompilerType { auto_guess, clang, clangcl, gcc, msvc, nvcc, other };
std::string compiler_type_to_string(CompilerType compiler_type);
const std::string& compiler() const;
const std::string& compiler_check() const;
CompilerType compiler_type() const;
+ // Returns true for clang or clangcl.
+ bool is_compiler_group_clang() const;
+ // Returns true for cl or clangcl.
+ bool is_compiler_group_cl() const;
bool compression() const;
int8_t compression_level() const;
const std::string& cpp_extension() const;
return m_compiler_type;
}
+inline bool
+Config::is_compiler_group_clang() const
+{
+ return m_compiler_type == CompilerType::clang
+ || m_compiler_type == CompilerType::clangcl;
+}
+
+inline bool
+Config::is_compiler_group_cl() const
+{
+ return m_compiler_type == CompilerType::msvc
+ || m_compiler_type == CompilerType::clangcl;
+}
+
inline bool
Config::compression() const
{
new_profile_path = arg.substr(arg.find('=') + 1);
} else if (arg == "-fprofile-generate" || arg == "-fprofile-instr-generate") {
args_info.profile_generate = true;
- if (ctx.config.compiler_type() == CompilerType::clang) {
+ if (ctx.config.is_compiler_group_clang()) {
new_profile_path = ".";
} else {
// GCC uses $PWD/$(basename $obj).
}
bool changed_from_slash = false;
- if (ctx.config.compiler_type() == CompilerType::msvc
- && util::starts_with(args[i], "/")) {
+ if (ctx.config.is_compiler_group_cl() && util::starts_with(args[i], "/")) {
// MSVC understands both /option and -option, so convert all /option to
// -option to simplify our handling.
args[i][0] = '-';
return Statistic::called_for_preprocessing;
}
// MSVC -P is -E with output to a file.
- if (args[i] == "-P" && ctx.config.compiler_type() == CompilerType::msvc) {
+ if (args[i] == "-P" && ctx.config.is_compiler_group_cl()) {
return Statistic::called_for_preprocessing;
}
++argpath;
}
auto file_args =
- Args::from_atfile(argpath, config.compiler_type() == CompilerType::msvc);
+ Args::from_atfile(argpath, ctx.config.is_compiler_group_cl());
if (!file_args) {
LOG("Couldn't read arg file {}", argpath);
return Statistic::bad_compiler_arguments;
}
// MSVC -Fo with no space.
- if (util::starts_with(args[i], "-Fo")
- && config.compiler_type() == CompilerType::msvc) {
+ if (util::starts_with(args[i], "-Fo") && config.is_compiler_group_cl()) {
args_info.output_obj =
Util::make_relative_path(ctx, string_view(args[i]).substr(3));
return nullopt;
// These options require special handling, because they behave differently
// with gcc -E, when the output file is not specified.
if ((args[i] == "-MD" || args[i] == "-MMD")
- && config.compiler_type() != CompilerType::msvc) {
+ && !config.is_compiler_group_cl()) {
args_info.generating_dependencies = true;
args_info.seen_MD_MMD = true;
state.dep_args.push_back(args[i]);
}
if ((util::starts_with(args[i], "-MQ") || util::starts_with(args[i], "-MT"))
- && config.compiler_type() != CompilerType::msvc) {
+ && !config.is_compiler_group_cl()) {
args_info.dependency_target_specified = true;
if (args[i].size() == 3) {
// MSVC -MD[d], -MT[d] and -LT[d] options are something different than GCC's
// -MD etc.
- if (config.compiler_type() == CompilerType::msvc
+ if (config.is_compiler_group_cl()
&& (util::starts_with(args[i], "-MD") || util::starts_with(args[i], "-MT")
|| util::starts_with(args[i], "-LD"))) {
// These affect compiler but also #define some things.
}
// MSVC -u is something else than GCC -u, handle it specially.
- if (args[i] == "-u" && ctx.config.compiler_type() == CompilerType::msvc) {
+ if (args[i] == "-u" && ctx.config.is_compiler_group_cl()) {
state.cpp_args.push_back(args[i]);
return nullopt;
}
string_view extension;
if (state.found_S_opt) {
extension = ".s";
- } else if (ctx.config.compiler_type() != CompilerType::msvc) {
+ } else if (!ctx.config.is_compiler_group_cl()) {
extension = ".o";
} else {
extension = ".obj";
// Since output is redirected, compilers will not color their output by
// default, so force it explicitly.
nonstd::optional<std::string> diagnostics_color_arg;
- if (config.compiler_type() == CompilerType::clang) {
+ if (config.is_compiler_group_clang()) {
// Don't pass -fcolor-diagnostics when compiling assembler to avoid an
// "argument unused during compilation" warning.
if (args_info.actual_language != "assembler") {
const auto name =
Util::to_lowercase(Util::remove_extension(Util::base_name(compiler_path)));
- if (name.find("clang") != nonstd::string_view::npos) {
+ if (name.find("clang-cl") != nonstd::string_view::npos) {
+ return CompilerType::clangcl;
+ } else if (name.find("clang") != nonstd::string_view::npos) {
return CompilerType::clang;
} else if (name.find("gcc") != nonstd::string_view::npos
|| name.find("g++") != nonstd::string_view::npos) {
const Args& depend_extra_args,
Hash* depend_mode_hash)
{
- if (ctx.config.compiler_type() == CompilerType::msvc) {
+ if (ctx.config.is_compiler_group_cl()) {
args.push_back(fmt::format("-Fo{}", ctx.args_info.output_obj));
} else {
args.push_back("-o");
// clang will emit warnings for unused linker flags, so we shouldn't skip
// those arguments.
- int is_clang = ctx.config.compiler_type() == CompilerType::clang
+ int is_clang = ctx.config.is_compiler_group_clang()
|| ctx.config.compiler_type() == CompilerType::other;
// First the arguments.
//
// file 'foo.h' has been modified since the precompiled header 'foo.pch'
// was built
- if ((ctx.config.compiler_type() == CompilerType::clang
+ if ((ctx.config.is_compiler_group_clang()
|| ctx.config.compiler_type() == CompilerType::other)
&& ctx.args_info.output_is_precompiled_header
&& mode == FromCacheCallMode::cpp) {
TRY(set_up_uncached_err());
- if (!ctx.config.run_second_cpp()
- && ctx.config.compiler_type() == CompilerType::msvc) {
+ if (!ctx.config.run_second_cpp() && ctx.config.is_compiler_group_cl()) {
LOG_RAW("Second preprocessor cannot be disabled");
ctx.config.set_run_second_cpp(true);
}