【问题标题】:Linking both third party precompiled dynamic and static libaries in Windows在 Windows 中链接第三方预编译的动态和静态库
【发布时间】:2016-07-18 09:46:15
【问题描述】:

最近,我一直在使用 cmake 作为我的项目的生成器。我已经成功生成了许多 vtk 和其他应用程序项目。但是,我现在在尝试链接动态和静态预编译库时遇到了问题。特别是,我获得了一些动态预编译的第三方 dll 以及它们各自的 .lib 文件。此外,我正在尝试将一些静态预编译库(仅 .lib 文件)链接到我的项目,以便检查软件许可证。

假设我的项目名为 test_example,我在 libs 目录中有一些预编译的动态库。我的项目目录的结构是:

测试示例
-/包括
-/库
-/构建
-CMakeLists.txt

链接动态库的CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 2.8.9)
project (test_example)
set(CMAKE_BUILD_TYPE Release)

#For the shared libraries:
set (PROJECT_LINK_LIBS dynamic_1.dll dynamic_2.dll )
set (PROJECT_LINK_DIR ${test_example_SOURCE_DIR}/libs/)
set (PROJECT_INCLUDE_DIR ${test_example_SOURCE_DIR}/include/)

link_directories(${PROJECT_LINK_DIR})
include_directories(${PROJECT_INCLUDE_DIR})

add_executable(test_example test_example.cpp)
target_link_libraries(test_example ${PROJECT_LINK_LIBS})  

当我使用这个 cmake 列表生成项目时,我可以成功地使用预编译的 dll 中的方法。但是,我也没有找到一种方法来链接我的静态库。假设我有一个名为 test_licence.lib 的静态库。我是否也应该将它放在 libs 文件夹中,并像使用动态一样简单地引用它?当我这样做并在 Visual Studio 中打开我的项目解决方案时,我可以看到动态库和静态库都已添加到 Linker-->Input-->Additional DEpendencies。但是,当我尝试构建项目时,我有未解决的外部依赖项,它们是静态库中的方法。
你们有谁知道实现这一目标的最有效方法是什么?非常感谢!

【问题讨论】:

    标签: c++ cmake cmake-gui


    【解决方案1】:

    这里有几个问题。

    与您在 VS 中使用的 CMake prefers absolute paths for linking 不同,而不是设置链接目录并提供相对路径。

    此外,您不会链接到 .dll 文件。 Dll 在运行时加载,而不是在链接时加载。许多 dll 附带导入库(以 .lib 结尾),它们会自动为您处理运行时加载。 These are the ones you should link against.

    也尽量不要在 CMake 代码中硬编码库。这里的问题是,如果出现问题,最终会出现一个神秘的链接器错误。您应该改用find_library,如果出现问题,这通常会使 CMake 提早抱怨。

    您的 CMake 脚本的更简洁版本将类似于

    cmake_minimum_required(VERSION 2.8.9)
    project (test_example)
    
    # note setting the build type does nothing on a visual studio build
    # and should probably be left to the user for other generators
    set(CMAKE_BUILD_TYPE Release)
    
    #For the shared libraries:
    # this call will succeed if it finds a dynamic_1.lib file
    find_library(DYNAMIC_LIB1 dynamic_1 HINTS ${test_example_SOURCE_DIR}/libs)
    if(NOT DYNAMIC_LIB1)
        message(FATAL_ERROR "Library dynamic_1 was not found!")
    endif()
    find_library(DYNAMIC_LIB2 dynamic_2 HINTS ${test_example_SOURCE_DIR}/libs)
    if(NOT DYNAMIC_LIB2)
        message(FATAL_ERROR "Library dynamic_2 was not found!")
    endif()
    
    # for the static libraries:
    # basically the same; again this looks for a static_1.lib file
    find_library(STATIC_LIB1 static1 HINTS ${test_example_SOURCE_DIR}/libs)
    if(NOT STATIC_LIB1)
        message(FATAL_ERROR "Library static_1 was not found!")
    endif()
    
    
    set (PROJECT_INCLUDE_DIR ${test_example_SOURCE_DIR}/include/)
    
    include_directories(${PROJECT_INCLUDE_DIR})
    
    add_executable(test_example test_example.cpp)
    target_link_libraries(test_example ${DYNAMIC_LIB1} ${DYNAMIC_LIB2} ${STATIC_LIB1})
    

    在 Visual Studio 中仔细检查所有库是否按预期添加为链接器输入。如果您仍然收到链接器错误,则表示您的第三方 .lib 文件有问题。使用您得到的确切链接器错误打开一个新问题。

    【讨论】:

    • 您好,非常感谢您的宝贵回答。你的逻辑更清晰。但是,我仍然得到来自特定静态库的相同未解决的外部。我想这可能是由这个库的构建方式引起的。为了进行测试,我制作了一个静态库和一个动态库,并按照您的方式成功链接它们。顺便说一句,如果我在 lib 目录中有很多动态和静态库,是否有任何更短的方法可以链接到 libs 目录中的所有 *.lib 文件?我知道有一个文件(GLOB ...)命令。如何使用它来链接我的所有 .lib 文件?
    • @gioR 请不要尝试为.lib 文件查找全局 :) 如果这对您来说真的是一个统一的过程,其中唯一的变量是库名称,请将所有库放在一个列表中并foreach 在他们身上。但是不要试图让构建系统找出库名称。那只是在路上自找麻烦。至于您仍然得到的链接器错误:是的,这可能是 lib 构建方式的问题。正如我所说,如果您需要更多帮助,请随时提出另一个问题。
    • ComicSansMS 再次感谢您。 foreach 现在可以完成这项工作。至于链接错误,我发现这些可能来自我用来构建项目的 VS 版本。我有错误 LNK2001:未解析的外部符号 __imp___iob_fuc、未解析的外部符号 _sprintf 等。我读到这可以通过在 VS 14(2015)中重新编译这些库来解决。
    • @gioR 这听起来很合理。在不同 Visual Studio 版本之间编译的库文件are in general not compatible
    【解决方案2】:

    这是我们的做法:

    首先,使用add_library 和最终参数STATIC IMPORTED。然后随后使用set_property 设置IMPORTED_LOCATION 属性,这是构建库的路径。例如,我们像这样拉入 gtest:

    add_library(gtest UNKNOWN IMPORTED)
    set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${binary_dir}/googlemock/gtest/${CMAKE_FIND_LIBRARY_PREFIXES}gtest.a)
    

    然后,gtest 是您构建系统中的一个已知库,您可以稍后正常链接它,只需执行

    target_link_libraries(target-name gtest)
    

    另请参阅:Cmake imported libraries documenation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 2015-07-14
      • 1970-01-01
      相关资源
      最近更新 更多