在Windows

时间:2016-07-18 09:46:16

标签: c++ cmake cmake-gui

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

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

Test_example
- /包括
- /库
- /编译
-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中打开我的项目解决方案时,我可以看到动态和静态库都已添加到链接器 - >输入 - >其他依赖项。但是,当我尝试构建项目时,我有未解析的外部依赖项,它们是静态库中的方法 你们中有谁知道最有效的方法是什么?非常感谢提前!

2 个答案:

答案 0 :(得分:2)

这里有几个问题。

与您在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文件出现问题。使用您获得的确切链接器错误打开一个新问题。

答案 1 :(得分:1)

以下是我们的工作方式:

首先,将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