VS: Add StartupObject property for managed .NET projects

This commit is contained in:
Florian Schweiger
2022-04-08 13:01:57 +02:00
parent 359d7c19e5
commit d89af11f89
11 changed files with 112 additions and 0 deletions

View File

@@ -370,6 +370,7 @@ syn keyword cmakeProperty contained
\ VS_DOTNET_DOCUMENTATION_FILE
\ VS_DOTNET_REFERENCES
\ VS_DOTNET_REFERENCES_COPY_LOCAL
\ VS_DOTNET_STARTUP_OBJECT
\ VS_DOTNET_TARGET_FRAMEWORK_VERSION
\ VS_DPI_AWARE
\ VS_GLOBAL_KEYWORD

View File

@@ -394,6 +394,7 @@ Properties on Targets
/prop_tgt/VS_DOTNET_REFERENCEPROP_refname_TAG_tagname
/prop_tgt/VS_DOTNET_REFERENCES
/prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL
/prop_tgt/VS_DOTNET_STARTUP_OBJECT
/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION
/prop_tgt/VS_DPI_AWARE
/prop_tgt/VS_GLOBAL_KEYWORD

View File

@@ -0,0 +1,21 @@
VS_DOTNET_STARTUP_OBJECT
------------------------
.. versionadded:: 3.24
Sets the startup object property in Visual Studio .NET targets.
The property value defines a full qualified class name (including package
name), for example: ``MyCompany.Package.MyStarterClass``.
If the property is unset, Visual Studio uses the first matching
``static void Main(string[])`` function signature by default. When more
than one ``Main()`` method is available in the current project, the property
becomes mandatory for building the project.
This property only works for Visual Studio 2010 and above;
it is ignored on other generators.
.. code-block:: cmake
set_property(TARGET ${TARGET_NAME} PROPERTY
VS_DOTNET_STARTUP_OBJECT "MyCompany.Package.MyStarterClass")

View File

@@ -0,0 +1,8 @@
vs_dotnet_startup_object_support
--------------------------------
* The :prop_tgt:`VS_DOTNET_STARTUP_OBJECT` target property was added to
tell :ref:`Visual Studio Generators` which startup class shall be used
when the program or project is executed. This is necessary when more
than one ``static void Main(string[])`` function signature is available
in a managed .NET project.

View File

@@ -664,6 +664,14 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile(
}
}
cmValue startupObject =
this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");
if (startupObject && this->Managed) {
Elem e1(e0, "PropertyGroup");
e1.Element("StartupObject", *startupObject);
}
switch (this->ProjectType) {
case VsProjectType::vcxproj: {
std::string const& props =
@@ -927,6 +935,12 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
break;
}
e1.Element("OutputType", outputType);
cmValue startupObject =
this->GeneratorTarget->GetProperty("VS_DOTNET_STARTUP_OBJECT");
if (startupObject) {
e1.Element("StartupObject", *startupObject);
}
}
for (const std::string& config : this->Configurations) {

View File

@@ -83,6 +83,7 @@ else()
run_UnityBuildPCH()
endif()
run_cmake(VsDotnetStartupObject)
run_cmake(VsDotnetTargetFramework)
run_cmake(VsDotnetTargetFrameworkVersion)
run_cmake(VsNoCompileBatching)

View File

@@ -0,0 +1,22 @@
set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj")
if(NOT EXISTS "${vcProjectFile}")
set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
return()
endif()
set(startupObjectSet FALSE)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "^ *<StartupObject[^>]*>([^<>]+)</StartupObject>$")
if("${CMAKE_MATCH_1}" STREQUAL "MyCompany.Package.MyStarterClass")
message(STATUS "foo.csproj has StartupObject class set")
set(startupObjectSet TRUE)
endif()
endif()
endforeach()
if(NOT startupObjectSet)
set(RunCMake_TEST_FAILED "StartupObject not found or not set correctly.")
return()
endif()

View File

@@ -0,0 +1,10 @@
enable_language(CSharp)
if(NOT CMAKE_CSharp_COMPILER)
return()
endif()
set(CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION "v4.6.1")
add_executable(foo foo.cs)
set_target_properties(foo PROPERTIES VS_DOTNET_STARTUP_OBJECT "MyCompany.Package.MyStarterClass")

View File

@@ -3,6 +3,7 @@ include(RunCMake)
run_cmake(VsDotnetSdkCustomCommandsTarget)
run_cmake(VsDotnetSdkCustomCommandsSource)
run_cmake(VsDotnetSdkStartupObject)
run_cmake(DotnetSdkVariables)
function(run_VsDotnetSdk)

View File

@@ -0,0 +1,22 @@
set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj")
if(NOT EXISTS "${vcProjectFile}")
set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
return()
endif()
set(startupObjectSet FALSE)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "^ *<StartupObject[^>]*>([^<>]+)</StartupObject>$")
if("${CMAKE_MATCH_1}" STREQUAL "CSharpOnly.CSharpOnly")
message(STATUS "foo.csproj has StartupObject class set")
set(startupObjectSet TRUE)
endif()
endif()
endforeach()
if(NOT startupObjectSet)
set(RunCMake_TEST_FAILED "StartupObject not found or not set correctly.")
return()
endif()

View File

@@ -0,0 +1,11 @@
enable_language(CSharp)
if(NOT CMAKE_CSharp_COMPILER)
return()
endif()
set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk")
set(CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION "net5.0")
add_executable(foo csharponly.cs lib1.cs)
set_target_properties(foo PROPERTIES VS_DOTNET_STARTUP_OBJECT "CSharpOnly.CSharpOnly")