我有一个项目,其中包含一个核心库(LibA在下面的示例中)、一个可执行文件和一个LibB依赖于第一个库的第二个库 ( )。第二个库 ( LibB) 始终以共享(动态库)形式构建。
有什么办法,我可以强制LibB到永远压连杆共享的版本LibA?
这是一个CMakeLists.txt说明问题的小文件:
cmake_minimum_required(VERSION 3.16)
project(my_project LANGUAGES CXX)
# LibA should be buildable in either static or shared form.
add_library(LibA A.cpp)
# In the real case, there are many customizations to `LibA`:
# compile flags, include dirs, target properties, etc.
add_executable(ExecutableA main.cpp)
target_link_libraries(ExecutableA LibA)
# I want library myB to *always* link against the dynamic library libLibA.so.
add_library(LibB SHARED B.cpp)
target_link_libraries(LibB PUBLIC LibA m pthread)
Run Code Online (Sandbox Code Playgroud)
它可以使用以下命令构建:
echo 'int main() {}' > main.cpp
touch A.cpp B.cpp
mkdir -p build
cmake -B build/ -S .
cmake --build build/
Run Code Online (Sandbox Code Playgroud)
我知道我可以强制LibA始终与 共享add_library(LibA SHARED A.cpp),但我希望能够构建LibA为静态库。
真正的背景是我有一个核心库 ( LibA),并希望在创建可执行文件时静态链接它,但LibA.so在创建 Python 扩展模块 ( LibB.so)时动态链接它(作为)。
这是不可能的,libA只能是静态的或动态的,不能两者兼而有之。
您需要有两个版本libA,一个是动态的,一个是静态的:
cmake_minimum_required(VERSION 3.16)
project(my_project LANGUAGES CXX)
function( addLibA suffix type )
set( libname LibA${suffix} )
add_library(${libname} ${type} A.cpp)
# specify library properties here
endfunction()
# LibA should be buildable in either static or shared form.
addLibA("s" STATIC)
addLibA("" SHARED)
# In the real case, there are many customizations to `LibA`:
# compile flags, include dirs, target properties, etc.
add_executable(ExecutableA main.cpp)
target_link_libraries(ExecutableA LibAs)
# I want library myB to *always* link against the dynamic library libLibA.so.
add_library(LibB SHARED B.cpp)
target_link_libraries(LibB PUBLIC LibA m pthread)
Run Code Online (Sandbox Code Playgroud)
正如评论/ jpo38 的答案中提到的,您具体要求的内容将需要多个目标
但是,您可能有兴趣使用 CMake 的对象库来在库目标和可执行目标之间共享对象。例如:
cmake_minimum_required(VERSION 3.16)
project(my_project LANGUAGES CXX)
# Objects get built exactly once
add_library(LibA.objects OBJECTS
A.cpp
)
target_compile_commands( ... )
target_include_directories( ... )
# Shared library for libA
add_library(LibA SHARED
$<OBJECTS:LibA.objects>
)
# LibB -- always shared, always linked against dynamic LibA
add_library(LibB SHARED
B.cpp
)
target_link_libraries(LibB PUBLIC LibA)
# ExecutableA, built using LibA's objects
# (effectively the same linking a static LibA.a)
add_executable(ExecutableA
main.cpp
$<OBJECTS:LibA.objects>
)
Run Code Online (Sandbox Code Playgroud)
使用对象库,您的对象只需构建一次,即可在多个目标之间共享。另一方面,使用多个库目标将强制重建每个对象,因为每个目标可能使用不同的编译命令。
这允许ExecutableA将LibAs 对象内置到其中,因此它的行为就像在LibA.a. 在这种情况下,LibA现在已SHARED明确构建为库,因为这是LibB动态链接所需的。
如果您使用的是较新版本的 CMake,您还可以避免使用$<OBJECTS:...>生成器表达式,而只需直接链接到对象库target_link_libraries- 例如:
target_link_libraries(libA PRIVATE LibA.objects)
...
target_link_libraries(ExecutableA PRIVATE LibA.objects)
Run Code Online (Sandbox Code Playgroud)
这种方法还允许将属性一次性应用到各自的目标。有关源文件本身的任何属性只需要直接应用于对象库。有关库设置/布局的任何属性(例如输出位置、后缀等)都严格适用于库目标。
| 归档时间: |
|
| 查看次数: |
612 次 |
| 最近记录: |