在 CMAKE 中使用具有静态依赖项的库
Use library with static dependencies in CMAKE
CMake 中是否有办法将库用于具有不同静态依赖项的多个目标? 为了更好地解释它,请考虑这个最小示例:我想要两个可执行文件:第一个应该打印"YES",第二个应该打印"NO"。为此,我使用libarary"printsth",它打印"某物"。它打印的字符串来自"用户"(printyes 或 printno(提供的头文件。这完全看起来像这样:
├── apps
│ ├── printno
│ │ ├── CMakeLists.txt
│ │ │ add_executable(printno main.cpp)
│ │ │ target_link_libraries(printno PRIVATE printsth)
│ │ │
│ │ ├── main.cpp
│ │ │ #include "printsth/printsth.h"
│ │ │
│ │ │ int main() {
│ │ │ printsth();
│ │ │ return 0;
│ │ │ }
│ │ │
│ │ └── print_usr.h
│ │ #define USR_STRING "NO"
│ │
│ └── printyes
│ │ ├── CMakeLists.txt
│ │ │ add_executable(printyes main.cpp)
│ │ │ target_link_libraries(printyes PRIVATE printsth)
│ │ │
│ │ ├── main.cpp
│ │ │ #include "printsth/printsth.h"
│ │ │
│ │ │ int main() {
│ │ │ printsth();
│ │ │ return 0;
│ │ │ }
│ │ │
│ │ └── print_usr.h
│ │ #define USR_STRING "YES"
│ │
├── extern
│ └── printsh
│ ├── include
│ │ └── printsh
│ │ └── printsh.h
│ │ void printsth();
│ │
│ ├── src
│ │ ├── CMakeLists.txt
│ │ │ add_library(printsth printsth.cpp)
│ │ │ target_include_directories(printsth PUBLIC ../include)
│ │ │
│ │ └── printsh.cpp
│ │ #include "printsth/printsth.h"
│ │ #include "print_usr.h"
│ │ #include <iostream>
│ │
│ │ void printsth() {
│ │ std::cout << USR_STRING << std::endl;
│ │ }
│ │
│ └── CMakeLists.txt
│ cmake_minimum_required(VERSION 3.11...3.16)
│
│ project(printsh
│ VERSION 0.1
│ DESCRIPTION "Print something"
│ LANGUAGES CXX)
│
│ add_subdirectory(src)
│
└── CMakeLists.txt
cmake_minimum_required(VERSION 3.11...3.16)
project(printexamples
VERSION 0.1
DESCRIPTION "Print examples"
LANGUAGES CXX)
add_subdirectory(apps/printyes)
add_subdirectory(apps/printno)
add_subdirectory(extern/printsth)
构建时我显然收到错误
fatal error: print_usr.h: No such file or directory
那么,我可以告诉 CMake 在为 printno 构建 printsh lib 时使用 apps/printno 作为包含目录,并在为 printyes 构建时使用 apps/printyes 作为包含目录吗?
我知道这个例子没有多大意义,很容易摆脱标头依赖项(例如,将自定义字符串作为参数传递给 printsth(((,一切正常。所以这只是一个演示"现实世界"问题的例子,我无法轻易摆脱依赖关系。
在CMake意义上,库目标表示编译一次但可以链接到多个目标(可执行文件或其他库(的库。
由于无法将两个宏定义编译到单个库中,因此需要为每个定义集创建不同的库目标。也就是说,在您的情况下,您需要创建两个库。
对于重复的命令序列,CMake 提供了宏和函数,并使用不同的参数多次调用它们。
你也可以创建一个"参数化"的CMakeLists.txt
,并多次"调用"它(通过add_subdirectory
(:
extern/printsh/src/CMakeLists.txt:
# Requires 'printsth_target' and 'printish_usr_dir' variables to be set.
# The first variable denotes name of the target created,
# the second variable denotes include directory with 'print_usr.h' header.
if (NOT printsth_target)
message(FATAL_ERROR "printsth_target variable is required but is not set.")
endif()
if (NOT printish_usr_dir)
message(FATAL_ERROR "printish_usr_dir variable is required but is not set.")
endif()
# Create a library target with user-provided name
add_library(${printsth_target} printsth.cpp)
target_include_directories(${printsth_target} PUBLIC ../include)
# Add user-provided include directory
target_include_directories(${printsth_target} PRIVATE ${printish_usr_dir})
使用这样的脚本,printsth
库可以在应用程序的CMakeLists.txt
中实例化。
apps/printno/CMakeLists.txt:
add_executable(printno main.cpp)
# Instantiate 'printsth' library with needed parameters.
set(printsth_target "printsh_no")
set(printish_usr_dir ${CMAKE_CURRENT_SOURCE_DIR})
# Need to specify the second argument - build directory, where the library will be built.
add_subdirectory(../../extern/printsh printsh_no_dir)
# No we can link with a library. Use a name, specified for 'printsth_target' variable.
target_link_libraries(printno PRIVATE printsh_no)
应修改顶级CMakeLists.txt
,以便不实例化库。
CMakeLists.txt:
# <...>
add_subdirectory(apps/printyes)
add_subdirectory(apps/printno)
# Uncommenting the following line causes FATAL_ERROR triggered.
#add_subdirectory(extern/printsth)
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 在链接可执行文件之前查找静态库未解析的依赖项
- 在 CMAKE 中使用具有静态依赖项的库
- 在现代 CMake 项目中存档静态依赖项
- CMake 外部和内部静态库的循环依赖关系
- 如何将 SDL2 用作我的静态 (CMake ) 库的 3D 方依赖项?
- 依赖于依赖类型的非静态数据成员的非限定名称
- 您如何将所有链接依赖项都包装到一个Linux静态库中
- 如何使用捆绑依赖项-CMAKE构建静态库
- 具有依赖于实现的成员函数类型的多个静态接口
- 在不同翻译单元中具有静态存储持续时间的依赖非局部常量浮点变量的常量初始化
- cmake-包括静态库中的依赖项
- 这是静态库依赖树中的菱形问题吗?
- 是否可以编译具有在编译时无法解析的外部依赖项的静态库?
- 依赖于其他静态库的静态库
- 为 c++ 构建一个静态库,该库在内部依赖于第三方库
- 相互依赖的静态库
- 完全静态构建具有所有依赖项(libgcc等)的应用程序
- 依赖静态对象地址安全吗
- 如何强制依赖静态对象(包括模板成员)的初始化顺序