Commit 8f8ea243 authored by Brad King's avatar Brad King
Browse files

VS: Work around Intel Compiler 2019 bug in VS 2019 integration

When VS 2019 sees a project with an empty `LanguageStandard` setting it
replaces that empty string with the value `Default` (this was not done
in VS 2017 or earlier).  The Intel Compiler 2019 Visual Studio
Integration does not recognize the value and gives the error:

    ...\PlatformToolsets\Intel C++ Compiler 19.0\Toolset.targets(350,5):
    error : Element <LanguageStandard> has an invalid value of "Default".

Parse the `icl.xml` file that comes with the Intel VS integration to
detect when this problem is present (so that we hopefully avoid this
when Intel fixes the problem).  Work around this by replacing an empty
`LanguageStandard` value with a value that the Intel integration
recognizes.  Issue a warning when doing so may change the build
semantics or cause warnings.

Issue: #19691
parent 9602bcfc
......@@ -241,6 +241,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(vs_version ${CMAKE_MATCH_1})
set(id_platform ${CMAKE_VS_PLATFORM_NAME})
set(id_lang "${lang}")
set(id_LanguageStandard "")
set(id_PostBuildEvent_Command "")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "^[Ll][Ll][Vv][Mm](_v[0-9]+(_xp)?)?$")
set(id_cl_var "ClangClExecutable")
......@@ -282,6 +283,10 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_toolset "<PlatformToolset>${CMAKE_VS_PLATFORM_TOOLSET}</PlatformToolset>")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
set(id_cl icl.exe)
if(NOT "${vs_version}" VERSION_LESS 16)
# The Intel Compiler 2019 VS integration fails on the "Default" value.
set(id_LanguageStandard "<LanguageStandard>stdcpp14</LanguageStandard>")
endif()
endif()
if(CMAKE_VS_PLATFORM_TOOLSET_VERSION)
set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build\\${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
......
......@@ -48,6 +48,7 @@
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<DebugInformationFormat>
</DebugInformationFormat>
@id_LanguageStandard@
</ClCompile>
@id_ItemDefinitionGroup_entry@
<Link>
......
......@@ -229,6 +229,40 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
}
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS16 &&
cmHasLiteralPrefix(this->GetPlatformToolsetString(), "Intel")) {
std::string const icl_xml = cmStrCat(
this->VCTargetsPath, "/Platforms/", this->GetPlatformName(),
"/PlatformToolsets/", this->GetPlatformToolsetString(), "/1033/icl.xml");
cmsys::ifstream fin(icl_xml.c_str());
std::string line;
bool haveLanguageStandard = false;
bool haveLanguageStandardDefault = false;
while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
if (haveLanguageStandard) {
if (line.find("</EnumProperty>") != std::string::npos) {
break;
}
if (line.find("<EnumValue Name=\"Default\" ") != std::string::npos) {
haveLanguageStandardDefault = true;
break;
}
} else {
if (line.find("<EnumProperty Name=\"LanguageStandard\" ") !=
std::string::npos) {
haveLanguageStandard = true;
}
}
}
if (haveLanguageStandard && !haveLanguageStandardDefault) {
// VS 2019 converts an empty LanguageStandard value to "Default"
// but the Intel Compiler integration does not know about it.
// Use a value that passes '-std:c++14' which is close to the
// compiler default for C++ anyway.
this->PlatformToolsetDefaultLanguageStandard = "stdcpp14";
}
}
if (this->GeneratorToolsetCuda.empty()) {
// Find the highest available version of the CUDA tools.
std::vector<std::string> cudaTools;
......@@ -351,6 +385,29 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
return true;
}
void cmGlobalVisualStudio10Generator::
WarnPlatformToolsetDefaultLanguageStandard()
{
if (this->PlatformToolsetDefaultLanguageStandardWarned ||
this->CMakeInstance->GetIsInTryCompile()) {
return;
}
this->PlatformToolsetDefaultLanguageStandardWarned = true;
/* clang-format off */
std::string w = cmStrCat(
"The toolset '", this->GetPlatformToolsetString(), "' has a bug "
"in its Intel Compiler Visual Studio integration. "
"It cannot build a '.vcxproj' file without one of the C++ standard level "
"flags '-std:c++{14,17,latest}' (even for C). "
"CMake is working around this by forcing a default LanguageStandard "
"value '", this->PlatformToolsetDefaultLanguageStandard, "', "
"but this may cause warnings about conflicts with Qstd flags. "
"Hopefully Intel fixes this in a newer version of their compiler."
);
/* clang-format on */
this->CMakeInstance->IssueMessage(MessageType::WARNING, w);
}
bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
std::string const& ts, cmMakefile* mf)
{
......@@ -557,6 +614,7 @@ cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator(
void cmGlobalVisualStudio10Generator::Generate()
{
this->PlatformToolsetDefaultLanguageStandardWarned = false;
this->LongestSource = LongestSourcePath();
this->cmGlobalVisualStudio8Generator::Generate();
if (this->LongestSource.Length > 0) {
......
......@@ -72,6 +72,13 @@ public:
return this->PlatformToolsetNeedsDebugEnum;
}
/** Return the default LanguageStandard needed by this toolset, if any. */
std::string const& GetPlatformToolsetDefaultLanguageStandard() const
{
return this->PlatformToolsetDefaultLanguageStandard;
}
void WarnPlatformToolsetDefaultLanguageStandard();
/** Return the CMAKE_SYSTEM_NAME. */
std::string const& GetSystemName() const { return this->SystemName; }
......@@ -203,6 +210,8 @@ private:
std::string GetVSMakeProgram() override { return this->GetMSBuildCommand(); }
bool PlatformToolsetNeedsDebugEnum;
std::string PlatformToolsetDefaultLanguageStandard;
bool PlatformToolsetDefaultLanguageStandardWarned = false;
bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
......
......@@ -2848,6 +2848,14 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.RemoveFlag("SpectreMitigation");
}
std::string const& defaultLanguageStandard =
gg->GetPlatformToolsetDefaultLanguageStandard();
if (!defaultLanguageStandard.empty() &&
!clOptions.HasFlag("LanguageStandard")) {
gg->WarnPlatformToolsetDefaultLanguageStandard();
clOptions.AddFlag("LanguageStandard", defaultLanguageStandard);
}
this->ClOptions[configName] = std::move(pOptions);
return true;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment