mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-09 07:11:05 -06:00
CSharp: Add support for source groups with out-of-source builds
This also fixes support for multiple sources of the same name in different directories. Add a test for both problems. Issue: #19505
This commit is contained in:
@@ -981,17 +981,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 =
|
||||
@@ -1054,25 +1048,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 +1417,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);
|
||||
@@ -1805,30 +1775,8 @@ 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);
|
||||
}
|
||||
}
|
||||
if (this->ProjectType == csproj && !this->InSourceBuild) {
|
||||
toolHasSettings = true;
|
||||
}
|
||||
if (ext == "hlsl") {
|
||||
tool = "FXCompile";
|
||||
@@ -2047,9 +1995,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
|
||||
if (!settingsLastGenOutput.empty()) {
|
||||
e2.Element("LastGenOutput", settingsLastGenOutput);
|
||||
}
|
||||
if (!sourceLink.empty()) {
|
||||
e2.Element("Link", sourceLink);
|
||||
}
|
||||
if (!subType.empty()) {
|
||||
e2.Element("SubType", subType);
|
||||
}
|
||||
@@ -2102,6 +2047,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);
|
||||
}
|
||||
@@ -2461,12 +2420,6 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
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()) {
|
||||
@@ -4869,24 +4822,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 (fullFileName.find(srcDir) == 0) {
|
||||
link = fullFileName.substr(srcDir.length() + 1);
|
||||
} else if (fullFileName.find(binDir) == 0) {
|
||||
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(
|
||||
|
||||
@@ -183,7 +183,7 @@ private:
|
||||
std::map<std::string, std::string>& tags);
|
||||
void WriteCSharpSourceProperties(
|
||||
Elem& e2, const std::map<std::string, std::string>& tags);
|
||||
void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link);
|
||||
std::string GetCSharpSourceLink(cmSourceFile const* source);
|
||||
|
||||
private:
|
||||
friend class cmVS10GeneratorOptions;
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
project (CSharpOnly CSharp)
|
||||
|
||||
# C# does not make any difference between STATIC and SHARED libs
|
||||
add_library(lib1 STATIC lib1.cs)
|
||||
add_library(lib1 STATIC lib1.cs nested/lib1.cs)
|
||||
#without the source group this test will fail to compile
|
||||
source_group(nested FILES nested/lib1.cs)
|
||||
add_library(lib2 SHARED lib2.cs)
|
||||
|
||||
add_executable(CSharpOnly csharponly.cs)
|
||||
|
||||
@@ -5,10 +5,8 @@ namespace CSharpOnly
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
int val = Lib1.getResult();
|
||||
|
||||
Lib2 l = new Lib2();
|
||||
val = l.myVal;
|
||||
|
||||
val = val + l.myVal + nested.Lib1.getResult();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
13
Tests/CSharpOnly/nested/lib1.cs
Normal file
13
Tests/CSharpOnly/nested/lib1.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace CSharpOnly
|
||||
{
|
||||
namespace nested
|
||||
{
|
||||
public class Lib1
|
||||
{
|
||||
public static int getResult()
|
||||
{
|
||||
return 23;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Tests/RunCMake/VS10Project/CSharpSourceGroup/foo.cs
Normal file
3
Tests/RunCMake/VS10Project/CSharpSourceGroup/foo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
void foo()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
void baz()
|
||||
{
|
||||
}
|
||||
@@ -3,12 +3,12 @@ cmake_policy(SET CMP0057 NEW)
|
||||
include(RunCMake)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
|
||||
run_cmake(VsCsharpSourceGroup)
|
||||
run_cmake(VsCSharpCompilerOpts)
|
||||
run_cmake(ExplicitCMakeLists)
|
||||
run_cmake(RuntimeLibrary)
|
||||
run_cmake(SourceGroupCMakeLists)
|
||||
run_cmake(SourceGroupTreeCMakeLists)
|
||||
|
||||
run_cmake(VsConfigurationType)
|
||||
run_cmake(VsTargetsFileReferences)
|
||||
run_cmake(VsCustomProps)
|
||||
|
||||
22
Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
Normal file
22
Tests/RunCMake/VS10Project/VsCsharpSourceGroup-check.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
set(csProjFile "${RunCMake_TEST_BINARY_DIR}/VsCsharpSourceGroup.csproj")
|
||||
if(NOT EXISTS "${csProjFile}")
|
||||
set(RunCMake_TEST_FAILED "Project file ${csProjFile} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS "${csProjFile}" lines)
|
||||
|
||||
include(${RunCMake_TEST_SOURCE_DIR}/VsCsharpSourceGroupHelpers.cmake)
|
||||
|
||||
set(SOURCE_GROUPS_TO_FIND
|
||||
"CSharpSourceGroup"
|
||||
"CSharpSourceGroup/nested"
|
||||
"Images"
|
||||
)
|
||||
|
||||
foreach(GROUP_NAME IN LISTS ${SOURCE_GROUPS_TO_FIND})
|
||||
find_source_group("${lines}" ${GROUP_NAME})
|
||||
if(NOT ${SOURCE_GROUP_FOUND})
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
16
Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
Normal file
16
Tests/RunCMake/VS10Project/VsCsharpSourceGroup.cmake
Normal file
@@ -0,0 +1,16 @@
|
||||
enable_language(CSharp)
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug)
|
||||
|
||||
set(SRC_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/foo.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/nested/baz.cs
|
||||
)
|
||||
|
||||
set(IMAGE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/Images/empty.bmp
|
||||
)
|
||||
|
||||
add_library(VsCsharpSourceGroup SHARED ${SRC_FILES} ${IMAGE_FILES})
|
||||
source_group("CSharpSourceGroup" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/foo.cs)
|
||||
source_group("CSharpSourceGroup/nested" FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSharpSourceGroup/nested/baz.cs)
|
||||
source_group("Images" FILES ${IMAGE_FILES})
|
||||
15
Tests/RunCMake/VS10Project/VsCsharpSourceGroupHelpers.cmake
Normal file
15
Tests/RunCMake/VS10Project/VsCsharpSourceGroupHelpers.cmake
Normal file
@@ -0,0 +1,15 @@
|
||||
function(find_source_group LINES NAME)
|
||||
set(foundSourceGroupLink 0)
|
||||
foreach(line IN LISTS LINES)
|
||||
if(line MATCHES "<Link>${NAME}</Link>")
|
||||
set(foundSourceGroupLink 1)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT foundSourceGroupLink)
|
||||
set(RunCMake_TEST_FAILED "Source group link for ${NAME} not found." PARENT_SCOPE)
|
||||
set(SOURCE_GROUP_FOUND 0 PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(SOURCE_GROUP_FOUND 1 PARENT_SCOPE)
|
||||
endfunction()
|
||||
Reference in New Issue
Block a user