是否链接已构建的静态库而不是使用add_subdirectory
Linking against built static libraries rather than using add_subdirectory?
给定一个具有"app"answers"lib"同级目录的项目,其中"app"根据"lib"构建的(静态)库构建可执行文件。我想要的是,正常的构建过程只构建库,但如果我构建"应用程序",它会同时构建"lib"answers"app"。
我现在正在做的是,在app
中,我将lib
和add_subdirectory
包括在内,但无论出于何种原因,这都是通过一种我不知道的机制将所有的lib
的间接依赖关系拉入链接行。我喜欢的是让我的应用程序只构建libmylib.a
和libmylib.pc
,然后app
可以从libmylib.pc
计算自己的链接线(或手动指定),但我不确定是如何做到的。
下面是我现在设置的一个最低限度的工作示例:
lib/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")
app/CMakeLists.txt
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")
为了获得一个有效的例子,这里有一些源文件在库中拉入libssl
(但该函数在应用程序中没有使用)-我把它们放在注册表中,因为它们只是为了完整性而包含的,我不想混淆问题文本:
- lib/map_printer.cpp
- lib/map_printer.hpp
- app/main.cpp
问题是,当我cmake app
然后执行make VERBOSE=1
时,生成的链接器命令是:
/usr/lib/hardening-wrapper/bin/c++ CMakeFiles/myapp.dir/main.cpp.o -o myapp build/libmylib.a -lssl
但我没有在app
中的任何位置指定-lssl
。通常情况下,这是可以的,但在我的real应用程序中,由于间接依赖关系,-lssl
和其他几个不必要的符号被包含为.so文件。当我手动从链接器命令中删除它们时,任务构建和运行都很好。理想情况下,我会将构建的.a
及其.pc
文件(本例中未生成)拉入,如果必须拉入多余的依赖项,我可以手动调整链接行,但使用这种方法,链接器标志(可能还有其他东西)会以某种我不理解的方式从lib
范围中泄漏出来。
链接就是要解析符号,以便最终目标(独立的可执行文件或共享对象)拥有启动所需的一切。当你只依赖于一个库或一组库,而这些库又不依赖于其他库时,事情就很简单了。对于任何中等规模或更大规模的项目来说,这种情况都不太可能发生。根本问题是如何处理可传递的依赖关系,例如程序直接使用的东西的依赖关系。
CMake了解所有这些,并且设计为使您在不了解整个依赖关系图的情况下使用库变得简单。如果查看target_link_libraries
的文档,您将看到所描述的PRIVATE
、PUBLIC
和INTERFACE
关键字。这允许您描述构建库时所需的库的私有需求(编译定义、编译参数、依赖库等)。公共部分允许您指定库及其从属(使用者)需要的东西。接口部分允许您指定从属项所需的内容,但不能指定库本身。命令CCD_ 22和CCD_。
所有这些的结果是,在CMake中正确声明了依赖项后,该依赖项的客户端只需在自己的target_link_libraries
命令中将其添加到依赖项列表中,就可以自然地获取所有编译定义,包括成功编译和链接所需的目录和临时链接依赖项。
CppCon 2017演示文稿Modern CMake模块化设计对此进行了更详细的介绍。
- Visual Studio - Cmake Project - Add NetCDF
- 在 atomic() 中 ++、add operation 和 fetch_add() 有什么区别
- wxImageList::Add()始终返回0
- 函数 C::add() 中不允许将'C *'隐式转换为'A *'
- C++有"not equal compare and exchange"或"fetch add on not equal"吗?
- gRPC trace.cc 的方法 TraceFlagList::Add(TraceFlag* flag) 使其链接列表
- 如何将用户定义的格式标志"add" basic_ostream?
- 'Cannot add two pointers'添加带有 WCHAR 的 LPCWSTR
- 在创建完整对象之前编写 if-can-add check 方法的正确方法?
- CMake add library libpq (postgreSQL) mac c++ clion
- 收到错误:C3867 '<int>Template_class::add':非标准语法;将指针指向带有模板的函数时
- 呼叫'php :: Extension :: add()没有匹配函数
- 使用intel内联汇编程序对bigint-add进行进位编码
- C++ 中头文件中的 Add 方法出错
- 二进制'+=':未找到采用类型 'Add' C++ 的全局运算符
- 如果我们使用链表数组来实现哈希表,则可以以不需要遍历的方式实现"add"。这是真的还是假的?
- 为什么 cmake 在定义 CXX 时忽略 ADD(SYSTEM) 头文件?
- "QFileSystemWatcher: failed to add paths"但仍然有效
- LNK2019反对CArray Add、GetAt、GetSize,所有包含都存在
- Add argc for Windows cmd