在动态库中包含依赖项



我正在用c++构建一个库,需要包含几个库,其中一些是GLEW, SDL2和GLM。我正在使用CMake来构建这个库,并且已经成功地设置了(至少据我所知)一个充分做到这一点的CMakeLists.txt,但目前没有依赖关系。我想知道将这些外部库添加到我自己的库的适当约定,记住不同机器上的人可能正在使用这个库(即未定义的文件结构/本地安装)。

这是我当前的CMakeLists.txt:

cmake_minimum_required(VERSION 3.8)
project(mylib VERSION 1.0.1 LANGUAGES CXX)
set (DEFAULT_BUILD_TYPE "Release")
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.")
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
include (GNUInstallDirs)
set (SOURCE_FILES "src/driver.cpp")
add_library(${PROJECT_NAME} ${SOURCE_FILES})
target_include_directories(
${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE src
)
set_target_properties (
${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1
)
install (
TARGETS ${PROJECT_NAME} EXPORT mylibConfig
ARCHIVE  DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY  DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME  DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install (
DIRECTORY include/ 
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
)
install (
EXPORT mylibConfig 
DESTINATION share/mylib/cmake
)
export (
TARGETS ${PROJECT_NAME}
FILE mylibConfig.cmake
)

如果你同样注意到我当前文件中的任何关键错误/错误,请随时让我知道,但更重要的事情是我应该如何正确地包括这些库。

动态链接glw、SDL2和GLM,可以使用find_package命令。

find_package(GLEW REQUIRED)
find_package(SDL2 REQUIRED)
find_package(glm REQUIRED)

然后,在你调用了add_library之后,你需要将库链接到你的库:

target_link_libraries(mylib PRIVATE GLEW::GLEW SDL2::SDL2 glm::glm)

如果你在你的API中暴露任何这些依赖,那么你可以用PUBLIC(而不是PRIVATE)来调用target_link_libraries来代替这些依赖。

考虑使用像conan这样的包管理器。我去柯南中心找过你,那里有治疗你依赖性的方法。你可以遵循入门指南,它应该可以工作。

在CMake中有很多处理依赖的方法,

手动
  • 使用子模块
  • 使用fine_package

但这里我只参考两个简单且可移植的方法

<<p>

子模块/strong>如果依赖项存在于github/gitlab或一些使用的地方,则git,然后可以方便地使用子模块方法

与子模块你的依赖可以随时更新(通过他们的github/gitlab页面),但你不能改变他们自己,因为你的改变将是本地的(就像每次你克隆一个存储库,你的改变将是本地的,除非你做一个拉取请求或贡献者)。

使用

为了使用子模块,您需要在您的.CMakeLists.txt文件中包含此部分:

#--------------------------------------------------------------
# submodule section
# here we use the following code to support
# old versions of git(that don't download submodule
# contents automatically).
#--------------------------------------------------------------
# [[[
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
if(GIT_SUBMODULE)
message(STATUS "Submodule update")
execute_process(
COMMAND ${GIT_EXECUTABLE} submodule update
--init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT
)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(FATAL_ERROR "Git submodule update --init failed with ${GIT_SUBMODULE_RESULT}, Please checkout submodules")
endif()
endif()
endif()
# ]]]
#

这很容易为您自动运行git submodule update --init --recursive。然后你可以像这样使用子模块:

# your submodule directory that has a main .CMakeLists.txt file inside it.
add_subdirectory("YOUR_SUBMODULE_DIRECTORY")
target_include_directories(
executable_or_library_name PRIVATE
YOUR_SUBMODULE_DIRECTORY/include
)

下面是子模块的一个例子。

find_package

如果依赖项有find_package支持,那么你应该使用find_package方法,特别是如果它有这个支持,并且它不在github/gitlab或使用git的地方,你应该使用这个方法。

使用

它也很容易使用,只需一个命令:

find_package(dependency)
target_include_directories(YOUR_TARGET 
"${dependency_INCLUDE_DIR}"
# ... your other include directories
)
target_link_libraries(YOUR_TARGET 
"${dependency_LIBRARIES}"
# ... your other libraries to add
)

有许多可能的参数,如REQUIRED和COMPONENTS,在cmake官方网站 中有解释。不是这个问题的一部分,但很有用(旁注)

我通常把这个放在我的主。cmakelists .txt的末尾,以支持emacs/vim/…以及所有使用LSP查找符号的编辑器:

#--------------------------------------------------------------
# Generating compile_commands.json file for lsp servers
#--------------------------------------------------------------
# [[[
option(CMAKE_EXPORT_COMPILE_COMMANDS "Generate lsp command file" ON)
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json")
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json
${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json
)
endif()
# ]]]
#--------------------------------------------------------------

最新更新