From d89af11f89fe1a76e3c48e3320a541c58b794c72 Mon Sep 17 00:00:00 2001 From: Florian Schweiger Date: Fri, 8 Apr 2022 13:01:57 +0200 Subject: VS: Add StartupObject property for managed .NET projects --- Auxiliary/vim/syntax/cmake.vim | 1 + Help/manual/cmake-properties.7.rst | 1 + Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst | 21 +++++++++++++++++++++ .../dev/vs_dotnet_startup_object_support.rst | 8 ++++++++ Source/cmVisualStudio10TargetGenerator.cxx | 14 ++++++++++++++ Tests/RunCMake/VS10Project/RunCMakeTest.cmake | 1 + .../VS10Project/VsDotnetStartupObject-check.cmake | 22 ++++++++++++++++++++++ .../VS10Project/VsDotnetStartupObject.cmake | 10 ++++++++++ Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake | 1 + .../VsDotnetSdkStartupObject-check.cmake | 22 ++++++++++++++++++++++ .../VsDotnetSdk/VsDotnetSdkStartupObject.cmake | 11 +++++++++++ 11 files changed, 112 insertions(+) create mode 100644 Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst create mode 100644 Help/release/dev/vs_dotnet_startup_object_support.rst create mode 100644 Tests/RunCMake/VS10Project/VsDotnetStartupObject-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsDotnetStartupObject.cmake create mode 100644 Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject-check.cmake create mode 100644 Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject.cmake diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index c53d094..8773446 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -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 diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index fbddd8b..8c2f8c4 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -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 diff --git a/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst new file mode 100644 index 0000000..5212293 --- /dev/null +++ b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst @@ -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") diff --git a/Help/release/dev/vs_dotnet_startup_object_support.rst b/Help/release/dev/vs_dotnet_startup_object_support.rst new file mode 100644 index 0000000..1f0672f --- /dev/null +++ b/Help/release/dev/vs_dotnet_startup_object_support.rst @@ -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. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 276eccf..cf0cb17 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -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) { diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 273b9d5..ee8821a 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -83,6 +83,7 @@ else() run_UnityBuildPCH() endif() +run_cmake(VsDotnetStartupObject) run_cmake(VsDotnetTargetFramework) run_cmake(VsDotnetTargetFrameworkVersion) run_cmake(VsNoCompileBatching) diff --git a/Tests/RunCMake/VS10Project/VsDotnetStartupObject-check.cmake b/Tests/RunCMake/VS10Project/VsDotnetStartupObject-check.cmake new file mode 100644 index 0000000..b3e5e37 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDotnetStartupObject-check.cmake @@ -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 "^ *]*>([^<>]+)$") + 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() diff --git a/Tests/RunCMake/VS10Project/VsDotnetStartupObject.cmake b/Tests/RunCMake/VS10Project/VsDotnetStartupObject.cmake new file mode 100644 index 0000000..8a0ec5e --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDotnetStartupObject.cmake @@ -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") diff --git a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake index b174c25..9c9074e 100644 --- a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake +++ b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake @@ -3,6 +3,7 @@ include(RunCMake) run_cmake(VsDotnetSdkCustomCommandsTarget) run_cmake(VsDotnetSdkCustomCommandsSource) +run_cmake(VsDotnetSdkStartupObject) run_cmake(DotnetSdkVariables) function(run_VsDotnetSdk) diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject-check.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject-check.cmake new file mode 100644 index 0000000..e81de30 --- /dev/null +++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject-check.cmake @@ -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 "^ *]*>([^<>]+)$") + 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() diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject.cmake new file mode 100644 index 0000000..9ccd4f2 --- /dev/null +++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkStartupObject.cmake @@ -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") -- cgit v0.12