summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalVisualStudio10Generator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalVisualStudio10Generator.cxx')
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx373
1 files changed, 360 insertions, 13 deletions
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index e27615a..ca98e6c 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -10,14 +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.
@@ -94,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;
@@ -112,7 +124,10 @@ 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;
this->Version = VS10;
}
@@ -153,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)
{
@@ -168,36 +190,119 @@ 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;
}
bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
std::string const& ts, cmMakefile* mf)
{
- if (ts.find_first_of(",=") != ts.npos) {
- std::ostringstream e;
- /* clang-format off */
- e <<
- "Generator\n"
- " " << this->GetName() << "\n"
- "does not recognize the toolset\n"
- " " << ts << "\n"
- "that was specified.";
- /* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
- return false;
+ std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
+ std::vector<std::string>::const_iterator fi = fields.begin();
+ if (fi == fields.end()) {
+ return true;
+ }
+
+ // The first field may be the VS platform toolset.
+ if (fi->find('=') == fi->npos) {
+ this->GeneratorToolset = *fi;
+ ++fi;
+ }
+
+ std::set<std::string> handled;
+
+ // The rest of the fields must be key=value pairs.
+ for (; fi != fields.end(); ++fi) {
+ std::string::size_type pos = fi->find('=');
+ if (pos == fi->npos) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains a field after the first ',' with no '='."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ std::string const key = fi->substr(0, pos);
+ std::string const value = fi->substr(pos + 1);
+ if (!handled.insert(key).second) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains duplicate field key '" << key << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ if (!this->ProcessGeneratorToolsetField(key, value)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset specification\n"
+ " " << ts << "\n"
+ "that contains invalid field '" << *fi << "'."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
}
- this->GeneratorToolset = ts;
return true;
}
+bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
+ std::string const& key, std::string const& value)
+{
+ if (key == "cuda") {
+ this->GeneratorToolsetCuda = value;
+ return true;
+ }
+ return false;
+}
+
bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
{
if (this->SystemName == "Windows") {
@@ -354,6 +459,16 @@ void cmGlobalVisualStudio10Generator::Generate()
void cmGlobalVisualStudio10Generator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
+ for (std::vector<std::string>::const_iterator it = lang.begin();
+ it != lang.end(); ++it) {
+ if (*it == "ASM_NASM") {
+ this->NasmEnabled = true;
+ }
+ if (*it == "CUDA") {
+ this->CudaEnabled = true;
+ }
+ }
+ this->AddPlatformDefinitions(mf);
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
@@ -388,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)) {
@@ -442,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,
@@ -656,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(
@@ -663,3 +1005,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable;
}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
+{
+ return this->DefaultNasmFlagTable;
+}