in Source/cmVisualStudio10TargetGenerator.cxx [320:831]
void cmVisualStudio10TargetGenerator::Generate()
{
const std::string ProjectFileExtension =
computeProjectFileExtension(this->GeneratorTarget);
if (ProjectFileExtension == ".vcxproj") {
this->ProjectType = vcxproj;
this->Managed = false;
} else if (ProjectFileExtension == ".csproj") {
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
std::string message = "The C# target \"" +
this->GeneratorTarget->GetName() +
"\" is of type STATIC_LIBRARY. This is discouraged (and may be "
"disabled in future). Make it a SHARED library instead.";
this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
}
this->ProjectType = csproj;
this->Managed = true;
}
if (this->Android &&
this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
!this->GeneratorTarget->Target->IsAndroidGuiExecutable()) {
this->GlobalGenerator->AddAndroidExecutableWarning(this->Name);
}
// Tell the global generator the name of the project file
this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
this->Name);
this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
ProjectFileExtension);
this->DotNetHintReferences.clear();
this->AdditionalUsingDirectories.clear();
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
if (!this->ComputeClOptions()) {
return;
}
if (!this->ComputeRcOptions()) {
return;
}
if (!this->ComputeCudaOptions()) {
return;
}
if (!this->ComputeCudaLinkOptions()) {
return;
}
if (!this->ComputeMasmOptions()) {
return;
}
if (!this->ComputeNasmOptions()) {
return;
}
if (!this->ComputeLinkOptions()) {
return;
}
if (!this->ComputeLibOptions()) {
return;
}
}
std::string path =
cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
this->Name, ProjectFileExtension);
cmGeneratedFileStream BuildFileStream(path);
const std::string PathToProjectFile = path;
BuildFileStream.SetCopyIfDifferent(true);
// Write the encoding header into the file
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
BuildFileStream.write(magic, 3);
BuildFileStream << "<?xml version=\"1.0\" encoding=\""
<< this->GlobalGenerator->Encoding() << "\"?>";
{
Elem e0(BuildFileStream, "Project");
e0.Attribute("DefaultTargets", "Build");
const char* toolsVersion = this->GlobalGenerator->GetToolsVersion();
if (this->GlobalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS12 &&
this->GlobalGenerator->TargetsWindowsCE()) {
toolsVersion = "4.0";
}
e0.Attribute("ToolsVersion", toolsVersion);
e0.Attribute("xmlns",
"http://schemas.microsoft.com/developer/msbuild/2003");
if (this->NsightTegra) {
Elem e1(e0, "PropertyGroup");
e1.Attribute("Label", "NsightTegraProject");
const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
if (nsightTegraMajorVersion >= 2) {
if (nsightTegraMajorVersion > 3 ||
(nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
e1.Element("NsightTegraProjectRevisionNumber", "11");
} else {
// Nsight Tegra 2.0 uses project revision 9.
e1.Element("NsightTegraProjectRevisionNumber", "9");
}
// Tell newer versions to upgrade silently when loading.
e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
} else {
// Require Nsight Tegra 1.6 for JCompile support.
e1.Element("NsightTegraProjectRevisionNumber", "7");
}
}
if (const char* hostArch =
this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
Elem e1(e0, "PropertyGroup");
e1.Element("PreferredToolArchitecture", hostArch);
}
if (this->ProjectType != csproj) {
this->WriteProjectConfigurations(e0);
}
{
Elem e1(e0, "PropertyGroup");
e1.Attribute("Label", "Globals");
e1.Element("ProjectGuid", "{" + this->GUID + "}");
if ((this->MSTools || this->Android) &&
this->GeneratorTarget->IsInBuildSystem()) {
this->WriteApplicationTypeSettings(e1);
this->VerifyNecessaryFiles();
}
cmValue vsProjectTypes =
this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
if (vsProjectTypes) {
const char* tagName = "ProjectTypes";
if (this->ProjectType == csproj) {
tagName = "ProjectTypeGuids";
}
e1.Element(tagName, *vsProjectTypes);
}
cmValue vsProjectName =
this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
cmValue vsLocalPath =
this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
cmValue vsProvider =
this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
if (vsProjectName && vsLocalPath && vsProvider) {
e1.Element("SccProjectName", *vsProjectName);
e1.Element("SccLocalPath", *vsLocalPath);
e1.Element("SccProvider", *vsProvider);
cmValue vsAuxPath =
this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
if (vsAuxPath) {
e1.Element("SccAuxPath", *vsAuxPath);
}
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
e1.Element("WinMDAssembly", "true");
}
cmValue vsGlobalKeyword =
this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
if (!vsGlobalKeyword) {
if (this->GlobalGenerator->TargetsAndroid()) {
e1.Element("Keyword", "Android");
} else {
e1.Element("Keyword", "Win32Proj");
}
} else {
e1.Element("Keyword", *vsGlobalKeyword);
}
cmValue vsGlobalRootNamespace =
this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
if (vsGlobalRootNamespace) {
e1.Element("RootNamespace", *vsGlobalRootNamespace);
}
if (!this->BuildAsX) {
e1.Element("Platform", this->Platform);
}
e1.Element("Platform", this->Platform);
cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
e1.Element("ProjectName", projLabel ? projLabel : this->Name);
{
cm::optional<std::string> targetFramework;
cm::optional<std::string> targetFrameworkVersion;
cm::optional<std::string> targetFrameworkIdentifier;
cm::optional<std::string> targetFrameworkTargetsVersion;
if (cmValue tf =
this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) {
targetFramework = *tf;
} else if (cmValue vstfVer = this->GeneratorTarget->GetProperty(
"VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
// FIXME: Someday, add a deprecation warning for VS_* property.
targetFrameworkVersion = *vstfVer;
} else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
"DOTNET_TARGET_FRAMEWORK_VERSION")) {
targetFrameworkVersion = *tfVer;
} else if (this->ProjectType == csproj) {
targetFrameworkVersion =
this->GlobalGenerator->GetTargetFrameworkVersion();
}
if (this->ProjectType == vcxproj &&
this->GlobalGenerator->TargetsWindowsCE()) {
e1.Element("EnableRedirectPlatform", "true");
e1.Element("RedirectPlatformValue", this->Platform);
}
if (this->ProjectType == csproj) {
if (this->GlobalGenerator->TargetsWindowsCE()) {
// FIXME: These target VS_TARGET_FRAMEWORK* target properties
// are undocumented settings only ever supported for WinCE.
// We need a better way to control these in general.
if (cmValue tfId = this->GeneratorTarget->GetProperty(
"VS_TARGET_FRAMEWORK_IDENTIFIER")) {
targetFrameworkIdentifier = *tfId;
}
if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty(
"VS_TARGET_FRAMEWORKS_TARGET_VERSION")) {
targetFrameworkTargetsVersion = *tfTargetsVer;
}
}
if (!targetFrameworkIdentifier) {
targetFrameworkIdentifier =
this->GlobalGenerator->GetTargetFrameworkIdentifier();
}
if (!targetFrameworkTargetsVersion) {
targetFrameworkTargetsVersion =
this->GlobalGenerator->GetTargetFrameworkTargetsVersion();
}
}
if (targetFramework) {
if (targetFramework->find(';') != std::string::npos) {
e1.Element("TargetFrameworks", *targetFramework);
} else {
e1.Element("TargetFramework", *targetFramework);
}
}
if (targetFrameworkVersion) {
e1.Element("TargetFrameworkVersion", *targetFrameworkVersion);
}
if (targetFrameworkIdentifier) {
e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier);
}
if (targetFrameworkTargetsVersion) {
e1.Element("TargetFrameworkTargetsVersion",
*targetFrameworkTargetsVersion);
}
if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
.empty()) {
e1.Element(
"CudaToolkitCustomDir",
this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
this->GlobalGenerator->GetPlatformToolsetCudaNvccSubdirString());
}
}
// Disable the project upgrade prompt that is displayed the first time a
// project using an older toolset version is opened in a newer version of
// the IDE (respected by VS 2013 and above).
if (this->GlobalGenerator->GetVersion() >=
cmGlobalVisualStudioGenerator::VS12) {
e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
}
if (const char* vcTargetsPath =
this->GlobalGenerator->GetCustomVCTargetsPath()) {
e1.Element("VCTargetsPath", vcTargetsPath);
}
std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
for (std::string const& keyIt : keys) {
static const cm::string_view prefix = "VS_GLOBAL_";
if (!cmHasPrefix(keyIt, prefix))
continue;
cm::string_view globalKey =
cm::string_view(keyIt).substr(prefix.length());
// Skip invalid or separately-handled properties.
if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
continue;
}
cmValue value = this->GeneratorTarget->GetProperty(keyIt);
if (!value)
continue;
e1.Element(globalKey, *value);
}
if (this->Managed) {
if (this->LocalGenerator->GetVersion() >=
cmGlobalVisualStudioGenerator::VS17) {
e1.Element("ManagedAssembly", "true");
}
std::string outputType;
switch (this->GeneratorTarget->GetType()) {
case cmStateEnums::OBJECT_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
outputType = "Library";
break;
case cmStateEnums::MODULE_LIBRARY:
outputType = "Module";
break;
case cmStateEnums::EXECUTABLE: {
auto const win32 =
this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE");
if (win32.find("$<") != std::string::npos) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Target \"", this->GeneratorTarget->GetName(),
"\" has a generator expression in its WIN32_EXECUTABLE "
"property. This is not supported on managed executables."));
return;
}
if (cmIsOn(win32)) {
outputType = "WinExe";
} else {
outputType = "Exe";
}
} break;
case cmStateEnums::UTILITY:
case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::GLOBAL_TARGET:
outputType = "Utility";
break;
case cmStateEnums::UNKNOWN_LIBRARY:
break;
}
e1.Element("OutputType", outputType);
e1.Element("AppDesignerFolder", "Properties");
}
}
switch (this->ProjectType) {
case vcxproj: {
std::string const& props =
this->GlobalGenerator->GetPlatformToolsetVersionProps();
if (!props.empty()) {
Elem(e0, "Import").Attribute("Project", props);
}
Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
} break;
case csproj:
Elem(e0, "Import")
.Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
.Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
break;
}
this->WriteProjectConfigurationValues(e0);
if (this->ProjectType == vcxproj) {
Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
}
{
Elem e1(e0, "ImportGroup");
e1.Attribute("Label", "ExtensionSettings");
e1.SetHasElements();
if (this->GlobalGenerator->IsCudaEnabled()) {
auto customDir =
this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
this->GlobalGenerator
->GetPlatformToolsetCudaVSIntegrationSubdirString() +
"extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
this->GlobalGenerator->GetPlatformToolsetCuda() +
".props");
}
if (this->GlobalGenerator->IsMasmEnabled()) {
Elem(e1, "Import")
.Attribute("Project",
"$(VCTargetsPath)\\BuildCustomizations\\masm.props");
}
if (this->GlobalGenerator->IsNasmEnabled()) {
// Always search in the standard modules location.
std::string propsTemplate =
GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
std::string propsLocal =
cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
ConvertToWindowsSlash(propsLocal);
this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
true);
Elem(e1, "Import").Attribute("Project", propsLocal);
}
}
{
Elem e1(e0, "ImportGroup");
e1.Attribute("Label", "PropertySheets");
std::string props;
switch (this->ProjectType) {
case vcxproj:
props = VS10_CXX_USER_PROPS;
break;
case csproj:
props = VS10_CSharp_USER_PROPS;
break;
}
if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
props = *p;
}
if (!props.empty()) {
ConvertToWindowsSlash(props);
Elem(e1, "Import")
.Attribute("Project", props)
.Attribute("Condition", "exists('" + props + "')")
.Attribute("Label", "LocalAppDataPlatform");
}
this->WritePlatformExtensions(e1);
}
this->WriteDotNetDocumentationFile(e0);
Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
this->WriteWinRTPackageCertificateKeyFile(e0);
this->WritePathAndIncrementalLinkOptions(e0);
this->WriteCEDebugProjectConfigurationValues(e0);
this->WriteItemDefinitionGroups(e0);
this->WriteCustomCommands(e0);
this->WriteAllSources(e0);
this->WriteDotNetReferences(e0);
this->WritePackageReferences(e0);
this->WriteImports(e0);
this->WriteEmbeddedResourceGroup(e0);
this->WriteXamlFilesGroup(e0);
this->WriteWinRTReferences(e0);
this->WriteProjectReferences(e0);
this->WriteSDKReferences(e0);
switch (this->ProjectType) {
case vcxproj:
Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
break;
case csproj:
if (this->GlobalGenerator->TargetsWindowsCE()) {
Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS);
} else {
Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
}
break;
}
this->WriteTargetSpecificReferences(e0);
{
Elem e1(e0, "ImportGroup");
e1.Attribute("Label", "ExtensionTargets");
e1.SetHasElements();
this->WriteTargetsFileReferences(e1);
if (this->GlobalGenerator->IsCudaEnabled()) {
auto customDir =
this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
std::string cudaPath = customDir.empty()
? "$(VCTargetsPath)\\BuildCustomizations\\"
: customDir +
this->GlobalGenerator
->GetPlatformToolsetCudaVSIntegrationSubdirString() +
"extras\\visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
std::move(cudaPath) + "CUDA " +
this->GlobalGenerator->GetPlatformToolsetCuda() +
".targets");
}
if (this->GlobalGenerator->IsMasmEnabled()) {
Elem(e1, "Import")
.Attribute("Project",
"$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
}
if (this->GlobalGenerator->IsNasmEnabled()) {
std::string nasmTargets =
GetCMakeFilePath("Templates/MSBuild/nasm.targets");
Elem(e1, "Import").Attribute("Project", nasmTargets);
}
}
if (this->ProjectType == vcxproj && this->HaveCustomCommandDepfile) {
std::string depfileTargets =
GetCMakeFilePath("Templates/MSBuild/CustomBuildDepFile.targets");
Elem(e0, "Import").Attribute("Project", depfileTargets);
}
if (this->ProjectType == csproj) {
for (std::string const& c : this->Configurations) {
Elem e1(e0, "PropertyGroup");
e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
e1.SetHasElements();
this->WriteEvents(e1, c);
}
// make sure custom commands are executed before build (if necessary)
{
Elem e1(e0, "PropertyGroup");
std::ostringstream oss;
oss << "\n";
for (std::string const& i : this->CSharpCustomCommandNames) {
oss << " " << i << ";\n";
}
oss << " "
<< "$(BuildDependsOn)\n";
e1.Element("BuildDependsOn", oss.str());
}
}
}
if (BuildFileStream.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
}
// The groups are stored in a separate file for VS 10
this->WriteGroups();
}