From 91b9db90e5ba33aac16dc777a2c5ef2c31093ca1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 17 Dec 2025 16:15:57 -0500 Subject: VS: Restore subsystem link flag for DLLs In commit 99d09ec45a (VS: Suppress MSBuild default link flags not specified by project or user, 2025-06-17, v4.1.0-rc1~6^2) we removed our default `-subsystem:...` link flag from `SHARED` and `MODULE` libraries in Visual Studio generators for consistency with command-line generators. However, unlike other flag suppressions for #27004, this change did not just suppress MSBuild defaults, but actually changed flags the generator was previously adding itself. For the linker subsystem flag, consistency across generators should perhaps achieved by adding the flag in other generators instead of removing it from Visual Studio generators. Restore the previous behavior pending further investigation. Issue: #27466 Fixes: #27464 --- Source/cmVisualStudio10TargetGenerator.cxx | 47 ++++++++++------------ .../VS10Project/VsDefaultFlags-check.cmake | 36 ++++++----------- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 775e568..88e584f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -4576,35 +4576,32 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( } if (this->MSTools) { - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - // Specify an entry point for executables. - if (this->GeneratorTarget->IsWin32Executable(config)) { - if (this->GlobalGenerator->TargetsWindowsCE()) { - linkOptions.AddFlag("SubSystem", "WindowsCE"); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (this->ClOptions[config]->UsingUnicode()) { - linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup"); - } else { - linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup"); - } + if (this->GeneratorTarget->IsWin32Executable(config)) { + if (this->GlobalGenerator->TargetsWindowsCE()) { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + if (this->ClOptions[config]->UsingUnicode()) { + linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup"); + } else { + linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup"); } - } else { - linkOptions.AddFlag("SubSystem", "Windows"); } } else { - if (this->GlobalGenerator->TargetsWindowsCE()) { - linkOptions.AddFlag("SubSystem", "WindowsCE"); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (this->ClOptions[config]->UsingUnicode()) { - linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup"); - } else { - linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup"); - } - } - } else { - linkOptions.AddFlag("SubSystem", "Console"); - }; + linkOptions.AddFlag("SubSystem", "Windows"); } + } else { + if (this->GlobalGenerator->TargetsWindowsCE()) { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + if (this->ClOptions[config]->UsingUnicode()) { + linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup"); + } else { + linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup"); + } + } + } else { + linkOptions.AddFlag("SubSystem", "Console"); + }; } if (cmValue stackVal = this->Makefile->GetDefinition( diff --git a/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake b/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake index afecdf3..4cdad74 100644 --- a/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake @@ -38,12 +38,12 @@ macro(VsDefaultCompilerFlags_check tgt) endif() endmacro() -macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) +macro(VsDefaultLinkerFlags_check tgt) set(HAVE_DataExecutionPrevention 0) set(HAVE_ImageHasSafeExceptionHandlers 0) set(HAVE_LinkErrorReporting 0) set(HAVE_RandomizedBaseAddress 0) - set(HAVE_SubSystem 0) + set(HAVE_SubSystem_Empty 0) set(HAVE_SubSystem_Console 0) file(STRINGS "${vcProjectFile}" lines) @@ -61,7 +61,7 @@ macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) set(HAVE_RandomizedBaseAddress 1) endif() if(line MATCHES "^ *") - set(HAVE_SubSystem 1) + set(HAVE_SubSystem_Empty 1) endif() if(line MATCHES "^ *Console") set(HAVE_SubSystem_Console 1) @@ -88,33 +88,21 @@ macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) return() endif() - if(${needs_subsystem_console}) - if(HAVE_SubSystem) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property.") - return() - endif() - - if(NOT HAVE_SubSystem_Console) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property with 'Console' value.") - return() - endif() - else() - if(NOT HAVE_SubSystem) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property.") - return() - endif() + if(HAVE_SubSystem_Empty) + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property.") + return() + endif() - if(HAVE_SubSystem_Console) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property with 'Console' value.") - return() - endif() + if(NOT HAVE_SubSystem_Console) + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property with 'Console' value.") + return() endif() endmacro() VsDefaultCompilerFlags_check(emptyStatic) VsDefaultCompilerFlags_check(emptyShared) -VsDefaultLinkerFlags_check(emptyShared OFF) +VsDefaultLinkerFlags_check(emptyShared) VsDefaultCompilerFlags_check(main) -VsDefaultLinkerFlags_check(main ON) +VsDefaultLinkerFlags_check(main) -- cgit v0.12 From b6defd96c92060ee2bcca8bd3f73f4fb19a3a516 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 17 Dec 2025 16:15:57 -0500 Subject: VS: Restore subsystem link flag for DLLs In commit 99d09ec45a (VS: Suppress MSBuild default link flags not specified by project or user, 2025-06-17, v4.1.0-rc1~6^2) we removed our default `-subsystem:...` link flag from `SHARED` and `MODULE` libraries in Visual Studio generators for consistency with command-line generators. However, unlike other flag suppressions for #27004, this change did not just suppress MSBuild defaults, but actually changed flags the generator was previously adding itself. For the linker subsystem flag, consistency across generators should perhaps achieved by adding the flag in other generators instead of removing it from Visual Studio generators. Restore the previous behavior pending further investigation. Issue: #27466 Fixes: #27464 --- Source/cmVisualStudio10TargetGenerator.cxx | 47 ++++++++++------------ .../VS10Project/VsDefaultFlags-check.cmake | 36 ++++++----------- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4d0ee2a..9e706a5 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -4630,35 +4630,32 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( } if (this->MSTools) { - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - // Specify an entry point for executables. - if (this->GeneratorTarget->IsWin32Executable(config)) { - if (this->GlobalGenerator->TargetsWindowsCE()) { - linkOptions.AddFlag("SubSystem", "WindowsCE"); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (this->CharSet[config] == MsvcCharSet::Unicode) { - linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup"); - } else { - linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup"); - } + if (this->GeneratorTarget->IsWin32Executable(config)) { + if (this->GlobalGenerator->TargetsWindowsCE()) { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + if (this->CharSet[config] == MsvcCharSet::Unicode) { + linkOptions.AddFlag("EntryPointSymbol", "wWinMainCRTStartup"); + } else { + linkOptions.AddFlag("EntryPointSymbol", "WinMainCRTStartup"); } - } else { - linkOptions.AddFlag("SubSystem", "Windows"); } } else { - if (this->GlobalGenerator->TargetsWindowsCE()) { - linkOptions.AddFlag("SubSystem", "WindowsCE"); - if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - if (this->CharSet[config] == MsvcCharSet::Unicode) { - linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup"); - } else { - linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup"); - } - } - } else { - linkOptions.AddFlag("SubSystem", "Console"); - }; + linkOptions.AddFlag("SubSystem", "Windows"); } + } else { + if (this->GlobalGenerator->TargetsWindowsCE()) { + linkOptions.AddFlag("SubSystem", "WindowsCE"); + if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { + if (this->CharSet[config] == MsvcCharSet::Unicode) { + linkOptions.AddFlag("EntryPointSymbol", "mainWCRTStartup"); + } else { + linkOptions.AddFlag("EntryPointSymbol", "mainACRTStartup"); + } + } + } else { + linkOptions.AddFlag("SubSystem", "Console"); + }; } if (cmValue stackVal = this->Makefile->GetDefinition( diff --git a/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake b/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake index 5a71b30..ac0cbc4 100644 --- a/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake +++ b/Tests/RunCMake/VS10Project/VsDefaultFlags-check.cmake @@ -110,12 +110,12 @@ macro(VsDefaultCompilerFlags_check tgt) endif() endmacro() -macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) +macro(VsDefaultLinkerFlags_check tgt) set(HAVE_DataExecutionPrevention 0) set(HAVE_ImageHasSafeExceptionHandlers 0) set(HAVE_LinkErrorReporting 0) set(HAVE_RandomizedBaseAddress 0) - set(HAVE_SubSystem 0) + set(HAVE_SubSystem_Empty 0) set(HAVE_SubSystem_Console 0) file(STRINGS "${vcProjectFile}" lines) @@ -133,7 +133,7 @@ macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) set(HAVE_RandomizedBaseAddress 1) endif() if(line MATCHES "^ *") - set(HAVE_SubSystem 1) + set(HAVE_SubSystem_Empty 1) endif() if(line MATCHES "^ *Console") set(HAVE_SubSystem_Console 1) @@ -160,33 +160,21 @@ macro(VsDefaultLinkerFlags_check tgt needs_subsystem_console) return() endif() - if(${needs_subsystem_console}) - if(HAVE_SubSystem) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property.") - return() - endif() - - if(NOT HAVE_SubSystem_Console) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property with 'Console' value.") - return() - endif() - else() - if(NOT HAVE_SubSystem) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property.") - return() - endif() + if(HAVE_SubSystem_Empty) + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property.") + return() + endif() - if(HAVE_SubSystem_Console) - set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has a property with 'Console' value.") - return() - endif() + if(NOT HAVE_SubSystem_Console) + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a property with 'Console' value.") + return() endif() endmacro() VsDefaultCompilerFlags_check(emptyStatic) VsDefaultCompilerFlags_check(emptyShared) -VsDefaultLinkerFlags_check(emptyShared OFF) +VsDefaultLinkerFlags_check(emptyShared) VsDefaultCompilerFlags_check(main) -VsDefaultLinkerFlags_check(main ON) +VsDefaultLinkerFlags_check(main) -- cgit v0.12