mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 02:39:48 -06:00
Merge topic 'csharp_reference_imported_targets'
de549083e3cmVisualStudio10TargetGenerator: warn if /clr flag is set manually59ec7d50bdcmVisualStudio10TargetGenerator: fix for backward compatibility663f5120f4cmGlobalVisualStudioGenerator: remove TargetCanBeReferenced()359544a907add tests for using target_link_libraries() with imported managed targets43571073e0cmVisualStudio10TargetGenerator: store managed reference information in maps16fec7e2fccmVisualStudio10TargetGenerator: make some methods config awaref3c6828876cmVisualStudio10TargetGenerator: /clr compatible flags for managed tgtf9042d807dremove TargetIsCSharpOnly() and use methods from cmGeneratorTarget ... Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1805
This commit is contained in:
@@ -786,9 +786,14 @@ void cmExportFileGenerator::SetImportDetailProperties(
|
||||
std::string propval;
|
||||
if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
|
||||
propval = p;
|
||||
} else if (target->HasLanguage("CSharp", config)) {
|
||||
// C# projects do not have the /clr flag, so we set the property
|
||||
// here to mark the target as (only) managed (i.e. no .lib file
|
||||
// to link to). Otherwise the COMMON_LANGUAGE_RUNTIME target
|
||||
// property would have to be set manually for C# targets to make
|
||||
// exporting/importing work.
|
||||
propval = "CSharp";
|
||||
}
|
||||
// TODO: make sure propval is set to non-empty string for
|
||||
// CSharp targets (i.e. force ManagedType::Managed).
|
||||
properties[prop] = propval;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5530,7 +5530,9 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
|
||||
return this->CheckManagedType(clr);
|
||||
}
|
||||
|
||||
// TODO: need to check if target is a CSharp target here.
|
||||
// If yes: return ManagedType::Managed.
|
||||
return ManagedType::Native;
|
||||
// C# targets are always managed. This language specific check
|
||||
// is added to avoid that the COMMON_LANGUAGE_RUNTIME target property
|
||||
// has to be set manually for C# targets.
|
||||
return this->HasLanguage("CSharp", config) ? ManagedType::Managed
|
||||
: ManagedType::Native;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
|
||||
ext = ".vfproj";
|
||||
project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
|
||||
}
|
||||
if (this->TargetIsCSharpOnly(t)) {
|
||||
if (t->HasLanguage("CSharp", "")) {
|
||||
ext = ".csproj";
|
||||
project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"";
|
||||
}
|
||||
|
||||
@@ -734,42 +734,6 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
|
||||
cmGeneratorTarget const* gt)
|
||||
{
|
||||
// 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;
|
||||
gt->GetLanguages(languages, "");
|
||||
return languages.size() == 1 && languages.count("CSharp") > 0;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
|
||||
cmGeneratorTarget const* gt)
|
||||
{
|
||||
if (this->TargetIsCSharpOnly(gt)) {
|
||||
return true;
|
||||
}
|
||||
if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
|
||||
gt->GetType() != cmStateEnums::EXECUTABLE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
|
||||
cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
|
||||
{
|
||||
|
||||
@@ -81,12 +81,6 @@ public:
|
||||
// return true if target is fortran only
|
||||
bool TargetIsFortranOnly(const cmGeneratorTarget* gt);
|
||||
|
||||
// return true if target is C# only
|
||||
static bool TargetIsCSharpOnly(cmGeneratorTarget const* gt);
|
||||
|
||||
// return true if target can be referenced by C# targets
|
||||
bool TargetCanBeReferenced(cmGeneratorTarget const* gt);
|
||||
|
||||
/** Get the top-level registry key for this VS version. */
|
||||
std::string GetRegistryBase();
|
||||
|
||||
|
||||
@@ -208,9 +208,7 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t,
|
||||
{
|
||||
std::string res;
|
||||
res = ".vcxproj";
|
||||
std::string lang = t->GetLinkerLanguage(config);
|
||||
if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t) ||
|
||||
lang == "CSharp") {
|
||||
if (t->HasLanguage("CSharp", config)) {
|
||||
res = ".csproj";
|
||||
}
|
||||
return res;
|
||||
@@ -350,6 +348,8 @@ void cmVisualStudio10TargetGenerator::Generate()
|
||||
this->Name.c_str());
|
||||
this->GeneratorTarget->Target->SetProperty(
|
||||
"GENERATOR_FILE_NAME_EXT", this->ProjectFileExtension.c_str());
|
||||
this->DotNetHintReferences.clear();
|
||||
this->AdditionalUsingDirectories.clear();
|
||||
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
|
||||
if (!this->ComputeClOptions()) {
|
||||
return;
|
||||
@@ -710,8 +710,6 @@ void cmVisualStudio10TargetGenerator::Generate()
|
||||
void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
|
||||
{
|
||||
std::vector<std::string> references;
|
||||
typedef std::pair<std::string, std::string> HintReference;
|
||||
std::vector<HintReference> hintReferences;
|
||||
if (const char* vsDotNetReferences =
|
||||
this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
|
||||
cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
|
||||
@@ -727,11 +725,12 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
|
||||
"/" + path;
|
||||
}
|
||||
ConvertToWindowsSlash(path);
|
||||
hintReferences.push_back(HintReference(name, path));
|
||||
this->DotNetHintReferences[""].push_back(
|
||||
DotNetHintReference(name, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!references.empty() || !hintReferences.empty()) {
|
||||
if (!references.empty() || !this->DotNetHintReferences.empty()) {
|
||||
this->WriteString("<ItemGroup>\n", 1);
|
||||
for (std::string const& ri : references) {
|
||||
// if the entry from VS_DOTNET_REFERENCES is an existing file, generate
|
||||
@@ -740,23 +739,36 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
|
||||
std::string name = cmsys::SystemTools::GetFilenameWithoutExtension(ri);
|
||||
std::string path = ri;
|
||||
ConvertToWindowsSlash(path);
|
||||
hintReferences.push_back(HintReference(name, path));
|
||||
this->DotNetHintReferences[""].push_back(
|
||||
DotNetHintReference(name, path));
|
||||
} else {
|
||||
this->WriteDotNetReference(ri, "");
|
||||
this->WriteDotNetReference(ri, "", "");
|
||||
}
|
||||
}
|
||||
for (const auto& i : hintReferences) {
|
||||
this->WriteDotNetReference(i.first, i.second);
|
||||
for (const auto& h : this->DotNetHintReferences) {
|
||||
// DotNetHintReferences is also populated from AddLibraries().
|
||||
// The configuration specific hint references are added there.
|
||||
for (const auto& i : h.second) {
|
||||
this->WriteDotNetReference(i.first, i.second, h.first);
|
||||
}
|
||||
}
|
||||
this->WriteString("</ItemGroup>\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
void cmVisualStudio10TargetGenerator::WriteDotNetReference(
|
||||
std::string const& ref, std::string const& hint)
|
||||
std::string const& ref, std::string const& hint, std::string const& config)
|
||||
{
|
||||
this->WriteString("<Reference Include=\"", 2);
|
||||
(*this->BuildFileStream) << cmVS10EscapeAttr(ref) << "\">\n";
|
||||
std::string attr = " Include=\"" + cmVS10EscapeAttr(ref) + "\"";
|
||||
// If 'config' is not empty, the reference is only added for the given
|
||||
// configuration. This is used when referencing imported managed assemblies.
|
||||
// See also cmVisualStudio10TargetGenerator::AddLibraries().
|
||||
if (!config.empty()) {
|
||||
this->WritePlatformConfigTag("Reference", config, 2, attr.c_str());
|
||||
} else {
|
||||
this->WriteString("<Reference ", 2);
|
||||
(*this->BuildFileStream) << attr << ">\n";
|
||||
}
|
||||
this->WriteElem("CopyLocalSatelliteAssemblies", "true", 3);
|
||||
this->WriteElem("ReferenceOutputAssembly", "true", 3);
|
||||
if (!hint.empty()) {
|
||||
@@ -2510,8 +2522,20 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
|
||||
// check for managed C++ assembly compiler flag. This overrides any
|
||||
// /clr* compiler flags which may be defined in the flags variable(s).
|
||||
if (this->ProjectType != csproj) {
|
||||
// TODO: add check here, if /clr was defined manually and issue
|
||||
// warning that this is discouraged.
|
||||
// Warn if /clr was added manually. This should not be done
|
||||
// anymore, because cmGeneratorTarget may not be aware that the
|
||||
// target uses C++/CLI.
|
||||
if (flags.find("/clr") != std::string::npos ||
|
||||
defineFlags.find("/clr") != std::string::npos) {
|
||||
if (configName == this->Configurations[0]) {
|
||||
std::string message = "For the target \"" +
|
||||
this->GeneratorTarget->GetName() +
|
||||
"\" the /clr compiler flag was added manually. " +
|
||||
"Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME "
|
||||
"target property.";
|
||||
this->Makefile->IssueMessage(cmake::MessageType::WARNING, message);
|
||||
}
|
||||
}
|
||||
if (auto* clr =
|
||||
this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
|
||||
std::string clrString = clr;
|
||||
@@ -2584,10 +2608,15 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
|
||||
if (this->ProjectType != csproj && clOptions.IsManaged()) {
|
||||
this->Managed = true;
|
||||
std::string managedType = clOptions.GetFlag("CompileAsManaged");
|
||||
if (managedType == "Safe") {
|
||||
if (managedType == "Safe" || managedType == "Pure") {
|
||||
// force empty calling convention if safe clr is used
|
||||
clOptions.AddFlag("CallingConvention", "");
|
||||
}
|
||||
// The default values of these flags are incompatible to
|
||||
// managed assemblies. We have to force valid values if
|
||||
// the target is a managed C++ target.
|
||||
clOptions.AddFlag("ExceptionHandling", "Async");
|
||||
clOptions.AddFlag("BasicRuntimeChecks", "Default");
|
||||
}
|
||||
if (this->ProjectType == csproj) {
|
||||
// /nowin32manifest overrides /win32manifest: parameter
|
||||
@@ -2646,6 +2675,18 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
|
||||
ConvertToWindowsSlash(pdb);
|
||||
this->WriteElemEscapeXML("ProgramDataBaseFileName", pdb, 3);
|
||||
}
|
||||
|
||||
// add AdditionalUsingDirectories
|
||||
if (this->AdditionalUsingDirectories.count(configName) > 0) {
|
||||
std::string dirs;
|
||||
for (auto u : this->AdditionalUsingDirectories[configName]) {
|
||||
if (!dirs.empty()) {
|
||||
dirs.append(";");
|
||||
}
|
||||
dirs.append(u);
|
||||
}
|
||||
this->WriteElemEscapeXML("AdditionalUsingDirectories", dirs, 3);
|
||||
}
|
||||
}
|
||||
|
||||
this->WriteString("</ClCompile>\n", 2);
|
||||
@@ -3289,7 +3330,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
|
||||
|
||||
std::vector<std::string> libVec;
|
||||
std::vector<std::string> vsTargetVec;
|
||||
this->AddLibraries(cli, libVec, vsTargetVec);
|
||||
this->AddLibraries(cli, libVec, vsTargetVec, config);
|
||||
if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(),
|
||||
"CUDA") != linkClosure->Languages.end()) {
|
||||
switch (this->CudaOptions[config]->GetCudaRuntime()) {
|
||||
@@ -3505,23 +3546,51 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
|
||||
}
|
||||
|
||||
void cmVisualStudio10TargetGenerator::AddLibraries(
|
||||
cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
|
||||
std::vector<std::string>& vsTargetVec)
|
||||
const cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
|
||||
std::vector<std::string>& vsTargetVec, const std::string& config)
|
||||
{
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
ItemVector const& libs = cli.GetItems();
|
||||
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.Target) {
|
||||
auto managedType = l.Target->GetManagedType(config);
|
||||
if (managedType != cmGeneratorTarget::ManagedType::Native &&
|
||||
this->GeneratorTarget->GetManagedType(config) !=
|
||||
cmGeneratorTarget::ManagedType::Native &&
|
||||
l.Target->IsImported()) {
|
||||
auto location = l.Target->GetFullPath(config);
|
||||
if (!location.empty()) {
|
||||
ConvertToWindowsSlash(location);
|
||||
switch (this->ProjectType) {
|
||||
case csproj:
|
||||
// If the target we want to "link" to is an imported managed
|
||||
// target and this is a C# project, we add a hint reference. This
|
||||
// reference is written to project file in
|
||||
// WriteDotNetReferences().
|
||||
this->DotNetHintReferences[config].push_back(
|
||||
DotNetHintReference(l.Target->GetName(), location));
|
||||
break;
|
||||
case vcxproj:
|
||||
// Add path of assembly to list of using-directories, so the
|
||||
// managed assembly can be used by '#using <assembly.dll>' in
|
||||
// code.
|
||||
this->AdditionalUsingDirectories[config].insert(
|
||||
cmSystemTools::GetFilenamePath(location));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 (managedType == cmGeneratorTarget::ManagedType::Managed) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (l.IsPath) {
|
||||
@@ -3746,8 +3815,24 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
|
||||
"{" + this->GlobalGenerator->GetGUID(name) + "}", 3);
|
||||
this->WriteElem("Name", name, 3);
|
||||
this->WriteDotNetReferenceCustomTags(name);
|
||||
if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
|
||||
this->WriteElem("ReferenceOutputAssembly", "false", 3);
|
||||
if (this->Managed) {
|
||||
// If the dependency target is not managed (compiled with /clr or
|
||||
// C# target) we cannot reference it and have to set
|
||||
// 'ReferenceOutputAssembly' to false.
|
||||
cmGeneratorTarget::ManagedType check =
|
||||
cmGeneratorTarget::ManagedType::Mixed;
|
||||
// FIXME: These (5) lines should be removed. They are here to allow
|
||||
// manual setting of the /clr flag in compiler options. Setting
|
||||
// /clr manually makes cmGeneratorTarget::GetManagedType() return
|
||||
// 'Native' instead of 'Mixed' or 'Managed'.
|
||||
check = cmGeneratorTarget::ManagedType::Native;
|
||||
bool unmanagedStatic = false;
|
||||
if (dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
|
||||
unmanagedStatic = !dt->HasLanguage("CSharp", "");
|
||||
}
|
||||
if (dt->GetManagedType("") < check || unmanagedStatic) {
|
||||
this->WriteElem("ReferenceOutputAssembly", "false", 3);
|
||||
}
|
||||
}
|
||||
this->WriteString("</ProjectReference>\n", 2);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ private:
|
||||
std::vector<size_t> const& exclude_configs);
|
||||
void WriteAllSources();
|
||||
void WriteDotNetReferences();
|
||||
void WriteDotNetReference(std::string const& ref, std::string const& hint);
|
||||
void WriteDotNetReference(std::string const& ref, std::string const& hint,
|
||||
std::string const& config);
|
||||
void WriteDotNetReferenceCustomTags(std::string const& ref);
|
||||
void WriteEmbeddedResourceGroup();
|
||||
void WriteWinRTReferences();
|
||||
@@ -148,9 +149,10 @@ private:
|
||||
void WriteProjectReferences();
|
||||
void WriteApplicationTypeSettings();
|
||||
void OutputSourceSpecificFlags(Elem&, cmSourceFile const* source);
|
||||
void AddLibraries(cmComputeLinkInformation& cli,
|
||||
void AddLibraries(const cmComputeLinkInformation& cli,
|
||||
std::vector<std::string>& libVec,
|
||||
std::vector<std::string>& vsTargetVec);
|
||||
std::vector<std::string>& vsTargetVec,
|
||||
const std::string& config);
|
||||
void AddTargetsFileAndConfigPair(std::string const& targetsFile,
|
||||
std::string const& config);
|
||||
void WriteLibOptions(std::string const& config);
|
||||
@@ -214,6 +216,15 @@ private:
|
||||
bool IsMissingFiles;
|
||||
std::vector<std::string> AddedFiles;
|
||||
std::string DefaultArtifactDir;
|
||||
// managed C++/C# relevant members
|
||||
typedef std::pair<std::string, std::string> DotNetHintReference;
|
||||
typedef std::vector<DotNetHintReference> DotNetHintReferenceList;
|
||||
typedef std::map<std::string, DotNetHintReferenceList>
|
||||
DotNetHintReferenceMap;
|
||||
DotNetHintReferenceMap DotNetHintReferences;
|
||||
typedef std::set<std::string> UsingDirectories;
|
||||
typedef std::map<std::string, UsingDirectories> UsingDirectoriesMap;
|
||||
UsingDirectoriesMap AdditionalUsingDirectories;
|
||||
|
||||
typedef std::map<std::string, ToolSources> ToolSourceMap;
|
||||
ToolSourceMap Tools;
|
||||
|
||||
@@ -443,4 +443,5 @@ endif()
|
||||
|
||||
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
|
||||
add_RunCMake_test(CSharpCustomCommand)
|
||||
add_RunCMake_test(CSharpReferenceImport)
|
||||
endif()
|
||||
|
||||
3
Tests/RunCMake/CSharpReferenceImport/CMakeLists.txt
Normal file
3
Tests/RunCMake/CSharpReferenceImport/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
45
Tests/RunCMake/CSharpReferenceImport/ImportLib.cmake
Normal file
45
Tests/RunCMake/CSharpReferenceImport/ImportLib.cmake
Normal file
@@ -0,0 +1,45 @@
|
||||
enable_language(CXX CSharp)
|
||||
|
||||
if(NOT DEFINED exportFileName OR
|
||||
NOT DEFINED exportNameSpace OR
|
||||
NOT DEFINED exportTargetName)
|
||||
message(FATAL_ERROR "export information missing")
|
||||
endif()
|
||||
|
||||
add_library(${exportTargetName}CSharp SHARED
|
||||
ImportLib.cs)
|
||||
|
||||
# native c++ dll
|
||||
add_library(${exportTargetName}Native SHARED
|
||||
ImportLibNative.h
|
||||
ImportLibNative.cxx)
|
||||
|
||||
# mixed c++ dll
|
||||
add_library(${exportTargetName}Mixed SHARED
|
||||
ImportLibMixed.cxx
|
||||
ImportLibMixedNative.h
|
||||
ImportLibMixedNative.cxx)
|
||||
set_target_properties(${exportTargetName}Mixed PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "")
|
||||
|
||||
# pure c++ dll
|
||||
add_library(${exportTargetName}Pure SHARED
|
||||
ImportLibPure.cxx)
|
||||
set_target_properties(${exportTargetName}Pure PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "pure")
|
||||
|
||||
# safe c++ dll
|
||||
add_library(${exportTargetName}Safe SHARED
|
||||
ImportLibSafe.cxx)
|
||||
set_target_properties(${exportTargetName}Safe PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "safe")
|
||||
|
||||
# generate export file
|
||||
export(TARGETS
|
||||
${exportTargetName}CSharp
|
||||
${exportTargetName}Native
|
||||
${exportTargetName}Mixed
|
||||
${exportTargetName}Pure
|
||||
${exportTargetName}Safe
|
||||
NAMESPACE "${exportNameSpace}:"
|
||||
FILE "${exportFileName}")
|
||||
8
Tests/RunCMake/CSharpReferenceImport/ImportLib.cs
Normal file
8
Tests/RunCMake/CSharpReferenceImport/ImportLib.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
public
|
||||
class ImportLibCSharp
|
||||
{
|
||||
public
|
||||
static void Message() { Console.WriteLine("ImportLibCSharp"); }
|
||||
}
|
||||
8
Tests/RunCMake/CSharpReferenceImport/ImportLibMixed.cxx
Normal file
8
Tests/RunCMake/CSharpReferenceImport/ImportLibMixed.cxx
Normal file
@@ -0,0 +1,8 @@
|
||||
using namespace System;
|
||||
|
||||
public
|
||||
ref class ImportLibMixed
|
||||
{
|
||||
public:
|
||||
static void Message() { Console::WriteLine("ImportLibMixed"); }
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "ImportLibMixedNative.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void ImportLibMixedNative::Message()
|
||||
{
|
||||
std::cout << "ImportLibMixedNative" << std::endl;
|
||||
}
|
||||
13
Tests/RunCMake/CSharpReferenceImport/ImportLibMixedNative.h
Normal file
13
Tests/RunCMake/CSharpReferenceImport/ImportLibMixedNative.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ImportLibMixed_EXPORTS
|
||||
#define mixedAPI __declspec(dllexport)
|
||||
#else
|
||||
#define mixedAPI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
class mixedAPI ImportLibMixedNative
|
||||
{
|
||||
public:
|
||||
static void Message();
|
||||
};
|
||||
8
Tests/RunCMake/CSharpReferenceImport/ImportLibNative.cxx
Normal file
8
Tests/RunCMake/CSharpReferenceImport/ImportLibNative.cxx
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "ImportLibNative.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void ImportLibNative::Message()
|
||||
{
|
||||
std::cout << "ImportLibNative" << std::endl;
|
||||
}
|
||||
13
Tests/RunCMake/CSharpReferenceImport/ImportLibNative.h
Normal file
13
Tests/RunCMake/CSharpReferenceImport/ImportLibNative.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef ImportLibNative_EXPORTS
|
||||
#define nativeAPI __declspec(dllexport)
|
||||
#else
|
||||
#define nativeAPI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
class nativeAPI ImportLibNative
|
||||
{
|
||||
public:
|
||||
static void Message();
|
||||
};
|
||||
8
Tests/RunCMake/CSharpReferenceImport/ImportLibPure.cxx
Normal file
8
Tests/RunCMake/CSharpReferenceImport/ImportLibPure.cxx
Normal file
@@ -0,0 +1,8 @@
|
||||
using namespace System;
|
||||
|
||||
public
|
||||
ref class ImportLibPure
|
||||
{
|
||||
public:
|
||||
static void Message() { Console::WriteLine("ImportLibPure"); }
|
||||
};
|
||||
8
Tests/RunCMake/CSharpReferenceImport/ImportLibSafe.cxx
Normal file
8
Tests/RunCMake/CSharpReferenceImport/ImportLibSafe.cxx
Normal file
@@ -0,0 +1,8 @@
|
||||
using namespace System;
|
||||
|
||||
public
|
||||
ref class ImportLibSafe
|
||||
{
|
||||
public:
|
||||
static void Message() { Console::WriteLine("ImportLibSafe"); }
|
||||
};
|
||||
88
Tests/RunCMake/CSharpReferenceImport/ReferenceImport.cmake
Normal file
88
Tests/RunCMake/CSharpReferenceImport/ReferenceImport.cmake
Normal file
@@ -0,0 +1,88 @@
|
||||
enable_language(CXX CSharp)
|
||||
|
||||
if(NOT DEFINED exportFileName OR
|
||||
NOT DEFINED exportNameSpace OR
|
||||
NOT DEFINED exportTargetName)
|
||||
message(FATAL_ERROR "export information missing")
|
||||
endif()
|
||||
|
||||
# Include generated export file.
|
||||
if(NOT EXISTS "${exportFileName}")
|
||||
message(FATAL_ERROR "exportFileNameCSharp does not exist: ${exportFileName}")
|
||||
endif()
|
||||
include(${exportFileName})
|
||||
|
||||
# Verify expected targets are imported
|
||||
set(linkNames linkNameCSharp linkNameNative linkNameMixed
|
||||
linkNamePure linkNameSafe)
|
||||
set(linkNameCSharp "${exportNameSpace}:${exportTargetName}CSharp")
|
||||
set(linkNameNative "${exportNameSpace}:${exportTargetName}Native")
|
||||
set(linkNameMixed "${exportNameSpace}:${exportTargetName}Mixed")
|
||||
set(linkNamePure "${exportNameSpace}:${exportTargetName}Pure")
|
||||
set(linkNameSafe "${exportNameSpace}:${exportTargetName}Safe")
|
||||
foreach(l ${linkNames})
|
||||
if(NOT TARGET ${${l}})
|
||||
message(FATAL_ERROR "imported target not found (${${l}})")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Test referencing managed assemblies from C# executable.
|
||||
add_executable(ReferenceImportCSharp ReferenceImport.cs)
|
||||
target_link_libraries(ReferenceImportCSharp
|
||||
${linkNameCSharp}
|
||||
${linkNameNative} # ignored
|
||||
${linkNameMixed}
|
||||
${linkNamePure}
|
||||
${linkNameSafe}
|
||||
)
|
||||
|
||||
# native C++ executable.
|
||||
add_executable(ReferenceImportNative ReferenceImportNative.cxx)
|
||||
target_link_libraries(ReferenceImportNative
|
||||
${linkNameCSharp} # ignored
|
||||
${linkNameNative}
|
||||
${linkNameMixed}
|
||||
${linkNamePure} # ignored
|
||||
${linkNameSafe} # ignored
|
||||
)
|
||||
add_custom_command(TARGET ReferenceImportNative POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:${linkNameNative}>"
|
||||
"${CMAKE_BINARY_DIR}/$<CONFIG>"
|
||||
)
|
||||
|
||||
# mixed C++ executable.
|
||||
add_executable(ReferenceImportMixed ReferenceImportMixed.cxx)
|
||||
target_link_libraries(ReferenceImportMixed
|
||||
${linkNameCSharp}
|
||||
${linkNameNative}
|
||||
${linkNameMixed}
|
||||
${linkNamePure}
|
||||
${linkNameSafe}
|
||||
)
|
||||
set_target_properties(ReferenceImportMixed PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "")
|
||||
|
||||
# pure C++ executable.
|
||||
add_executable(ReferenceImportPure ReferenceImportPure.cxx)
|
||||
target_link_libraries(ReferenceImportPure
|
||||
${linkNameCSharp}
|
||||
${linkNameNative} # ignored
|
||||
${linkNameMixed}
|
||||
${linkNamePure}
|
||||
${linkNameSafe}
|
||||
)
|
||||
set_target_properties(ReferenceImportPure PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "pure")
|
||||
|
||||
# native C++ executable.
|
||||
add_executable(ReferenceImportSafe ReferenceImportSafe.cxx)
|
||||
target_link_libraries(ReferenceImportSafe
|
||||
${linkNameCSharp}
|
||||
${linkNameNative} # ignored
|
||||
${linkNameMixed}
|
||||
${linkNamePure}
|
||||
${linkNameSafe}
|
||||
)
|
||||
set_target_properties(ReferenceImportSafe PROPERTIES
|
||||
COMMON_LANGUAGE_RUNTIME "safe")
|
||||
13
Tests/RunCMake/CSharpReferenceImport/ReferenceImport.cs
Normal file
13
Tests/RunCMake/CSharpReferenceImport/ReferenceImport.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
public class ReferenceImport
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Console.WriteLine("ReferenceImportCSharp");
|
||||
ImportLibMixed.Message();
|
||||
ImportLibPure.Message();
|
||||
ImportLibSafe.Message();
|
||||
ImportLibCSharp.Message();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// clang-format off
|
||||
|
||||
using namespace System;
|
||||
|
||||
#using <ImportLibMixed.dll>
|
||||
#using <ImportLibPure.dll>
|
||||
#using <ImportLibSafe.dll>
|
||||
#using <ImportLibCSharp.dll>
|
||||
|
||||
#include "ImportLibNative.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
Console::WriteLine("ReferenceImportMixed");
|
||||
ImportLibNative::Message();
|
||||
ImportLibMixed::Message();
|
||||
ImportLibPure::Message();
|
||||
ImportLibSafe::Message();
|
||||
ImportLibCSharp::Message();
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
// clang-format off
|
||||
|
||||
#include "ImportLibNative.h"
|
||||
#include "ImportLibMixedNative.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "ReferenceImportNative" << std::endl;
|
||||
ImportLibNative::Message();
|
||||
ImportLibMixedNative::Message();
|
||||
};
|
||||
17
Tests/RunCMake/CSharpReferenceImport/ReferenceImportPure.cxx
Normal file
17
Tests/RunCMake/CSharpReferenceImport/ReferenceImportPure.cxx
Normal file
@@ -0,0 +1,17 @@
|
||||
// clang-format off
|
||||
|
||||
using namespace System;
|
||||
|
||||
#using <ImportLibMixed.dll>
|
||||
#using <ImportLibPure.dll>
|
||||
#using <ImportLibSafe.dll>
|
||||
#using <ImportLibCSharp.dll>
|
||||
|
||||
int main()
|
||||
{
|
||||
Console::WriteLine("ReferenceImportPure");
|
||||
ImportLibMixed::Message();
|
||||
ImportLibPure::Message();
|
||||
ImportLibSafe::Message();
|
||||
ImportLibCSharp::Message();
|
||||
};
|
||||
17
Tests/RunCMake/CSharpReferenceImport/ReferenceImportSafe.cxx
Normal file
17
Tests/RunCMake/CSharpReferenceImport/ReferenceImportSafe.cxx
Normal file
@@ -0,0 +1,17 @@
|
||||
// clang-format off
|
||||
|
||||
using namespace System;
|
||||
|
||||
#using <ImportLibMixed.dll>
|
||||
#using <ImportLibPure.dll>
|
||||
#using <ImportLibSafe.dll>
|
||||
#using <ImportLibCSharp.dll>
|
||||
|
||||
int main()
|
||||
{
|
||||
Console::WriteLine("ReferenceImportSafe");
|
||||
ImportLibMixed::Message();
|
||||
ImportLibPure::Message();
|
||||
ImportLibSafe::Message();
|
||||
ImportLibCSharp::Message();
|
||||
};
|
||||
41
Tests/RunCMake/CSharpReferenceImport/RunCMakeTest.cmake
Normal file
41
Tests/RunCMake/CSharpReferenceImport/RunCMakeTest.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
include(RunCMake)
|
||||
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
|
||||
set(exportFileName "${RunCMake_BINARY_DIR}/module.cmake")
|
||||
set(exportNameSpace "ex")
|
||||
set(exportTargetName "ImportLib")
|
||||
|
||||
set(RunCMake_TEST_OPTIONS_BASE ${RunCMake_TEST_OPTIONS}
|
||||
"-DexportNameSpace:INTERNAL=${exportNameSpace}"
|
||||
"-DexportTargetName:INTERNAL=${exportTargetName}")
|
||||
|
||||
file(REMOVE "${exportFileName}")
|
||||
|
||||
# generate C# & C++ assemblies for use as imported target
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ImportLib-build)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
set(RunCMake_TEST_OPTIONS ${RunCMake_TEST_OPTIONS_BASE}
|
||||
"-DexportFileName:INTERNAL=${exportFileName}"
|
||||
# make sure we know the RunCMake_TEST if configuring the project again
|
||||
# with cmake-gui for debugging.
|
||||
"-DRunCMake_TEST:INTERNAL=ImportLib")
|
||||
|
||||
run_cmake(ImportLib)
|
||||
run_cmake_command(ImportLib-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
|
||||
# generate C# & managed C++ programs which reference imported managed assemblies.
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ReferenceImport-build)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
set(RunCMake_TEST_OPTIONS ${RunCMake_TEST_OPTIONS_BASE}
|
||||
"-DexportFileName:INTERNAL=${exportFileName}"
|
||||
# make sure we know the RunCMake_TEST if configuring the project again
|
||||
# with cmake-gui for debugging.
|
||||
"-DRunCMake_TEST:INTERNAL=ReferenceImport")
|
||||
|
||||
run_cmake(ReferenceImport)
|
||||
run_cmake_command(ReferenceImport-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
Reference in New Issue
Block a user