summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-properties.7.rst3
-rw-r--r--Help/prop_sf/VS_COPY_TO_OUT_DIR.rst6
-rw-r--r--Help/prop_sf/VS_INCLUDE_IN_VSIX.rst6
-rw-r--r--Help/prop_sf/VS_RESOURCE_GENERATOR.rst8
-rw-r--r--Help/release/dev/vs-advanced-source-properties.rst12
-rw-r--r--Help/release/dev/vs-csharp-support.rst13
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx209
7 files changed, 230 insertions, 27 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 5b39bed..e748cd1 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -363,8 +363,11 @@ Properties on Source Files
/prop_sf/SKIP_AUTORCC
/prop_sf/SKIP_AUTOUIC
/prop_sf/SYMBOLIC
+ /prop_sf/VS_COPY_TO_OUT_DIR
/prop_sf/VS_DEPLOYMENT_CONTENT
/prop_sf/VS_DEPLOYMENT_LOCATION
+ /prop_sf/VS_INCLUDE_IN_VSIX
+ /prop_sf/VS_RESOURCE_GENERATOR
/prop_sf/VS_SHADER_ENTRYPOINT
/prop_sf/VS_SHADER_FLAGS
/prop_sf/VS_SHADER_MODEL
diff --git a/Help/prop_sf/VS_COPY_TO_OUT_DIR.rst b/Help/prop_sf/VS_COPY_TO_OUT_DIR.rst
new file mode 100644
index 0000000..16c8d83
--- /dev/null
+++ b/Help/prop_sf/VS_COPY_TO_OUT_DIR.rst
@@ -0,0 +1,6 @@
+VS_COPY_TO_OUT_DIR
+------------------
+
+Sets the ``<CopyToOutputDirectory>`` tag for a source file in a
+Visual Studio project file. Valid values are ``Never``, ``Always``
+and ``PreserveNewest``.
diff --git a/Help/prop_sf/VS_INCLUDE_IN_VSIX.rst b/Help/prop_sf/VS_INCLUDE_IN_VSIX.rst
new file mode 100644
index 0000000..30f471d
--- /dev/null
+++ b/Help/prop_sf/VS_INCLUDE_IN_VSIX.rst
@@ -0,0 +1,6 @@
+VS_INCLUDE_IN_VSIX
+------------------
+
+Boolean property to specify if the file should be included within a VSIX
+extension package. This is needed for development of Visual Studio
+extensions.
diff --git a/Help/prop_sf/VS_RESOURCE_GENERATOR.rst b/Help/prop_sf/VS_RESOURCE_GENERATOR.rst
new file mode 100644
index 0000000..97e5aac
--- /dev/null
+++ b/Help/prop_sf/VS_RESOURCE_GENERATOR.rst
@@ -0,0 +1,8 @@
+VS_RESOURCE_GENERATOR
+---------------------
+
+This property allows to specify the resource generator to be used
+on this file. It defaults to ``PublicResXFileCodeGenerator`` if
+not set.
+
+This property only applies to C# projects.
diff --git a/Help/release/dev/vs-advanced-source-properties.rst b/Help/release/dev/vs-advanced-source-properties.rst
new file mode 100644
index 0000000..dd391e0
--- /dev/null
+++ b/Help/release/dev/vs-advanced-source-properties.rst
@@ -0,0 +1,12 @@
+vs-advanced-source-properties
+-----------------------------
+
+* The :ref:`Visual Studio Generators` for VS 2010 and above
+ learned some more source file properties:
+
+ - :prop_sf:`VS_RESOURCE_GENERATOR` (C# only): allows setting the resource
+ generator
+ - :prop_sf:`VS_COPY_TO_OUT_DIR`: parameter to set if file should be copied
+ to output directory (values: ``Never``, ``Always``, ``PreserveNewest``)
+ - :prop_sf:`VS_INCLUDE_IN_VSIX`: boolean property to include file include
+ Visual Studio extension package
diff --git a/Help/release/dev/vs-csharp-support.rst b/Help/release/dev/vs-csharp-support.rst
index 26d8574..46b235a 100644
--- a/Help/release/dev/vs-csharp-support.rst
+++ b/Help/release/dev/vs-csharp-support.rst
@@ -19,7 +19,16 @@ vs-native-csharp-support
that specifically targets C# contains ``CSharp`` as a part of
their names.
-* More finetuning of C# targets can be done using target
- properties. Specifically the Visual Studio related target
+* More finetuning of C# targets can be done using target and source
+ file properties. Specifically the Visual Studio related target
properties (``VS_*``) are worth a look (for setting toolset
versions, root namespaces, assembly icons, ...).
+
+* **Auto-"linking"** in .csproj files: In C#/.NET development with
+ Visual Studio there is a number of visual editors used which
+ generate code. Both the generated files and the ones edited
+ with the UI are connected in the ``.csproj`` file using
+ ``<DependentUpon>`` tags. If CMake finds within a C# project
+ any source file with extension ``.Designer.cs`` or ``.xaml.cs``,
+ it checks sibling files with extension ``.xaml``, ``.settings``,
+ ``.resx`` or ``.cs`` and establishes the dependency connection.
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 89380eb..2e6c19b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -610,30 +610,91 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
this->GeneratorTarget->GetResxSources(resxObjs, "");
if (!resxObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
+ std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
+ this->ConvertToWindowsSlash(srcDir);
for (std::vector<cmSourceFile const*>::const_iterator oi =
resxObjs.begin();
oi != resxObjs.end(); ++oi) {
std::string obj = (*oi)->GetFullPath();
this->WriteString("<EmbeddedResource Include=\"", 2);
this->ConvertToWindowsSlash(obj);
+ bool useRelativePath = false;
+ if (csproj == this->ProjectType && this->InSourceBuild) {
+ // If we do an in-source build and the resource file is in a
+ // subdirectory
+ // of the .csproj file, we have to use relative pathnames, otherwise
+ // visual studio does not show the file in the IDE. Sorry.
+ if (obj.find(srcDir) == 0) {
+ obj = this->ConvertPath(obj, true);
+ this->ConvertToWindowsSlash(obj);
+ useRelativePath = true;
+ }
+ }
(*this->BuildFileStream) << obj << "\">\n";
- this->WriteString("<DependentUpon>", 3);
- std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
-
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
- if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
- // Handle variant of VS_GLOBAL_<variable> for RootNamespace.
- this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
- (*this->BuildFileStream) << "$(RootNamespace).";
+ if (csproj != this->ProjectType) {
+ this->WriteString("<DependentUpon>", 3);
+ std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
+ (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+
+ for (std::vector<std::string>::const_iterator i =
+ this->Configurations.begin();
+ i != this->Configurations.end(); ++i) {
+ this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
+ if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
+ // Handle variant of VS_GLOBAL_<variable> for RootNamespace.
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
+ (*this->BuildFileStream) << "$(RootNamespace).";
+ }
+ (*this->BuildFileStream) << "%(Filename)";
+ (*this->BuildFileStream) << ".resources";
+ (*this->BuildFileStream) << "</LogicalName>\n";
+ }
+ } else {
+ std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ this->ConvertToWindowsSlash(binDir);
+ // If the resource was NOT added using a relative path (which should
+ // be the default), we have to provide a link here
+ if (!useRelativePath) {
+ std::string link;
+ if (obj.find(srcDir) == 0) {
+ link = obj.substr(srcDir.length() + 1);
+ } else if (obj.find(binDir) == 0) {
+ link = obj.substr(binDir.length() + 1);
+ } else {
+ link = cmsys::SystemTools::GetFilenameName(obj);
+ }
+ if (!link.empty()) {
+ this->WriteString("<Link>", 3);
+ (*this->BuildFileStream) << link << "</Link>\n";
+ }
+ }
+ // Determine if this is a generated resource from a .Designer.cs file
+ std::string designerResource =
+ cmSystemTools::GetFilenamePath((*oi)->GetFullPath()) + "/" +
+ cmSystemTools::GetFilenameWithoutLastExtension(
+ (*oi)->GetFullPath()) +
+ ".Designer.cs";
+ if (cmsys::SystemTools::FileExists(designerResource)) {
+ std::string generator = "PublicResXFileCodeGenerator";
+ if (const char* g = (*oi)->GetProperty("VS_RESOURCE_GENERATOR")) {
+ generator = g;
+ }
+ this->WriteString("<Generator>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(generator)
+ << "</Generator>\n";
+ if (designerResource.find(srcDir) == 0) {
+ designerResource = designerResource.substr(srcDir.length() + 1);
+ } else if (designerResource.find(binDir) == 0) {
+ designerResource = designerResource.substr(binDir.length() + 1);
+ } else {
+ designerResource =
+ cmsys::SystemTools::GetFilenameName(designerResource);
+ }
+ this->ConvertToWindowsSlash(designerResource);
+ this->WriteString("<LastGenOutput>", 3);
+ (*this->BuildFileStream) << designerResource << "</LastGenOutput>\n";
}
- (*this->BuildFileStream) << "%(Filename)";
- (*this->BuildFileStream) << ".resources";
- (*this->BuildFileStream) << "</LogicalName>\n";
}
this->WriteString("</EmbeddedResource>\n", 2);
@@ -661,6 +722,24 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
}
this->WriteSource(xamlType, *oi, ">\n");
+ if (csproj == this->ProjectType && !this->InSourceBuild) {
+ // add <Link> tag to written XAML source if necessary
+ const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
+ const std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ std::string link;
+ if (obj.find(srcDir) == 0) {
+ link = obj.substr(srcDir.length() + 1);
+ } else if (obj.find(binDir) == 0) {
+ link = obj.substr(binDir.length() + 1);
+ } else {
+ link = cmsys::SystemTools::GetFilenameName(obj);
+ }
+ if (!link.empty()) {
+ this->ConvertToWindowsSlash(link);
+ this->WriteString("<Link>", 3);
+ (*this->BuildFileStream) << link << "</Link>\n";
+ }
+ }
this->WriteString("<SubType>Designer</SubType>\n", 3);
this->WriteString("</", 2);
(*this->BuildFileStream) << xamlType << ">\n";
@@ -1348,7 +1427,12 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
std::string shaderEntryPoint;
std::string shaderModel;
std::string shaderAdditionalFlags;
+ std::string settingsGenerator;
+ std::string settingsLastGenOutput;
std::string sourceLink;
+ std::string subType;
+ std::string copyToOutDir;
+ std::string includeInVsix;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
if (csproj == this->ProjectType) {
// EVERY extra source file must have a <Link>, otherwise it might not
@@ -1405,6 +1489,28 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
tool = "XML";
} else if (ext == "natvis") {
tool = "Natvis";
+ } else if (ext == "settings") {
+ // remove path to current source dir (if files are in current source dir)
+ if (!sourceLink.empty()) {
+ settingsLastGenOutput = sourceLink;
+ } else {
+ settingsLastGenOutput = sf->GetFullPath();
+ }
+ std::size_t pos = settingsLastGenOutput.find(".settings");
+ settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
+ settingsGenerator = "SettingsSingleFileGenerator";
+ toolHasSettings = true;
+ } else if (ext == "vsixmanifest") {
+ subType = "Designer";
+ }
+ if (const char* c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
+ copyToOutDir = c;
+ toolHasSettings = true;
+ }
+ if (sf->GetPropertyAsBool("VS_INCLUDE_IN_VSIX")) {
+ includeInVsix = "True";
+ tool = "Content";
+ toolHasSettings = true;
}
if (this->NsightTegra) {
@@ -1495,10 +1601,35 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
(*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
<< "</AdditionalOptions>\n";
}
+ if (!settingsGenerator.empty()) {
+ this->WriteString("<Generator>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
+ << "</Generator>\n";
+ }
+ if (!settingsLastGenOutput.empty()) {
+ this->WriteString("<LastGenOutput>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
+ << "</LastGenOutput>\n";
+ }
if (!sourceLink.empty()) {
this->WriteString("<Link>", 3);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
}
+ if (!subType.empty()) {
+ this->WriteString("<SubType>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ }
+ if (!copyToOutDir.empty()) {
+ this->WriteString("<CopyToOutputDirectory>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
+ << "</CopyToOutputDirectory>\n";
+ }
+ if (!includeInVsix.empty()) {
+ this->WriteString("<IncludeInVSIX>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
+ << "</IncludeInVSIX>\n";
+ }
+
this->WriteString("</", 2);
(*this->BuildFileStream) << tool << ">\n";
} else {
@@ -1540,12 +1671,6 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
}
}
- if (csproj == this->ProjectType && this->InSourceBuild) {
- std::string srcdir = this->Makefile->GetCurrentSourceDirectory();
- if (sourceFile.find(srcdir) != std::string::npos) {
- sourceFile = sourceFile.substr(srcdir.size() + 1);
- }
- }
this->ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
(*this->BuildFileStream) << tool << " Include=\""
@@ -1815,9 +1940,43 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
sourceFileTags["Link"] = link;
}
}
- //
- // NOTE: in future commits additional props will be added!
- //
+ // check if file is a generated .Designer.cs or .xaml.cs file
+ // to add additional necessary tags
+ const std::string fileExtension =
+ cmsys::SystemTools::GetFilenameExtension(f);
+ if (fileExtension == ".Designer.cs" || fileExtension == ".xaml.cs") {
+ f = f.substr(0, f.length() - fileExtension.length());
+ if (sourceFileTags.find("Link") == sourceFileTags.end() &&
+ !this->InSourceBuild) {
+ // add link fallback
+ sourceFileTags["Link"] =
+ cmsys::SystemTools::GetFilenameName(f) + fileExtension;
+ }
+ std::vector<std::string> extensions;
+ extensions.push_back(".resx");
+ extensions.push_back(".settings");
+ extensions.push_back(".xaml");
+ extensions.push_back(".cs");
+ std::string dependencyExtension;
+ for (std::vector<std::string>::iterator i = extensions.begin();
+ i != extensions.end(); ++i) {
+ if (cmsys::SystemTools::FileExists(f + *i)) {
+ dependencyExtension = *i;
+ // There should never be more than one match. Otherwise
+ // one cannot tell on which match the file depends.
+ break;
+ }
+ }
+ if (dependencyExtension == ".resx") {
+ sourceFileTags["DesignTime"] = "True";
+ sourceFileTags["AutoGen"] = "True";
+ } else if (dependencyExtension == ".settings") {
+ sourceFileTags["DesignTimeSharedInput"] = "True";
+ sourceFileTags["AutoGen"] = "True";
+ }
+ sourceFileTags["DependentUpon"] =
+ cmsys::SystemTools::GetFilenameName(f) + dependencyExtension;
+ }
// write source file specific tags
if (!sourceFileTags.empty()) {
hasFlags = true;
@@ -1825,7 +1984,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
firstString = "";
for (CsPropMap::const_iterator i = sourceFileTags.begin();
i != sourceFileTags.end(); ++i) {
- this->WriteString("<", 2);
+ this->WriteString("<", 3);
(*this->BuildFileStream)
<< i->first << ">" << cmVS10EscapeXML(i->second) << "</" << i->first
<< ">\n";