mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-09 23:59:53 -05:00
VS: Support C# project references
When specifying a pure C# target in the `target_link_libraries()` call to another C++ target, a `<ProjectReference>` was setup for it (we wanted this) but also a corresponding `.lib` was added under `<AdditionalDependencies>` (we didn't want this). This change introduces a check that prevents `.lib` linker options from being used when the corresponding target for that library is a C# target. Fixes: #17678
This commit is contained in:
@@ -737,26 +737,24 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
|
||||
bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
|
||||
cmGeneratorTarget const* gt)
|
||||
{
|
||||
// check to see if this is a C# build
|
||||
// C# targets can be defined with add_library() (using SHARED or STATIC) and
|
||||
// also using add_executable(). We do not treat imported C# targets the same
|
||||
// (these come in as UTILITY)
|
||||
if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
|
||||
gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
|
||||
gt->GetType() != cmStateEnums::EXECUTABLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Issue diagnostic if the source files depend on the config.
|
||||
std::vector<cmSourceFile*> sources;
|
||||
if (!gt->GetConfigCommonSourceFiles(sources)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<std::string> languages;
|
||||
{
|
||||
// Issue diagnostic if the source files depend on the config.
|
||||
std::vector<cmSourceFile*> sources;
|
||||
if (!gt->GetConfigCommonSourceFiles(sources)) {
|
||||
return false;
|
||||
}
|
||||
// Only "real" targets are allowed to be C# targets.
|
||||
if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
gt->GetLanguages(languages, "");
|
||||
if (languages.size() == 1) {
|
||||
if (*languages.begin() == "CSharp") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return languages.size() == 1 && languages.count("CSharp") > 0;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
|
||||
|
||||
@@ -3451,6 +3451,17 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
|
||||
std::string currentBinDir =
|
||||
this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
for (cmComputeLinkInformation::Item const& l : libs) {
|
||||
// Do not allow C# targets to be added to the LIB listing. LIB files are
|
||||
// used for linking C++ dependencies. C# libraries do not have lib files.
|
||||
// Instead, they compile down to C# reference libraries (DLL files). The
|
||||
// `<ProjectReference>` elements added to the vcxproj are enough for the
|
||||
// IDE to deduce the DLL file required by other C# projects that need its
|
||||
// reference library.
|
||||
if (l.Target &&
|
||||
cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(l.Target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l.IsPath) {
|
||||
std::string path =
|
||||
this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
|
||||
|
||||
@@ -348,6 +348,7 @@ if(BUILD_TESTING)
|
||||
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
|
||||
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
|
||||
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
|
||||
ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
|
||||
endif()
|
||||
|
||||
ADD_TEST_MACRO(COnly COnly)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
UsefulManagedCppClass.* -format.clang-format
|
||||
@@ -0,0 +1,19 @@
|
||||
# Take a C# shared library and link it to a managed C++ shared library
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project (CSharpLinkFromCxx CXX CSharp)
|
||||
|
||||
add_library(CSharpLibrary SHARED UsefulCSharpClass.cs)
|
||||
|
||||
# we have to change the default flags for the
|
||||
# managed C++ project to build
|
||||
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
|
||||
# The C# project is a dependency of the C++/CLI project
|
||||
add_library(ManagedCppLibrary SHARED UsefulManagedCppClass.cpp UsefulManagedCppClass.hpp)
|
||||
target_compile_options(ManagedCppLibrary PRIVATE "/clr")
|
||||
target_link_libraries(ManagedCppLibrary PUBLIC CSharpLibrary)
|
||||
|
||||
# Main executable for the test framework
|
||||
add_executable(CSharpLinkFromCxx CSharpLinkFromCxx.cs)
|
||||
target_link_libraries(CSharpLinkFromCxx PRIVATE ManagedCppLibrary)
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using CSharpLibrary;
|
||||
|
||||
namespace CSharpLinkFromCxx
|
||||
{
|
||||
internal class CSharpLinkFromCxx
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Starting test for CSharpLinkFromCxx");
|
||||
|
||||
var useful = new UsefulManagedCppClass();
|
||||
useful.RunTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace CSharpLibrary
|
||||
{
|
||||
public class UsefulCSharpClass
|
||||
{
|
||||
public string GetSomethingUseful()
|
||||
{
|
||||
return "Something Useful";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "UsefulManagedCppClass.hpp"
|
||||
|
||||
namespace CSharpLibrary
|
||||
{
|
||||
UsefulManagedCppClass::UsefulManagedCppClass()
|
||||
{
|
||||
auto useful = gcnew UsefulCSharpClass();
|
||||
m_usefulString = useful->GetSomethingUseful();
|
||||
}
|
||||
|
||||
void UsefulManagedCppClass::RunTest()
|
||||
{
|
||||
Console::WriteLine("Printing from Managed CPP Class: " + m_usefulString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using namespace System;
|
||||
|
||||
namespace CSharpLibrary
|
||||
{
|
||||
public ref class UsefulManagedCppClass
|
||||
{
|
||||
public:
|
||||
|
||||
UsefulManagedCppClass();
|
||||
void RunTest();
|
||||
|
||||
private:
|
||||
|
||||
String^ m_usefulString;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user