11

I have this simple CMake file

cmake_minimum_required(VERSION 2.8)
project(test)
set(SOURCES source.cpp)
add_executable(test ${SOURCES})

where source.cpp is a simple hello world program. I then generate the Visual Studio project

cmake -G"Visual Studio 14 2015" ..\Sources  

The generated Visual Studio project has the following libraries, under Configuration Properties > Linker > Input > Additional Dependencies:

kernel32.lib
user32.lib
gdi32.lib
winspool.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
comdlg32.lib
advapi32.lib

If I remove these libraries I can still successfully build and run the hello world.

Why does CMake add all these libraries and what can I do to not have them in my projects?

Ali
  • 1,001
  • 2
  • 14
  • 32
  • 4
    Those are all of the standard Windows OS libraries (that connect to the Windows kernel, user, and GDI DLLs). Many (most) of them are required for any Windows application that does anything more than write *Hello, world* to the console. – Ken White Dec 30 '16 at 18:11
  • 1
    @KenWhite OK, but if they are needed why I can still run my project without linking them? – Ali Dec 30 '16 at 18:14
  • 2
    Because you're writing a simple *Hello world* application, presumably. – Ken White Dec 30 '16 at 18:24
  • 2
    There seems to be a CMAKE_STANDARD_LIBRARIES variable. Mabey you can modify it to link only against your preferred libraries. – Vertexwahn Dec 31 '16 at 00:59
  • 2
    @Vertexwahn Yes, you are right. But `CMAKE_STANDARD_LIBRARIES` seems to be empty. The variables that I could change are `CMAKE_CXX_STANDARD_LIBRARIES` and `CMAKE_C_STANDARD_LIBRARIES`. If you change your comment to an answer I will accept it. – Ali Dec 31 '16 at 12:55

3 Answers3

4

As commented by @Vertexwahn those are the defaults defined from CMake by CMAKE_CXX_STANDARD_LIBRARIES_INIT in CMakeCXXInformation.cmake.

I just wanted to add a simple AdditionalDependencies macro replacement found here:

cmake_minimum_required(VERSION 3.0)

file(
    WRITE "${CMAKE_BINARY_DIR}/MakeRulesOverwrite.cmake"
[=[
    if (MSVC)        
        set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "%(AdditionalDependencies)")
    endif()
]=]
)
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_BINARY_DIR}/MakeRulesOverwrite.cmake")

project(test)
...

References

Community
  • 1
  • 1
Florian
  • 39,996
  • 9
  • 133
  • 149
  • Wow, very nice. Didn't know about `CMAKE_USER_MAKE_RULES_OVERRIDE`. Could you also add a link to what `[=[`/`]=]` does? – Ali Dec 31 '16 at 16:09
  • 3
    @Ali This part is called [Bracket Argument](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#bracket-argument) and does just take everything between the `[=[`/`]=]` brackets as-is (including the indentation and newlines). I use those if I e.g. directly want to write the content of another text file. – Florian Jan 01 '17 at 14:31
  • This didn't work for me on Windows/MSYS2. I mean the standard libraries are still set and passed to the toolchain. – legends2k Dec 04 '22 at 06:17
1

The MSVC linker doesn't link libraries that are not needed, even if specified on the command-line. You can check it in Dependency Walker or dumpbin. E.g., cmake passes "gdi32.lib" to the linker, but if it's not needed, it won't be present in the resulting executable. Whether you link manually, or let cmake do it, the resulting libraries are exactly the same, I compared them. Linking manually:

Command-line:

... -DCMAKE_EXE_LINKER_FLAGS_RELEASE:STRING="/INCREMENTAL:NO /OPT:REF,ICF /LTCG" -DCMAKE_C_STANDARD_LIBRARIES:STRING=""

cmakelists.txt :

set_target_properties(XXX PROPERTIES LINKER_LANGUAGE C)

target_link_libraries(XXX PUBLIC
    oleacc
    user32
    shell32
    ole32
)

So I had to pass all libraries to the linker myself. If I let cmake do it, I only need to pass "oleacc.lib" to it, other libraries are handled by cmake:

 link.exe ... oleacc.lib user32.lib shell32.lib ole32.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib

dumpbin /imports "c:\windows\system32\ietab.exe"

Section contains the following imports:

    oleacc.dll
    user32.dll
    shell32.dll
    ole32.dll
    kernel32.dll
    msvcp140.dll
    vcruntime140.dll

See? Same libraries as with manual linking.

WRFan
  • 147
  • 1
  • 3
0

If you need to force linker to add some static libraries, and target_link_libraries does not work, you can try this workaround:

set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} AdvAPI32.Lib")

— Here we add AdvAPI32.Lib.

  • 1
    Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P May 29 '22 at 10:52