Skip to content

C++ linker flags are unset when a C# project is also present

I've got a C++/CLI project which depends on Nuget packages, so to get around the inability to make it depend on them directly, I have a dummy C# project which depends on the packages, and then the C++/CLI part depends on that (via add_dependencies as it doesn't directly need to link with the dummy project). I noticed that .pdb files weren't being produced in Debug or RelWithDebInfo.

This is because GenerateDebugInformation is being set to false in the .vcxproj for all configurations, which, in turn, is because CMAKE_WHATEVER_LINKER_FLAGS (and configuration-specific versions) are set to an empty string. This is because CMakeInitializeConfigs.cmake is setting these variables based on the _INIT versions before Windows-MSVC.cmake is setting them. I believe this is because CMakeCSharpInformation.cmake is calling cmake_initialize_per_config_variable(CMAKE_EXE_LINKER_FLAGS Flags used by the linker ) (and the same with CMAKE_SHARED_LINKER_FLAGS) without first doing everything it depends on.

A minimal example that reproduces the issue is

cmake_minimum_required(VERSION 3.17)

project(dotnet_project_that_also_exists LANGUAGES CSharp)
add_library(dotnet SHARED main.cs)

project(linker_flag_test)
add_executable(cplusplus main.cpp)

add_dependencies(cplusplus dotnet)

Giving that a basic hello-world C++ file and a blank C# file and building it in Debug/RelWithDebInfo (at least with the Visual Studio 16 2019 generator and CMake 3.17.2) will give you no .pdb file, you'll be able to find <GenerateDebugInformation>false</GenerateDebugInformation> in the linker section of the .vcxproj for all configurations, and if you trace CMake, cmake_initialize_per_config_variable(CMAKE_EXE_LINKER_FLAGS Flags used by the linker ) will be called by CMakeCSharpInformation.cmake before Windows-MSVC.cmake runs.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information