diff options
Diffstat (limited to 'Source/cmVisualStudio10TargetGenerator.cxx')
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 478 |
1 files changed, 242 insertions, 236 deletions
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8da113e..ec7fe96 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -6,6 +6,7 @@ #include <set> #include <cm/memory> +#include <cm/string_view> #include <cm/vector> #include "windows.h" @@ -22,6 +23,7 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVisualStudioGeneratorOptions.h" @@ -61,10 +63,10 @@ struct cmVisualStudio10TargetGenerator::Elem this->StartElement(); } Elem(const Elem&) = delete; - Elem(Elem& par, const std::string& tag) + Elem(Elem& par, cm::string_view tag) : S(par.S) , Indent(par.Indent + 1) - , Tag(tag) + , Tag(std::string(tag)) { par.SetHasElements(); this->StartElement(); @@ -78,22 +80,22 @@ struct cmVisualStudio10TargetGenerator::Elem } std::ostream& WriteString(const char* line); void StartElement() { this->WriteString("<") << this->Tag; } - void Element(const std::string& tag, const std::string& val) + void Element(cm::string_view tag, std::string val) { - Elem(*this, tag).Content(val); + Elem(*this, tag).Content(std::move(val)); } - Elem& Attribute(const char* an, const std::string& av) + Elem& Attribute(const char* an, std::string av) { - this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\""; + this->S << " " << an << "=\"" << cmVS10EscapeAttr(std::move(av)) << "\""; return *this; } - void Content(const std::string& val) + void Content(std::string val) { if (!this->HasContent) { this->S << ">"; this->HasContent = true; } - this->S << cmVS10EscapeXML(val); + this->S << cmVS10EscapeXML(std::move(val)); } ~Elem() { @@ -556,10 +558,11 @@ void cmVisualStudio10TargetGenerator::Generate() std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::string const& keyIt : keys) { - static const char* prefix = "VS_GLOBAL_"; - if (keyIt.find(prefix) != 0) + static const cm::string_view prefix = "VS_GLOBAL_"; + if (!cmHasPrefix(keyIt, prefix)) continue; - std::string globalKey = keyIt.substr(strlen(prefix)); + 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") { @@ -790,21 +793,14 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) for (std::string const& ri : packageReferences) { size_t versionIndex = ri.find_last_of('_'); if (versionIndex != std::string::npos) { - WritePackageReference(e1, ri.substr(0, versionIndex), - ri.substr(versionIndex + 1)); + Elem e2(e1, "PackageReference"); + e2.Attribute("Include", ri.substr(0, versionIndex)); + e2.Attribute("Version", ri.substr(versionIndex + 1)); } } } } -void cmVisualStudio10TargetGenerator::WritePackageReference( - Elem& e1, std::string const& ref, std::string const& version) -{ - Elem e2(e1, "PackageReference"); - e2.Attribute("Include", ref); - e2.Attribute("Version", version); -} - void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) { std::vector<std::string> references; @@ -814,17 +810,15 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) } cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); for (auto const& i : props.GetList()) { - if (i.first.find("VS_DOTNET_REFERENCE_") == 0) { - std::string name = i.first.substr(20); - if (!name.empty()) { - std::string path = i.second; - if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; - } - ConvertToWindowsSlash(path); - this->DotNetHintReferences[""].push_back( - DotNetHintReference(name, path)); + static const cm::string_view vsDnRef = "VS_DOTNET_REFERENCE_"; + if (cmHasPrefix(i.first, vsDnRef)) { + std::string path = i.second; + if (!cmsys::SystemTools::FileIsFullPath(path)) { + path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; } + ConvertToWindowsSlash(path); + this->DotNetHintReferences[""].emplace_back( + DotNetHintReference(i.first.substr(vsDnRef.length()), path)); } } if (!references.empty() || !this->DotNetHintReferences.empty()) { @@ -837,7 +831,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) cmsys::SystemTools::GetFilenameWithoutLastExtension(ri); std::string path = ri; ConvertToWindowsSlash(path); - this->DotNetHintReferences[""].push_back( + this->DotNetHintReferences[""].emplace_back( DotNetHintReference(name, path)); } else { this->WriteDotNetReference(e1, ri, "", ""); @@ -883,11 +877,10 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0) { - const char* imports = + cmProp imports = this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT"); if (imports) { - std::vector<std::string> argsSplit = - cmExpandedList(std::string(imports), false); + std::vector<std::string> argsSplit = cmExpandedList(*imports, false); for (auto& path : argsSplit) { if (!cmsys::SystemTools::FileIsFullPath(path)) { path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; @@ -910,12 +903,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( CustomTags tags; cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); for (const auto& i : props.GetList()) { - if (i.first.find(refPropFullPrefix) == 0) { - std::string refTag = i.first.substr(refPropFullPrefix.length()); - std::string refVal = i.second; - if (!refTag.empty() && !refVal.empty()) { - tags[refTag] = refVal; - } + if (cmHasPrefix(i.first, refPropFullPrefix) && !i.second.empty()) { + tags[i.first.substr(refPropFullPrefix.length())] = i.second; } } for (auto const& tag : tags) { @@ -952,7 +941,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) // 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) { + if (cmHasPrefix(obj, srcDir)) { obj = this->ConvertPath(obj, true); ConvertToWindowsSlash(obj); useRelativePath = true; @@ -981,17 +970,11 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) // 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 { + std::string link = this->GetCSharpSourceLink(oi); + if (link.empty()) { link = cmsys::SystemTools::GetFilenameName(obj); } - if (!link.empty()) { - e2.Element("Link", link); - } + e2.Element("Link", link); } // Determine if this is a generated resource from a .Designer.cs file std::string designerResource = @@ -1005,10 +988,10 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) } if (!generator.empty()) { e2.Element("Generator", generator); - if (designerResource.find(srcDir) == 0) { - designerResource = designerResource.substr(srcDir.length() + 1); - } else if (designerResource.find(binDir) == 0) { - designerResource = designerResource.substr(binDir.length() + 1); + if (cmHasPrefix(designerResource, srcDir)) { + designerResource.erase(0, srcDir.length()); + } else if (cmHasPrefix(designerResource, binDir)) { + designerResource.erase(0, binDir.length()); } else { designerResource = cmsys::SystemTools::GetFilenameName(designerResource); @@ -1019,11 +1002,12 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) } const cmPropertyMap& props = oi->GetProperties(); for (const std::string& p : props.GetKeys()) { - static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.find(propNamePrefix) == 0) { - std::string tagName = p.substr(propNamePrefix.length()); + static const cm::string_view propNamePrefix = "VS_CSHARP_"; + if (cmHasPrefix(p, propNamePrefix)) { + cm::string_view tagName = + cm::string_view(p).substr(propNamePrefix.length()); if (!tagName.empty()) { - std::string value = props.GetPropertyValue(p); + const std::string& value = *props.GetPropertyValue(p); if (!value.empty()) { e2.Element(tagName, value); } @@ -1054,25 +1038,6 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) Elem e2(e1, xamlType); this->WriteSource(e2, oi); e2.SetHasElements(); - if (this->ProjectType == csproj && !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()) { - ConvertToWindowsSlash(link); - e2.Element("Link", link); - } - } e2.Element("SubType", "Designer"); } } @@ -1442,13 +1407,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( } else { Elem e1(e0, "ItemGroup"); Elem e2(e1, "None"); - std::string link; - this->GetCSharpSourceLink(source, link); this->WriteSource(e2, source); e2.SetHasElements(); - if (!link.empty()) { - e2.Element("Link", link); - } } for (std::string const& c : this->Configurations) { cmCustomCommandGenerator ccg(command, c, lg); @@ -1779,9 +1739,63 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, if (this->IsResxHeader(fileName)) { e2.Element("FileType", "CppForm"); } else if (this->IsXamlHeader(fileName)) { - std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); - e2.Element("DependentUpon", xamlFileName); + e2.Element("DependentUpon", + fileName.substr(0, fileName.find_last_of("."))); + } +} + +void cmVisualStudio10TargetGenerator::ParseSettingsProperty( + const char* settingsPropertyValue, ConfigToSettings& toolSettings) +{ + if (settingsPropertyValue) { + cmGeneratorExpression ge; + + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(settingsPropertyValue); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + std::vector<std::string> settings = cmExpandedList(evaluated); + for (const std::string& setting : settings) { + const std::string::size_type assignment = setting.find('='); + if (assignment != std::string::npos) { + const std::string propName = setting.substr(0, assignment); + const std::string propValue = setting.substr(assignment + 1); + + if (!propValue.empty()) { + toolSettings[config][propName] = propValue; + } + } + } + } + } +} + +bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs( + const ConfigToSettings& toolSettings, const std::string& propName) +{ + std::string firstPropValue = ""; + for (const auto& configToSettings : toolSettings) { + const std::unordered_map<std::string, std::string>& settings = + configToSettings.second; + + if (firstPropValue.empty()) { + if (settings.find(propName) != settings.end()) { + firstPropValue = settings.find(propName)->second; + } + } + + if (settings.find(propName) == settings.end()) { + return false; + } + + if (settings.find(propName)->second != firstPropValue) { + return false; + } } + + return true; } void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, @@ -1789,15 +1803,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, { bool toolHasSettings = false; const char* tool = "None"; - std::string shaderType; - std::string shaderEntryPoint; - std::string shaderModel; - std::string shaderAdditionalFlags; - std::string shaderDisableOptimizations; - std::string shaderEnableDebug; - std::string shaderObjectFileName; - std::string outputHeaderFile; - std::string variableName; std::string settingsGenerator; std::string settingsLastGenOutput; std::string sourceLink; @@ -1805,76 +1810,84 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, std::string copyToOutDir; std::string includeInVsix; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - if (this->ProjectType == csproj) { - // EVERY extra source file must have a <Link>, otherwise it might not - // be visible in Visual Studio at all. The path relative to current - // source- or binary-dir is used within the link, if the file is - // in none of these paths, it is added with the plain filename without - // any path. This means the file will show up at root-level of the csproj - // (where CMakeLists.txt etc. are). - if (!this->InSourceBuild) { - toolHasSettings = true; - std::string fullFileName = sf->GetFullPath(); - std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); - std::string binDir = this->Makefile->GetCurrentBinaryDirectory(); - if (fullFileName.find(binDir) != std::string::npos) { - sourceLink.clear(); - } else if (fullFileName.find(srcDir) != std::string::npos) { - sourceLink = fullFileName.substr(srcDir.length() + 1); - } else { - // fallback: add plain filename without any path - sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName); - } - if (!sourceLink.empty()) { - ConvertToWindowsSlash(sourceLink); - } - } + ConfigToSettings toolSettings; + for (const auto& config : this->Configurations) { + toolSettings[config]; + } + + if (this->ProjectType == csproj && !this->InSourceBuild) { + toolHasSettings = true; } if (ext == "hlsl") { tool = "FXCompile"; // Figure out the type of shader compiler to use. if (const char* st = sf->GetProperty("VS_SHADER_TYPE")) { - shaderType = st; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ShaderType"] = st; + } } // Figure out which entry point to use if any if (const char* se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) { - shaderEntryPoint = se; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["EntryPointName"] = se; + } } // Figure out which shader model to use if any if (const char* sm = sf->GetProperty("VS_SHADER_MODEL")) { - shaderModel = sm; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ShaderModel"] = sm; + } } // Figure out which output header file to use if any if (const char* ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) { - outputHeaderFile = ohf; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["HeaderFileOutput"] = ohf; + } } // Figure out which variable name to use if any if (const char* vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) { - variableName = vn; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["VariableName"] = vn; + } } // Figure out if there's any additional flags to use if (const char* saf = sf->GetProperty("VS_SHADER_FLAGS")) { - shaderAdditionalFlags = saf; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["AdditionalOptions"] = saf; + } } // Figure out if debug information should be generated if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) { - shaderEnableDebug = sed; - toolHasSettings = true; + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(sed); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + if (!evaluated.empty()) { + toolSettings[config]["EnableDebuggingInformation"] = + cmIsOn(evaluated) ? "true" : "false"; + } + } } // Figure out if optimizations should be disabled if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) { - shaderDisableOptimizations = sdo; - toolHasSettings = true; + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(sdo); + + for (const std::string& config : this->Configurations) { + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + if (!evaluated.empty()) { + toolSettings[config]["DisableOptimizations"] = + cmIsOn(evaluated) ? "true" : "false"; + } + } } if (const char* sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) { - shaderObjectFileName = sofn; - toolHasSettings = true; + for (const std::string& config : this->Configurations) { + toolSettings[config]["ObjectFileOutput"] = sofn; + } } } else if (ext == "jpg" || ext == "png") { tool = "Image"; @@ -1944,11 +1957,56 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } + if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) { + cmProp toolTargetProperty = this->GeneratorTarget->Target->GetProperty( + "VS_SOURCE_SETTINGS_" + std::string(tool)); + ConfigToSettings toolTargetSettings; + if (toolTargetProperty) { + ParseSettingsProperty(toolTargetProperty->c_str(), toolTargetSettings); + } + + ParsedToolTargetSettings[tool] = toolTargetSettings; + } + + for (const auto& configToSetting : ParsedToolTargetSettings[tool]) { + for (const auto& setting : configToSetting.second) { + toolSettings[configToSetting.first][setting.first] = setting.second; + } + } + + ParseSettingsProperty(sf->GetProperty("VS_SETTINGS"), toolSettings); + + if (!toolSettings.empty()) { + toolHasSettings = true; + } + Elem e2(e1, tool); this->WriteSource(e2, sf); if (toolHasSettings) { e2.SetHasElements(); + std::vector<std::string> writtenSettings; + for (const auto& configSettings : toolSettings) { + for (const auto& setting : configSettings.second) { + + if (std::find(writtenSettings.begin(), writtenSettings.end(), + setting.first) != writtenSettings.end()) { + continue; + } + + if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { + e2.Element(setting.first, setting.second); + writtenSettings.push_back(setting.first); + } else { + e2.WritePlatformConfigTag(setting.first, + "'$(Configuration)|$(Platform)'=='" + + configSettings.first + "|" + + this->Platform + "'", + setting.second); + } + } + } + if (!deployContent.empty()) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = @@ -1974,82 +2032,13 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } } - if (!shaderType.empty()) { - e2.Element("ShaderType", shaderType); - } - if (!shaderEntryPoint.empty()) { - e2.Element("EntryPointName", shaderEntryPoint); - } - if (!shaderModel.empty()) { - e2.Element("ShaderModel", shaderModel); - } - if (!outputHeaderFile.empty()) { - for (size_t i = 0; i != this->Configurations.size(); ++i) { - e2.WritePlatformConfigTag("HeaderFileOutput", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - outputHeaderFile); - } - } - if (!variableName.empty()) { - for (size_t i = 0; i != this->Configurations.size(); ++i) { - e2.WritePlatformConfigTag("VariableName", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - variableName); - } - } - if (!shaderEnableDebug.empty()) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(shaderEnableDebug); - - for (size_t i = 0; i != this->Configurations.size(); ++i) { - const std::string& enableDebug = - cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (!enableDebug.empty()) { - e2.WritePlatformConfigTag("EnableDebuggingInformation", - "'$(Configuration)|$(Platform)'=='" + - this->Configurations[i] + "|" + - this->Platform + "'", - cmIsOn(enableDebug) ? "true" : "false"); - } - } - } - if (!shaderDisableOptimizations.empty()) { - cmGeneratorExpression ge; - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(shaderDisableOptimizations); - for (size_t i = 0; i != this->Configurations.size(); ++i) { - const std::string& disableOptimizations = - cge->Evaluate(this->LocalGenerator, this->Configurations[i]); - if (!disableOptimizations.empty()) { - e2.WritePlatformConfigTag( - "DisableOptimizations", - "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + - "|" + this->Platform + "'", - (cmIsOn(disableOptimizations) ? "true" : "false")); - } - } - } - if (!shaderObjectFileName.empty()) { - e2.Element("ObjectFileOutput", shaderObjectFileName); - } - if (!shaderAdditionalFlags.empty()) { - e2.Element("AdditionalOptions", shaderAdditionalFlags); - } if (!settingsGenerator.empty()) { e2.Element("Generator", settingsGenerator); } if (!settingsLastGenOutput.empty()) { e2.Element("LastGenOutput", settingsLastGenOutput); } - if (!sourceLink.empty()) { - e2.Element("Link", sourceLink); - } if (!subType.empty()) { e2.Element("SubType", subType); } @@ -2102,6 +2091,20 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, ConvertToWindowsSlash(sourceFile); e2.Attribute("Include", sourceFile); + if (this->ProjectType == csproj && !this->InSourceBuild) { + // For out of source projects we have to provide a link (if not specified + // via property) for every source file (besides .cs files) otherwise they + // will not be visible in VS at all. + // First we check if the file is in a source group, then we check if the + // file path is relative to current source- or binary-dir, otherwise it is + // added with the plain filename without any path. This means the file will + // show up at root-level of the csproj (where CMakeLists.txt etc. are). + std::string link = this->GetCSharpSourceLink(sf); + if (link.empty()) + link = cmsys::SystemTools::GetFilenameName(sf->GetFullPath()); + e2.Element("Link", link); + } + ToolSource toolSource = { sf, forceRelative }; this->Tools[e2.Tag].push_back(toolSource); } @@ -2454,19 +2457,13 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } if (this->IsXamlSource(source->GetFullPath())) { const std::string& fileName = source->GetFullPath(); - std::string xamlFileName = fileName.substr(0, fileName.find_last_of(".")); - e2.Element("DependentUpon", xamlFileName); + e2.Element("DependentUpon", + fileName.substr(0, fileName.find_last_of("."))); } if (this->ProjectType == csproj) { std::string f = source->GetFullPath(); using CsPropMap = std::map<std::string, std::string>; CsPropMap sourceFileTags; - // set <Link> tag if necessary - std::string link; - this->GetCSharpSourceLink(source, link); - if (!link.empty()) { - sourceFileTags["Link"] = link; - } this->GetCSharpSourceProperties(&sf, sourceFileTags); // write source file specific tags if (!sourceFileTags.empty()) { @@ -3412,9 +3409,8 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage; std::string libflags; - this->LocalGenerator->GetStaticLibraryFlags( - libflags, cmSystemTools::UpperCase(config), linkLanguage, - this->GeneratorTarget); + this->LocalGenerator->GetStaticLibraryFlags(libflags, config, linkLanguage, + this->GeneratorTarget); if (!libflags.empty()) { Elem e2(e1, "Lib"); cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator; @@ -4845,11 +4841,11 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( if (this->ProjectType == csproj) { const cmPropertyMap& props = sf->GetProperties(); for (const std::string& p : props.GetKeys()) { - static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.find(propNamePrefix) == 0) { + static const cm::string_view propNamePrefix = "VS_CSHARP_"; + if (cmHasPrefix(p, propNamePrefix)) { std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - const std::string val = props.GetPropertyValue(p); + const std::string& val = *props.GetPropertyValue(p); if (!val.empty()) { tags[tagName] = val; } else { @@ -4869,24 +4865,34 @@ void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties( } } -void cmVisualStudio10TargetGenerator::GetCSharpSourceLink( - cmSourceFile const* sf, std::string& link) +std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink( + cmSourceFile const* source) { - std::string const& sourceFilePath = sf->GetFullPath(); - std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory(); - - if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) { - const std::string& stripFromPath = - this->Makefile->GetCurrentSourceDirectory(); - if (sourceFilePath.find(stripFromPath) == 0) { - if (const char* l = sf->GetProperty("VS_CSHARP_Link")) { - link = l; - } else { - link = sourceFilePath.substr(stripFromPath.length() + 1); - } - ConvertToWindowsSlash(link); - } - } + // For out of source files, we first check if a matching source group + // for this file exists, otherwise we check if the path relative to current + // source- or binary-dir is used within the link and return that + std::string link; + std::string const& fullFileName = source->GetFullPath(); + std::string const& srcDir = this->Makefile->GetCurrentSourceDirectory(); + std::string const& binDir = this->Makefile->GetCurrentBinaryDirectory(); + // unfortunately we have to copy the source groups, because + // FindSourceGroup uses a regex which is modifying the group + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(fullFileName, sourceGroups); + if (sourceGroup && !sourceGroup->GetFullName().empty()) { + link = sourceGroup->GetFullName() + "/" + + cmsys::SystemTools::GetFilenameName(fullFileName); + } else if (cmHasPrefix(fullFileName, srcDir)) { + link = fullFileName.substr(srcDir.length() + 1); + } else if (cmHasPrefix(fullFileName, binDir)) { + link = fullFileName.substr(binDir.length() + 1); + } else if (const char* l = source->GetProperty("VS_CSHARP_Link")) { + link = l; + } + + ConvertToWindowsSlash(link); + return link; } std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( |