How to prevent CMake linking system libraries?

I’ll use CMake’s example project as an example. So I have this:

cmake_minimum_required(VERSION 3.10)

# set the project name
project(Tutorial)

# add the executable
add_executable(Tutorial tutorial.h)

set_target_properties(Tutorial PROPERTIES LINKER_LANGUAGE CXX)

After I generate the solution, when I open the solution in Visual Studio and go to Project Properties - Configuration Properties - Linker - Input - Additional Dependencies, I see that it links a lot of libraries :

I’d like to prevent user32.lib from linking for this specific project(not for every project in the solution). I tried googling and found this thread: How to avoid linking to system libraries. But I couldn’t find a solution.

The reason I’d like to do this is because I’m trying to not link user32.lib in my test project, so I can do the link substitution(also known as link seam) technique to be able to provide my own implementation in the test project, to mock the system calls to be able to test classes that do these system calls.
It already works: I removed the library in the Visual Studio’s project properties(as well as added it to the list in the Ignore Specific Default Libraries property), but the problem is that every time the solution is regenerated, the linking of the library gets restored.

It seems it comes from CMAKE_<LANG>_STANDARD_LIBRARIES_INIT. I think this is a project-wide variable and can’t really be removed for just some targets as it is part of the toolchain rather than target properties. You might be able to remove it from the list and add it where needed to all other targets though.

Cc: @brad.king in case there’s some more canonical way to do this.

1 Like

Thanks for the answer. I managed to fixed it.

I just tried to add SET(CMAKE_CXX_STANDARD_LIBRARIES_INIT "") line before project(Tutorial) line and it didn’t change anything: all the libraries were still there.

Then I googled CMAKE_<LANG>_STANDARD_LIBRARIES_INIT and found this stack overflow question: Why CMake adds unnecessary libraries to Visual studio project?.

In the comments the guy who asked the question said he could change the CMAKE_CXX_STANDARD_LIBRARIES variable. I set this one to be empty, too: SET(CMAKE_CXX_STANDARD_LIBRARIES "") and this time it worked!

Also, the whole solution keeps working: it actually still links all those libraries because of %(AdditionalDependencies) and the Inherit from parent or projects defaults checkbox:

And now I can actually exclude the user32.lib from linking in my test project with:
SET_TARGET_PROPERTIES(${MY_PROJECT_NAME} PROPERTIES LINK_FLAGS “/NODEFAULTLIB:User32.lib”)

And provide my own mock implementations.

I think it might be a mistake to explicitly link all those libraries like CMake does now, because Microsoft’s build system already links all of those by default, there’s no need to link them manually and, apparently, it only interferes if I wanna change something, like in my case. I think a good default value for this variable would be “”, because it just works out of the box and everything is still linked.

There’s a compatibility hazard here in that some projects might be relying on the libraries being there. Particularly for those not using Visual Studio. But I suppose that it’s something to consider at least.

FWIW, target_link_options is probably better here.