【发布时间】:2021-10-22 03:32:21
【问题描述】:
我使用CMake构建了一个包含多个嵌套静态库的项目。类似但简单的结构如下图所示:
TestProject:
|-CMakeLists.txt
|-Main.cpp
|-level2
| | - level2.cpp
| | - level2.h
| | - CMakeLists.txt
| | - level1
| | |-level1.cpp
| | |-level1.h
| | |-CMakeLists.txt
现在,我使用 CMake 分别为每个级别构建静态库。根据我的测试,每一层的静态库只包含该层的.cpp和.h文件。但是,我想在生成每一层的静态库时,将它与上一层引用的库结合起来。比如我先构建了1级的静态库。然后,在2级的CMakeLists.txt中,我创建了2级的静态库,依赖于1级的静态库( target_link_libraries(${PROJECT_NAME} LEVEL1) ) ,然后,我想将level 2和level 1的库合并到一个名为level1_2.lib的新静态lib文件中。
这是我在 Level1 中的 CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
#projcet name
project(LEVEL1 LANGUAGES CXX)
add_library( ${PROJECT_NAME} add.cpp)
# Add the include directories of user-written sources.
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
这是level2的CMakelists.txt。
cmake_minimum_required(VERSION 3.5)
project(LEVEL2 LANGUAGES CXX)
add_subdirectory(level1)
add_library( ${PROJECT_NAME} addplus.cpp)
target_link_libraries(${PROJECT_NAME} LEVEL1)
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
find_program(MSVC_LIB_TOOL lib.exe)
set(LIBNAME "level1_2.lib")
add_custom_command(
TARGET examplelib POST_BUILD
COMMAND ${MSVC_LIB_TOOL} /OUT:${LIBNAME} $<TARGET_FILE:LEVEL2> $<TARGET_FILE:LEVEL1>
DEPENDS LEVEL1 LEVEL2
COMMENT "Combining libs..."
)
add_custom_target(combinedLib
ALL
DEPENDS ${LIBNAME}
)
我使用 add_custom_command 和 add_custom_target 方法尝试生成混合库,参考以下几个网站:
CMake linking libraries into one single library
但是它们并不能真正解决我的需求。只生成了level1.lib和level2.lib。
任何帮助将不胜感激。
08-21 更新 ======================================= ================
感谢大家的回复。现在我使用了对象库(参考Alex的回答),并得到了合并的静态库。这是我的新代码:
#CMakeLists.txt in level1
cmake_minimum_required(VERSION 3.5)
#projcet name
project(LEVEL1 LANGUAGES CXX)
# Generate lib
add_library( LEVEL1obj OBJECT add.cpp)
# Add the include directories of user-written sources.
target_include_directories(LEVEL1obj PUBLIC ${PROJECT_SOURCE_DIR})
add_library(${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} PUBLIC LEVEL1obj)
这是level2的CMakelists.txt。
#CMakeLists.txt in level2
cmake_minimum_required(VERSION 3.5)
#projcet name
project(LEVEL2 LANGUAGES CXX)
add_subdirectory(level1)
add_library( LEVEL2obj OBJECT addplus.cpp addplus.h)
# Add the include directories of user-written sources.
target_include_directories(LEVEL2obj PUBLIC ${PROJECT_SOURCE_DIR})
target_link_libraries(LEVEL2obj LEVEL1obj)
add_library( ${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} PUBLIC LEVEL1obj LEVEL2obj)
这是测试项目中的顶级 CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(TestCppLib)
file(GLOB SRC "${PROJECT_SOURCE_DIR}/*.cpp")
add_subdirectory(level2)
add_executable(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
target_link_libraries(${PROJECT_NAME} PRIVATE LEVEL2)
与Alex的回答稍有不同的是:因为我的level2库依赖于level1库,所以我通过target_link_libraries(LEVEL2obj LEVEL1obj)给它添加了一个库依赖。与 Alex 的回答略有不同的是,因为我的 level2 库依赖于 level1 库的生成,所以我通过以下代码为其添加了库依赖项。至少目前,它运作良好。
【问题讨论】:
-
为什么使用build event 的
add_custom_command变体? (并使用从未创建的exampleLib目标,这应该会产生配置错误。)相反,使用该命令的常见generating 变体:add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME} COMMAND ...)。 -
如果您想要这种行为,请改用对象库。
-
你需要一个实际的静态库还是想在 cmake 中一起使用它们?
I wanted to merge the libraries of level 2 and level 1 together to a new static lib但是为了什么?只需将库level1与库level2链接,并且依赖关系是可传递的。或者您想专门向客户分发level1_2.lib?如果是这样,我建议从一开始就在 cmake 中创建一个库。 -
file(GLOB SRC "${PROJECT_SOURCE_DIR}/*.cpp")-- 请不要在没有CONFIGURE_DEPENDS的情况下使用 glob(放在SRC之后) -
此外,对象库在 3.12 版本之前无法正常工作。您需要使用您声明为最低版本的 ACTUAL CMake 版本来测试您的代码。我真的怀疑你正在运行3.5。运行
cmake --version并将其放入您的cmake_minimum_required
标签: c++ cmake static-libraries static-linking