diff options
author | Brad King <brad.king@kitware.com> | 2017-03-13 12:57:55 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2017-03-13 12:57:57 (GMT) |
commit | b46fa35824f2e8716032b3ec3201d0a0ee445f86 (patch) | |
tree | a0e4c215bde6903a94610651b404f5d612a7a169 /Source | |
parent | abfc55a362bd2ad5ea45f7f8f228adf516f389ad (diff) | |
parent | 65481a60a06b4238d342f64b5fed52e252ee191b (diff) | |
download | CMake-b46fa35824f2e8716032b3ec3201d0a0ee445f86.zip CMake-b46fa35824f2e8716032b3ec3201d0a0ee445f86.tar.gz CMake-b46fa35824f2e8716032b3ec3201d0a0ee445f86.tar.bz2 |
Merge topic 'cuda-vs'
65481a60 CUDA: Work around VS limitation in CudaOnly.WithDefs test
8cae24a1 VS: Add more CUDA flag table entries
6ca4f222 VS: Add support for the CUDA_SEPARABLE_COMPILATION property
94255511 VS: Select CUDA code generation architectures
253594d0 VS: Select the CUDA runtime library
4def02a3 VS: Place CUDA host compiler options in proper project file fields
29f07b08 VS: Do not pass CUDA compile options to C compiler
b966f489 VS: Do not use absolute paths to CUDA sources
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !566
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.cxx | 281 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.h | 16 | ||||
-rw-r--r-- | Source/cmVS10CudaFlagTable.h | 51 | ||||
-rw-r--r-- | Source/cmVS10CudaHostFlagTable.h | 35 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 150 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.h | 5 | ||||
-rw-r--r-- | Source/cmVisualStudioGeneratorOptions.cxx | 127 | ||||
-rw-r--r-- | Source/cmVisualStudioGeneratorOptions.h | 22 |
8 files changed, 678 insertions, 9 deletions
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index b1285ac..ca98e6c 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -10,15 +10,25 @@ #include "cmSourceFile.h" #include "cmVS10CLFlagTable.h" #include "cmVS10CSharpFlagTable.h" +#include "cmVS10CudaFlagTable.h" +#include "cmVS10CudaHostFlagTable.h" #include "cmVS10LibFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10MASMFlagTable.h" #include "cmVS10NASMFlagTable.h" #include "cmVS10RCFlagTable.h" +#include "cmVersion.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" +#include "cmXMLWriter.h" #include "cmake.h" +#include <cmsys/FStream.hxx> +#include <cmsys/Glob.hxx> +#include <cmsys/RegularExpression.hxx> + +#include <algorithm> + static const char vs10generatorName[] = "Visual Studio 10 2010"; // Map generator name without year to name with year. @@ -95,6 +105,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); + this->CudaEnabled = false; this->SystemIsWindowsCE = false; this->SystemIsWindowsPhone = false; this->SystemIsWindowsStore = false; @@ -113,6 +124,8 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable; this->DefaultLibFlagTable = cmVS10LibFlagTable; this->DefaultLinkFlagTable = cmVS10LinkFlagTable; + this->DefaultCudaFlagTable = cmVS10CudaFlagTable; + this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable; this->DefaultMasmFlagTable = cmVS10MASMFlagTable; this->DefaultNasmFlagTable = cmVS10NASMFlagTable; this->DefaultRcFlagTable = cmVS10RCFlagTable; @@ -155,6 +168,13 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform( return true; } +static void cmCudaToolVersion(std::string& s) +{ + // "CUDA x.y.props" => "x.y" + s = s.substr(5); + s = s.substr(0, s.size() - 6); +} + bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( std::string const& ts, cmMakefile* mf) { @@ -170,12 +190,37 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (!this->ParseGeneratorToolset(ts, mf)) { return false; } + + if (!this->FindVCTargetsPath(mf)) { + return false; + } + + if (this->GeneratorToolsetCuda.empty()) { + // Find the highest available version of the CUDA tools. + std::vector<std::string> cudaTools; + std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations"; + cmsys::Glob gl; + gl.SetRelative(bcDir.c_str()); + if (gl.FindFiles(bcDir + "/CUDA *.props")) { + cudaTools = gl.GetFiles(); + } + if (!cudaTools.empty()) { + std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion); + std::sort(cudaTools.begin(), cudaTools.end(), + cmSystemTools::VersionCompareGreater); + this->GeneratorToolsetCuda = cudaTools.at(0); + } + } + if (const char* toolset = this->GetPlatformToolset()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); } if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch); } + if (const char* cuda = this->GetPlatformToolsetCuda()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda); + } return true; } @@ -251,8 +296,10 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( std::string const& key, std::string const& value) { - static_cast<void>(key); - static_cast<void>(value); + if (key == "cuda") { + this->GeneratorToolsetCuda = value; + return true; + } return false; } @@ -417,6 +464,9 @@ void cmGlobalVisualStudio10Generator::EnableLanguage( if (*it == "ASM_NASM") { this->NasmEnabled = true; } + if (*it == "CUDA") { + this->CudaEnabled = true; + } } this->AddPlatformDefinitions(mf); cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); @@ -453,6 +503,20 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const return CM_NULLPTR; } +const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const +{ + if (!this->GeneratorToolsetCuda.empty()) { + return this->GeneratorToolsetCuda.c_str(); + } + return CM_NULLPTR; +} + +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const +{ + return this->GeneratorToolsetCuda; +} + bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf) { if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) { @@ -507,6 +571,208 @@ std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand() return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand(); } +bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) +{ + // Skip this in special cases within our own test suite. + if (this->GetPlatformName() == "Test Platform" || + this->GetPlatformToolsetString() == "Test Toolset") { + return true; + } + + std::string wd; + if (!this->ConfiguredFilesPath.empty()) { + // In a try-compile we are given the outer CMakeFiles directory. + wd = this->ConfiguredFilesPath; + } else { + wd = this->GetCMakeInstance()->GetHomeOutputDirectory(); + wd += cmake::GetCMakeFilesDirectory(); + } + wd += "/"; + wd += cmVersion::GetCMakeVersion(); + + // We record the result persistently in a file. + std::string const txt = wd + "/VCTargetsPath.txt"; + + // If we have a recorded result, use it. + { + cmsys::ifstream fin(txt.c_str()); + if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) && + cmSystemTools::FileIsDirectory(this->VCTargetsPath)) { + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + return true; + } + } + + // Prepare the work directory. + if (!cmSystemTools::MakeDirectory(wd)) { + std::string e = "Failed to make directory:\n " + wd; + mf->IssueMessage(cmake::FATAL_ERROR, e.c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + // Generate a project file for MSBuild to tell us the VCTargetsPath value. + std::string const vcxproj = "VCTargetsPath.vcxproj"; + { + std::string const vcxprojAbs = wd + "/" + vcxproj; + cmsys::ofstream fout(vcxprojAbs.c_str()); + cmXMLWriter xw(fout); + + /* clang-format off */ + xw.StartDocument(); + xw.StartElement("Project"); + xw.Attribute("DefaultTargets", "Build"); + xw.Attribute("ToolsVersion", "4.0"); + xw.Attribute("xmlns", + "http://schemas.microsoft.com/developer/msbuild/2003"); + if (this->IsNsightTegra()) { + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "NsightTegraProject"); + xw.StartElement("NsightTegraProjectRevisionNumber"); + xw.Content("6"); + xw.EndElement(); // NsightTegraProjectRevisionNumber + xw.EndElement(); // PropertyGroup + } + xw.StartElement("ItemGroup"); + xw.Attribute("Label", "ProjectConfigurations"); + xw.StartElement("ProjectConfiguration"); + xw.Attribute("Include", "Debug|" + this->GetPlatformName()); + xw.StartElement("Configuration"); + xw.Content("Debug"); + xw.EndElement(); // Configuration + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + xw.EndElement(); // ProjectConfiguration + xw.EndElement(); // ItemGroup + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Globals"); + xw.StartElement("ProjectGUID"); + xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}"); + xw.EndElement(); // ProjectGUID + xw.StartElement("Keyword"); + xw.Content("Win32Proj"); + xw.EndElement(); // Keyword + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + if (this->GetSystemName() == "WindowsPhone") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Phone"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } else if (this->GetSystemName() == "WindowsStore") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Store"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } + if (!this->WindowsTargetPlatformVersion.empty()) { + xw.StartElement("WindowsTargetPlatformVersion"); + xw.Content(this->WindowsTargetPlatformVersion); + xw.EndElement(); // WindowsTargetPlatformVersion + } + if (this->GetPlatformName() == "ARM") { + xw.StartElement("WindowsSDKDesktopARMSupport"); + xw.Content("true"); + xw.EndElement(); // WindowsSDKDesktopARMSupport + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + xw.EndElement(); // Import + if (!this->GeneratorToolsetHostArchitecture.empty()) { + xw.StartElement("PropertyGroup"); + xw.StartElement("PreferredToolArchitecture"); + xw.Content(this->GeneratorToolsetHostArchitecture); + xw.EndElement(); // PreferredToolArchitecture + xw.EndElement(); // PropertyGroup + } + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Configuration"); + xw.StartElement("ConfigurationType"); + if (this->IsNsightTegra()) { + // Tegra-Android platform does not understand "Utility". + xw.Content("StaticLibrary"); + } else { + xw.Content("Utility"); + } + xw.EndElement(); // ConfigurationType + xw.StartElement("CharacterSet"); + xw.Content("MultiByte"); + xw.EndElement(); // CharacterSet + if (this->IsNsightTegra()) { + xw.StartElement("NdkToolchainVersion"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // NdkToolchainVersion + } else { + xw.StartElement("PlatformToolset"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // PlatformToolset + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + xw.EndElement(); // Import + xw.StartElement("ItemDefinitionGroup"); + xw.StartElement("PostBuildEvent"); + xw.StartElement("Command"); + xw.Content("echo VCTargetsPath=$(VCTargetsPath)"); + xw.EndElement(); // Command + xw.EndElement(); // PostBuildEvent + xw.EndElement(); // ItemDefinitionGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + xw.EndElement(); // Import + xw.EndElement(); // Project + xw.EndDocument(); + /* clang-format on */ + } + + std::vector<std::string> cmd; + cmd.push_back(this->GetMSBuildCommand()); + cmd.push_back(vcxproj); + cmd.push_back(std::string("/p:VisualStudioVersion=") + + this->GetIDEVersion()); + std::string out; + int ret = 0; + cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]"); + if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(), + cmSystemTools::OUTPUT_NONE) || + ret != 0 || !regex.find(out)) { + cmSystemTools::ReplaceString(out, "\n", "\n "); + std::ostringstream e; + /* clang-format off */ + e << + "Failed to run MSBuild command:\n" + " " << cmd[0] << "\n" + "to get the value of VCTargetsPath:\n" + " " << out << "\n" + ; + /* clang-format on */ + if (ret != 0) { + e << "Exit code: " << ret << "\n"; + } + mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + this->VCTargetsPath = regex.match(1); + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + + { + cmsys::ofstream fout(txt.c_str()); + fout << this->VCTargetsPath << "\n"; + } + return true; +} + void cmGlobalVisualStudio10Generator::GenerateBuildCommand( std::vector<std::string>& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -721,6 +987,17 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable; } +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const +{ + return this->DefaultCudaFlagTable; +} + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() + const +{ + return this->DefaultCudaHostFlagTable; +} + cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable( diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index c5e4bcd..20f992a 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -42,6 +42,8 @@ public: cmMakefile*, bool optional); virtual void WriteSLNHeader(std::ostream& fout); + bool IsCudaEnabled() const { return this->CudaEnabled; } + /** Generating for Nsight Tegra VS plugin? */ bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; @@ -53,6 +55,10 @@ public: /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */ const char* GetPlatformToolsetHostArchitecture() const; + /** The cuda toolset version. */ + const char* GetPlatformToolsetCuda() const; + std::string const& GetPlatformToolsetCudaString() const; + /** Return the CMAKE_SYSTEM_NAME. */ std::string const& GetSystemName() const { return this->SystemName; } @@ -94,6 +100,8 @@ public: cmIDEFlagTable const* GetRcFlagTable() const; cmIDEFlagTable const* GetLibFlagTable() const; cmIDEFlagTable const* GetLinkFlagTable() const; + cmIDEFlagTable const* GetCudaFlagTable() const; + cmIDEFlagTable const* GetCudaHostFlagTable() const; cmIDEFlagTable const* GetMasmFlagTable() const; cmIDEFlagTable const* GetNasmFlagTable() const; @@ -118,6 +126,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCuda; std::string DefaultPlatformToolset; std::string WindowsTargetPlatformVersion; std::string SystemName; @@ -127,6 +136,8 @@ protected: cmIDEFlagTable const* DefaultCSharpFlagTable; cmIDEFlagTable const* DefaultLibFlagTable; cmIDEFlagTable const* DefaultLinkFlagTable; + cmIDEFlagTable const* DefaultCudaFlagTable; + cmIDEFlagTable const* DefaultCudaHostFlagTable; cmIDEFlagTable const* DefaultMasmFlagTable; cmIDEFlagTable const* DefaultNasmFlagTable; cmIDEFlagTable const* DefaultRcFlagTable; @@ -160,6 +171,11 @@ private: bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + std::string VCTargetsPath; + bool FindVCTargetsPath(cmMakefile* mf); + + bool CudaEnabled; + // We do not use the reload macros for VS >= 10. virtual std::string GetUserMacrosDirectory() { return ""; } }; diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h new file mode 100644 index 0000000..da19d64 --- /dev/null +++ b/Source/cmVS10CudaFlagTable.h @@ -0,0 +1,51 @@ +static cmVS7FlagTable cmVS10CudaFlagTable[] = { + // Collect options meant for the host compiler. + { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable }, + { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable }, + + // Select the CUDA runtime library. + { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 }, + { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library", + "Shared", 0 }, + { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static", + 0 }, + { "CudaRuntime", "cudart", "CUDA runtime library", "", + cmVS7FlagTable::UserFollowing }, + + // Capture arch/code arguments into temporaries for post-processing. + { "cmake-temp-gencode", "gencode=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "gencode", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + + { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing }, + + { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-arch", "-gpu-architecture=", "", "", + cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "-gpu-architecture", "", "", + cmVS7FlagTable::UserFollowing }, + + // Other flags. + + { "FastMath", "use_fast_math", "", "true", 0 }, + { "FastMath", "-use_fast_math", "", "true", 0 }, + + { "GPUDebugInfo", "G", "", "true", 0 }, + { "GPUDebugInfo", "-device-debug", "", "true", 0 }, + + { "HostDebugInfo", "g", "", "true", 0 }, + { "HostDebugInfo", "-debug", "", "true", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h new file mode 100644 index 0000000..5b61066 --- /dev/null +++ b/Source/cmVS10CudaHostFlagTable.h @@ -0,0 +1,35 @@ +static cmVS7FlagTable cmVS10CudaHostFlagTable[] = { + //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0}, + { "Optimization", "Od", "Disabled", "Od", 0 }, + { "Optimization", "O1", "Minimize Size", "O1", 0 }, + { "Optimization", "O2", "Maximize Speed", "O2", 0 }, + { "Optimization", "Ox", "Full Optimization", "O3", 0 }, + + //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0}, + { "Runtime", "MT", "Multi-Threaded", "MT", 0 }, + { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 }, + { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 }, + { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 }, + { "Runtime", "ML", "Single-Threaded", "ML", 0 }, + { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 }, + + //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0}, + //{"RuntimeChecks", "", "Default", "Default", 0}, + { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 }, + { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 }, + { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 }, + + //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0}, + { "TypeInfo", "GR", "Yes", "true", 0 }, + { "TypeInfo", "GR-", "No", "false", 0 }, + + //{"Warning", "", "<inherit from host>", "InheritFromHost", 0}, + { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 }, + { "Warning", "W1", "Level 1", "W1", 0 }, + { "Warning", "W2", "Level 2", "W2", 0 }, + { "Warning", "W3", "Level 3", "W3", 0 }, + { "Warning", "W4", "Level 4", "W4", 0 }, + { "Warning", "Wall", "Enable All Warnings", "Wall", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4aea6f8..052cc7f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -112,6 +112,10 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() i != this->LinkOptions.end(); ++i) { delete i->second; } + for (OptionsMap::iterator i = this->CudaOptions.begin(); + i != this->CudaOptions.end(); ++i) { + delete i->second; + } if (!this->BuildFileStream) { return; } @@ -206,6 +210,9 @@ void cmVisualStudio10TargetGenerator::Generate() if (!this->ComputeRcOptions()) { return; } + if (!this->ComputeCudaOptions()) { + return; + } if (!this->ComputeMasmOptions()) { return; } @@ -454,6 +461,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1); } this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\CUDA ", + 2); + (*this->BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".props\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("<Import Project=\"$(VCTargetsPath)\\" "BuildCustomizations\\masm.props\" />\n", @@ -524,6 +539,14 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteTargetSpecificReferences(); this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1); this->WriteTargetsFileReferences(); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("<Import Project=\"$(VCTargetsPath)\\" + "BuildCustomizations\\CUDA ", + 2); + (*this->BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".targets\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("<Import Project=\"$(VCTargetsPath)\\" "BuildCustomizations\\masm.targets\" />\n", @@ -1694,8 +1717,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, // // and fail if this exceeds the maximum allowed path length. Our path // conversion uses full paths when possible to allow deeper trees. - bool forceRelative = false; - std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false); + // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA + // we must use relative paths. + bool forceRelative = sf->GetLanguage() == "CUDA"; + std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative); if (this->LocalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS10 && cmSystemTools::FileIsFullPath(sourceFile.c_str())) { @@ -1772,6 +1797,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() tool = "ResourceCompile"; } else if (lang == "CSharp") { tool = "Compile"; + } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) { + tool = "CudaCompile"; } if (!tool.empty()) { @@ -2207,8 +2234,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( if (linkLanguage == "CXX") { clOptions.AddFlag("CompileAs", "CompileAsCpp"); } - this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, - linkLanguage, configName.c_str()); + if (linkLanguage != "CUDA") { + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, + linkLanguage, configName.c_str()); + } // Get preprocessor definitions for this directory. std::string defineFlags = @@ -2400,6 +2429,99 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions( this->WriteString("</ResourceCompile>\n", 2); } +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions() +{ + if (!this->GlobalGenerator->IsCudaEnabled()) { + return true; + } + for (std::vector<std::string>::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeCudaOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); + CM_AUTO_PTR<Options> pOptions(new Options( + this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable())); + Options& cudaOptions = *pOptions; + + // Get compile flags for CUDA in this directory. + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + + // Get preprocessor definitions for this directory. + std::string defineFlags = + this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); + + cudaOptions.Parse(flags.c_str()); + cudaOptions.Parse(defineFlags.c_str()); + cudaOptions.ParseFinish(); + + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { + cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true"); + } + + // Convert the host compiler options to the toolset's abstractions + // using a secondary flag table. + cudaOptions.ClearTables(); + cudaOptions.AddTable(gg->GetCudaHostFlagTable()); + cudaOptions.Reparse("AdditionalCompilerOptions"); + + // `CUDA 8.0.targets` places these before nvcc! Just drop whatever + // did not parse and hope it works. + cudaOptions.RemoveFlag("AdditionalCompilerOptions"); + + cudaOptions.FixCudaCodeGeneration(); + + std::vector<std::string> targetDefines; + this->GeneratorTarget->GetCompileDefinitions(targetDefines, + configName.c_str(), "CUDA"); + cudaOptions.AddDefines(targetDefines); + + // Add a definition for the configuration name. + std::string configDefine = "CMAKE_INTDIR=\""; + configDefine += configName; + configDefine += "\""; + cudaOptions.AddDefine(configDefine); + if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { + cudaOptions.AddDefine(exportMacro); + } + + this->CudaOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteCudaOptions( + std::string const& configName, std::vector<std::string> const& includes) +{ + if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) { + return; + } + this->WriteString("<CudaCompile>\n", 2); + + Options& cudaOptions = *(this->CudaOptions[configName]); + cudaOptions.AppendFlag("Include", includes); + cudaOptions.AppendFlag("Include", "%(Include)"); + cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "CUDA"); + cudaOptions.PrependInheritedString("AdditionalOptions"); + cudaOptions.OutputFlagMap(*this->BuildFileStream, " "); + + this->WriteString("</CudaCompile>\n", 2); +} + bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() { if (!this->GlobalGenerator->IsMasmEnabled()) { @@ -2738,8 +2860,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this)); Options& linkOptions = *pOptions; - const std::string& linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(config.c_str()); + cmGeneratorTarget::LinkClosure const* linkClosure = + this->GeneratorTarget->GetLinkClosure(config); + + const std::string& linkLanguage = linkClosure->LinkerLanguage; if (linkLanguage.empty()) { cmSystemTools::Error( "CMake can not determine linker language for target: ", @@ -2794,6 +2918,19 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::vector<std::string> libVec; std::vector<std::string> vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec); + if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(), + "CUDA") != linkClosure->Languages.end()) { + switch (this->CudaOptions[config]->GetCudaRuntime()) { + case cmVisualStudioGeneratorOptions::CudaRuntimeStatic: + libVec.push_back("cudart_static.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeShared: + libVec.push_back("cudart.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeNone: + break; + } + } std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; standardLibsVar += "_STANDARD_LIBRARIES"; @@ -3132,6 +3269,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteClOptions(*i, includes); // output rc compile flags <ResourceCompile></ResourceCompile> this->WriteRCOptions(*i, includes); + this->WriteCudaOptions(*i, includes); this->WriteMasmOptions(*i, includes); this->WriteNasmOptions(*i, includes); } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 0ebb4e4..52d5550 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -98,6 +98,10 @@ private: bool ComputeRcOptions(std::string const& config); void WriteRCOptions(std::string const& config, std::vector<std::string> const& includes); + bool ComputeCudaOptions(); + bool ComputeCudaOptions(std::string const& config); + void WriteCudaOptions(std::string const& config, + std::vector<std::string> const& includes); bool ComputeMasmOptions(); bool ComputeMasmOptions(std::string const& config); void WriteMasmOptions(std::string const& config, @@ -150,6 +154,7 @@ private: typedef std::map<std::string, Options*> OptionsMap; OptionsMap ClOptions; OptionsMap RcOptions; + OptionsMap CudaOptions; OptionsMap MasmOptions; OptionsMap NasmOptions; OptionsMap LinkOptions; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index dfe5ce6..1ca6b9c 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -43,6 +43,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( @@ -67,6 +69,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) @@ -81,6 +85,13 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) } } +void cmVisualStudioGeneratorOptions::ClearTables() +{ + for (int i = 0; i < FlagTableCount; ++i) { + this->FlagTable[i] = CM_NULLPTR; + } +} + void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() { // Exception handling is on by default because the platform file has @@ -176,6 +187,78 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const return false; } +cmVisualStudioGeneratorOptions::CudaRuntime +cmVisualStudioGeneratorOptions::GetCudaRuntime() const +{ + std::map<std::string, FlagValue>::const_iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string const& cudaRuntime = i->second[0]; + if (cudaRuntime == "Static") { + return CudaRuntimeStatic; + } + if (cudaRuntime == "Shared") { + return CudaRuntimeShared; + } + if (cudaRuntime == "None") { + return CudaRuntimeNone; + } + } + // nvcc default is static + return CudaRuntimeStatic; +} + +void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() +{ + // Extract temporary values stored by our flag table. + FlagValue arch = this->TakeFlag("cmake-temp-arch"); + FlagValue code = this->TakeFlag("cmake-temp-code"); + FlagValue gencode = this->TakeFlag("cmake-temp-gencode"); + + // No -code allowed without -arch. + if (arch.empty()) { + code.clear(); + } + + if (arch.empty() && gencode.empty()) { + return; + } + + // Create a CodeGeneration field with [arch],[code] syntax in each entry. + // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`. + FlagValue& result = this->FlagMap["CodeGeneration"]; + + // First entries for the -arch=<arch> [-code=<code>,...] pair. + if (!arch.empty()) { + std::string arch_name = arch[0]; + std::vector<std::string> codes; + if (!code.empty()) { + codes = cmSystemTools::tokenize(code[0], ","); + } + if (codes.empty()) { + codes.push_back(arch_name); + // nvcc -arch=<arch> has a special case that allows a real + // architecture to be specified instead of a virtual arch. + // It translates to -arch=<virtual> -code=<real>. + cmSystemTools::ReplaceString(arch_name, "sm_", "compute_"); + } + for (std::vector<std::string>::iterator ci = codes.begin(); + ci != codes.end(); ++ci) { + std::string entry = arch_name + "," + *ci; + result.push_back(entry); + } + } + + // Now add entries for the -gencode=<arch>,<code> pairs. + for (std::vector<std::string>::iterator ei = gencode.begin(); + ei != gencode.end(); ++ei) { + std::string entry = *ei; + cmSystemTools::ReplaceString(entry, "arch=", ""); + cmSystemTools::ReplaceString(entry, "code=", ""); + result.push_back(entry); + } +} + void cmVisualStudioGeneratorOptions::Parse(const char* flags) { // Parse the input string as a windows command line since the string @@ -209,6 +292,21 @@ void cmVisualStudioGeneratorOptions::ParseFinish() rl += this->FortranRuntimeDLL ? "DLL" : ""; this->FlagMap["RuntimeLibrary"] = rl; } + + if (this->CurrentTool == CudaCompiler) { + std::map<std::string, FlagValue>::iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string& cudaRuntime = i->second[0]; + if (cudaRuntime == "static") { + cudaRuntime = "Static"; + } else if (cudaRuntime == "shared") { + cudaRuntime = "Shared"; + } else if (cudaRuntime == "none") { + cudaRuntime = "None"; + } + } + } } void cmVisualStudioGeneratorOptions::PrependInheritedString( @@ -222,6 +320,18 @@ void cmVisualStudioGeneratorOptions::PrependInheritedString( value = "%(" + key + ") " + value; } +void cmVisualStudioGeneratorOptions::Reparse(std::string const& key) +{ + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key); + if (i == this->FlagMap.end() || i->second.size() != 1) { + return; + } + std::string const original = i->second[0]; + i->second[0] = ""; + this->UnknownFlagField = key; + this->Parse(original.c_str()); +} + void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) { // Look for Intel Fortran flags that do not map well in the flag table. @@ -248,7 +358,19 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) std::string const opts = cmOutputConverter::EscapeWindowsShellArgument( flag, cmOutputConverter::Shell_Flag_AllowMakeVariables | cmOutputConverter::Shell_Flag_VSIDE); - this->AppendFlagString("AdditionalOptions", opts); + this->AppendFlagString(this->UnknownFlagField, opts); +} + +cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag( + std::string const& key) +{ + FlagValue value; + std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key); + if (i != this->FlagMap.end()) { + value = i->second; + this->FlagMap.erase(i); + } + return value; } void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) @@ -264,6 +386,9 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( return; } const char* tag = "PreprocessorDefinitions"; + if (lang == "CUDA") { + tag = "Defines"; + } if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 8c49470..52689e0 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -26,6 +26,7 @@ public: { Compiler, ResourceCompiler, + CudaCompiler, MasmCompiler, NasmCompiler, Linker, @@ -43,12 +44,19 @@ public: // Add a table of flags. void AddTable(cmVS7FlagTable const* table); + // Clear the flag tables. + void ClearTables(); + // Store options from command line flags. void Parse(const char* flags); void ParseFinish(); void PrependInheritedString(std::string const& key); + // Parse the content of the given flag table entry again to extract + // known flags and leave the rest in the original entry. + void Reparse(std::string const& key); + // Fix the ExceptionHandling option to default to off. void FixExceptionHandlingDefault(); @@ -59,6 +67,16 @@ public: bool UsingUnicode() const; bool UsingSBCS() const; + enum CudaRuntime + { + CudaRuntimeStatic, + CudaRuntimeShared, + CudaRuntimeNone + }; + CudaRuntime GetCudaRuntime() const; + + void FixCudaCodeGeneration(); + bool IsDebug() const; bool IsWinRt() const; bool IsManaged() const; @@ -81,7 +99,11 @@ private: bool FortranRuntimeDLL; bool FortranRuntimeMT; + std::string UnknownFlagField; + virtual void StoreUnknownFlag(const char* flag); + + FlagValue TakeFlag(std::string const& key); }; #endif |