Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why CMake adds unnecessary libraries to Visual studio project?

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?

like image 946
Ali Avatar asked Dec 30 '16 17:12

Ali


2 Answers

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

  • CMAKE_USER_MAKE_RULES_OVERRIDE
  • what is %(AdditionalDependencies) macro?
  • Change default value of CMAKE_CXX_FLAGS_DEBUG and friends in CMake
like image 130
Florian Avatar answered Oct 15 '22 21:10

Florian


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.

like image 36
WRFan Avatar answered Oct 15 '22 22:10

WRFan