【问题标题】:Why CMake adds unnecessary libraries to Visual studio project?为什么 CMake 会在 Visual Studio 项目中添加不必要的库?
【发布时间】:2016-12-30 17:57:17
【问题描述】:

我有这个简单的 CMake 文件

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

其中 source.cpp 是一个简单的 hello world 程序。然后我生成 Visual Studio 项目

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

生成的 Visual Studio 项目在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

如果我删除这些库,我仍然可以成功构建和运行 hello world。

为什么 CMake 会添加所有这些库,我该怎么做才能在我的项目中不包含它们?

【问题讨论】:

  • 这些都是标准的 Windows 操作系统库(连接到 Windows 内核、用户和 GDI DLL)。任何除了将 Hello, world 写入控制台之外的任何 Windows 应用程序都需要它们中的许多(大部分)。
  • @KenWhite 好的,但是如果需要它们,为什么我仍然可以在不链接它们的情况下运行我的项目?
  • 因为你正在编写一个简单的 Hello world 应用程序,大概。
  • 似乎有一个 CMAKE_STANDARD_LIBRARIES 变量。您可以修改它以仅链接到您喜欢的库。
  • @Vertexwahn 是的,你是对的。但是CMAKE_STANDARD_LIBRARIES 似乎是空的。我可以更改的变量是CMAKE_CXX_STANDARD_LIBRARIESCMAKE_C_STANDARD_LIBRARIES。如果您将评论更改为答案,我会接受。

标签: visual-studio cmake


【解决方案1】:

正如@Vertexwahn 所评论的,这些是CMAKE_CXX_STANDARD_LIBRARIES_INITCMakeCXXInformation.cmake 中从CMake 定义的默认值。

我只是想添加一个简单的AdditionalDependencies 宏替换发现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)
...

参考文献

【讨论】:

  • 哇,非常好。不知道CMAKE_USER_MAKE_RULES_OVERRIDE。您能否也添加一个链接到 [=[/]=] 所做的事情?
  • @Ali 这部分被称为Bracket Argument,它只使用[=[/]=] 括号之间的所有内容(包括缩进和换行符)。如果我使用这些,例如直接想写另一个文本文件的内容。
【解决方案2】:

MSVC 链接器不会链接不需要的库,即使在命令行中指定。您可以在 Dependency Walker 或 dumpbin 中检查它。例如,cmake 将“gdi32.lib”传递给链接器,但如果不需要它,它就不会出现在生成的可执行文件中。无论是手动链接,还是让 cmake 链接,生成的库都是一样的,我对比了一下。手动链接:

命令行:

... -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
)

所以我必须自己将所有库传递给链接器。如果我让cmake做,我只需要传递“oleacc.lib”给它,其他库由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

看到了吗?与手动链接相同的库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多