链接内置静态库而不是使用add_subdirectory?

时间:2017-10-12 20:54:21

标签: c++ build cmake

给出一个项目" app"和" lib"兄弟目录,其中" app"根据" lib"构建的(静态)库构建可执行文件。我喜欢的是正常构建过程只构建库的情况,但是如果我构建" app"它构建了" lib"和" app"。

我现在正在做的是,在app中,我将libadd_subdirectory包括在内,但无论出于什么原因,这都是所有 lib通过我不知道的机制间接依赖于链接线。我喜欢的目的是让我的应用只构建libmylib.alibmylib.pc,然后app可以从{{1}计算自己的链接线(或手动指定),但我不确定它是如何完成的。

这是我现在已经设置的最低工作示例:

LIB /的CMakeLists.txt

libmylib.pc

应用/的CMakeLists.txt

cmake_minimum_required(VERSION 3.8.0)
project(mylib CXX)

find_package(PkgConfig REQUIRED)
pkg_check_modules("mylib" "libssl")

find_package(Boost REQUIRED)
set(LIBDIR "${PROJECT_SOURCE_DIR}")


set(HEADERS "${LIBDIR}/map_printer.hpp")
set(SOURCES "${LIBDIR}/map_printer.cpp")

add_library("mylib" "${SOURCES}")

target_include_directories("mylib" PUBLIC "${LIBDIR}"
                                          "${Boost_INCLUDE_DIR}"
                                          "${mylib_INCLUDE_DIRS}")
target_link_libraries("mylib" "${Boost_LIBRARIES}" "${mylib_LIBRARIES}")

install(TARGETS "mylib" ARCHIVE DESTINATION "lib")
install(FILES ${HEADERS} DESTINATION "include")

为了得到一个工作示例,这里有一些在lib中引入cmake_minimum_required(VERSION 3.8.0) project(mylib CXX) set(APPDIR "${PROJECT_SOURCE_DIR}") set(LIBDIR "${APPDIR}/../lib") set(SOURCES "${APPDIR}/main.cpp") add_subdirectory("${LIBDIR}" "build") list(APPEND LIBS "mylib") add_executable("myapp" "${SOURCES}") target_include_directories("myapp" PUBLIC "${LIBDIR}") target_link_libraries("myapp" "${LIBS}") install(TARGETS "myapp" DESTINATION "bin") 的源文件(但是这个函数没有在应用程序中使用) - 我把它们放在gists中因为它们仅用于完整性和我不想弄乱问题文本:

问题是,当我libssl然后执行cmake app时,生成的链接器命令是:

make VERBOSE=1

但我没有在/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/myapp.dir/main.cpp.o -o myapp build/libmylib.a -lssl 中的任何位置指定-lssl。通常情况下这很好,但在我的真正的应用程序中,由于间接依赖性,app和其他几个不必要的符号被包含为.so文件。当我手动从链接器命令中删除它们时,任务构建并运行正常。理想情况下,我会使用-lssl文件(在此示例中未生成)来提取已构建的.a,如果必须提取过多的依赖项,我可以手动调整链接行,但是使用此方法,链接器标志(以及可能的其他内容)以某种我不理解的方式从.pc范围泄漏。

1 个答案:

答案 0 :(得分:0)

链接完全是为了解决符号,以便最终目标(独立可执行文件或共享对象)具有需要启动的所有内容。当您只依赖于单个库或者依赖于其他任何东西的库集合时,事情就变得简单了。对于任何中等或较大尺寸的程序,这种情况不太可能发生。根本问题是如何处理传递依赖,例如程序直接使用的东西的依赖关系。

CMake了解所有这些,旨在使您在不了解整个依赖关系图的情况下使用库变得简单。如果您查看target_link_libraries的文档,则会看到所述的PRIVATEPUBLICINTERFACE个关键字。这允许您描述构建库时所需的库的私有要求(编译定义,编译参数,依赖库等)。公共部分允许您指定库及其依赖(消费者)所需的内容。界面部分允许您指定依赖者需要的内容,但不能指定库本身。命令target_compile_definitionstarget_include_directories的运作方式相似。

所有这一切的结果是,在CMake中正确声明的依赖项,该依赖项的客户端只是将其添加到其自己的target_link_libraries命令中的依赖项列表中,它自然会获取所有编译定义,包括成功编译和链接所需的目录和暂时链接依赖。

CppCon 2017演讲Modern CMake for modular design更详细地介绍了这一点。