在 Windows 中链接第三方预编译动态库和静态库
Linking both third party precompiled dynamic and static libaries in Windows
最近,我一直在使用 cmake 作为我项目的生成器。我已经成功生成了许多 vtk 和其他应用程序项目。但是,我现在在尝试 link 动态和静态预编译库时遇到问题。特别是,我获得了一些动态预编译的第三方 dll 以及它们各自的 .lib 文件。此外,我正在尝试 link 一些静态预编译库(仅 .lib 文件)到我的项目中,以检查软件许可证。
假设我的项目名为 test_example 并且我在 libs 目录中有一些预编译的动态库。我的项目目录结构是:
Test_example
-/包括
-/库
-/构建
-CMakeLists.txt
用于 linking 动态库的 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 中的方法。但是,我还没有找到 link 对付我的静态库的方法。假设我有一个名为 test_licence.lib 的静态库。我是否也应该将它放在 libs 文件夹中,然后像处理动态一样简单地引用它?当我这样做并在 Visual Studio 中打开我的项目解决方案时,我可以看到动态库和静态库都已添加到 Linker-->Input-->Additional Dependencies。但是,当我尝试构建项目时,我有未解决的外部依赖项,这些依赖项是静态库中的方法。
你们中有人知道什么是最有效的方法吗?非常感谢!
这是我们的做法:
首先,使用带有最终参数 STATIC IMPORTED
的 add_library
。然后随后使用 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
是您的构建系统中的一个已知库,您以后可以 link 通常只需执行
target_link_libraries(target-name gtest)
这里有几个问题。
与您可能习惯的 VS 不同,,而不是设置 link 目录并给出相对路径。
此外,您不 link 反对 .dll
个文件。 Dll 在运行时加载,而不是在 link 时间加载。许多 dll 附带导入库(以 .lib 结尾),它们会自动为您处理运行时加载。 These are the ones you should link against.
另外尽量不要在 CMake 代码中对库进行硬编码。这里的问题是,如果出现问题,您最终会遇到一个神秘的 linker 错误。您应该改用 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 所有库都按预期添加为 linker 输入。如果您仍然收到 linker 错误,则表示您的第三方 .lib
文件有问题。使用您得到的确切 linker 错误打开一个新问题。
最近,我一直在使用 cmake 作为我项目的生成器。我已经成功生成了许多 vtk 和其他应用程序项目。但是,我现在在尝试 link 动态和静态预编译库时遇到问题。特别是,我获得了一些动态预编译的第三方 dll 以及它们各自的 .lib 文件。此外,我正在尝试 link 一些静态预编译库(仅 .lib 文件)到我的项目中,以检查软件许可证。
假设我的项目名为 test_example 并且我在 libs 目录中有一些预编译的动态库。我的项目目录结构是:
Test_example
-/包括
-/库
-/构建
-CMakeLists.txt
用于 linking 动态库的 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 中的方法。但是,我还没有找到 link 对付我的静态库的方法。假设我有一个名为 test_licence.lib 的静态库。我是否也应该将它放在 libs 文件夹中,然后像处理动态一样简单地引用它?当我这样做并在 Visual Studio 中打开我的项目解决方案时,我可以看到动态库和静态库都已添加到 Linker-->Input-->Additional Dependencies。但是,当我尝试构建项目时,我有未解决的外部依赖项,这些依赖项是静态库中的方法。
你们中有人知道什么是最有效的方法吗?非常感谢!
这是我们的做法:
首先,使用带有最终参数 STATIC IMPORTED
的 add_library
。然后随后使用 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
是您的构建系统中的一个已知库,您以后可以 link 通常只需执行
target_link_libraries(target-name gtest)
这里有几个问题。
与您可能习惯的 VS 不同,
此外,您不 link 反对 .dll
个文件。 Dll 在运行时加载,而不是在 link 时间加载。许多 dll 附带导入库(以 .lib 结尾),它们会自动为您处理运行时加载。 These are the ones you should link against.
另外尽量不要在 CMake 代码中对库进行硬编码。这里的问题是,如果出现问题,您最终会遇到一个神秘的 linker 错误。您应该改用 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 所有库都按预期添加为 linker 输入。如果您仍然收到 linker 错误,则表示您的第三方 .lib
文件有问题。使用您得到的确切 linker 错误打开一个新问题。