gpt4 book ai didi

c++ - 如何将 CMake 子项目中定义的静态库链接到其他子项目中的目标?

转载 作者:太空宇宙 更新时间:2023-11-04 14:31:31 24 4
gpt4 key购买 nike

我有一个大型的模块化 CMake 项目。一些模块是静态库,一些是可能会或可能不会使用其中一些库的可执行文件。我已经有一个要求/依赖性检查系统,它会停止 cmake 并告诉用户他是否正在尝试构建可执行文件而不是它需要的库。

项目编译正常。我想将其拆分为子项目,即为每个模块的 CMakeLists.txt 设置 project(${module_name})。不幸的是,只要我将这一行插入到适当的宏中,我就会立即收到链接器错误,即可执行文件无法再看到静态库中定义的符号。

在可执行文件上调用的 c++ 命令(我碰巧使用的是 gcc 4.8)没有改变,所以其他地方肯定有所不同。我该如何解决这个问题并保留子项目结构?

编辑:根据@Gerald 的评论,附加信息。

项目文件夹结构:

root
|
|-bin
|-lib
|-cmake(various CMake scripts, added to module path)
|-third_party
|-...
|-CMakeLists.txt
|-modules(top-level module directory, expanded)
|
|-CMakeLists.txt
|-exec_module_a
|-exec_module_b
|-... (other exec modules)
|-lib_module_a
|-lib_module_b
|- ... (other lib modules)
|-lib_module_N (expanded)
|
|-CMakeLists.txt
|-include/root/module_N (various include files)
|-src (various source files)
|-tests

典型叶级 CMakeLists.txt 的结构(相同但 lib 和 exec 模块的 root_add_subproject 有一个参数):

include(RootUtils)

set(module_name ${EXEC_MODULE_A})
#---------------------------CHECK REQUIREMENTS---------------------------------#
root_check_module_requirements(module_name
BUILD_${LIB_MODULE_A}
BUILD_${LIB_MODULE_G}
#...
WITH_QT
WITH_THIRD_PARTY_BLAH1
WITH_THIRD_PARTY_BLAH2
#...
)
#---------------------------ADD SOURCES AND TARGET-----------------------------#
root_add_subproject(${module_name} executable qt_on)
#---------------------------ADD INCLUDES---------------------------------------#
target_include_directories(${TARGET_NAME} PUBLIC

#third-party includes
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
#...

#module includes
"${MODULES_DIR}/${LIB_MODULE_A}/include"
"${MODULES_DIR}/${LIB_MODULE_B}/include"
#...
)
#---------------------------LINK LIBRARIES-------------------------------------#
target_link_libraries(${TARGET_NAME} PUBLIC

#third-party libraries
${QT5_TARGETS}
${THIRD_PARTY_BLAH1_LIBRARIES}
${THIRD_PARTY_BLAH2_LIBRARIES}
#...

#module libraries
${LIB_MODULE_A}
${LIB_MODULE_B}
#...
)
if(UNIX)
#... link third-party dependencies conditional on platform
endif()
#---------------------------ADD TESTS------------------------------------------#
#SET(BUILD_TESTS FALSE)#comment out to build the local unit tests
root_add_tests(${module_name})

#==============================================================================#

RootUtils.cmake 中的相关脚本如下所示:

macro(augmentarium_add_subproject module_name proj_type qt_on)

if(${qt_on} STREQUAL "qt_on" OR ${qt_on} STREQUAL "YES" OR ${qt_on} STREQUAL "TRUE")
set(QT_ON TRUE)
else()
set(QT_ON FALSE)
endif()

#---------------------------DEFINE SUBPROJECT----------------------------------#
#TODO: fix problems with macro (figure out how to set up library as a subproject w/o destroying linking capability)
#project(${module_name}) # <------- THIS is the line that causes linker errors

set(TARGET_NAME ${module_name})
string(TOUPPER "${TARGET_NAME}" TARGET_NAME_UPPER)

if(QT_ON)
set(CMAKE_AUTOMOC ON)
endif()


#---------------------------DEFINE SOURCE FILES--------------------------------#
include_directories(include)
SET(${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR include/${PROJECT_NAME}/${TARGET_NAME})

file(GLOB ${TARGET_NAME_UPPER}_CMAKELISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)

file(GLOB ${TARGET_NAME_UPPER}_SOURCES src/*.cpp)
file(GLOB ${TARGET_NAME_UPPER}_HEADERS src/*.h src/*.h.in src/*.hpp src/*.tpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h.in
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.hpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.tpp)
file(GLOB ${TARGET_NAME_UPPER}_TEST_SOURCES tests/*.cpp)

if(QT_ON)
file(GLOB_RECURSE MOC_${TARGET_NAME_UPPER}_SOURCES moc_*.cpp *_automoc.cpp qrc_*.cpp)
#remove generated moc files
foreach(FILE_NAME ${MOC_${TARGET_NAME_UPPER}_SOURCES})
list(REMOVE_ITEM ${TARGET_NAME_UPPER}_SOURCES ${FILE_NAME})
endforeach()
endif(QT_ON)


if(QT_ON)
#---------------------------ADD UI FILES---------------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_UI src/*.ui)

if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_wrap_ui(${TARGET_NAME_UPPER}_UI_HEADERS ${${TARGET_NAME_UPPER}_UI})
endif()
#---------------------------ADD RESOUCE FILES----------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_RESOURCE_FILES *.qrc)

if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_add_resources(${TARGET_NAME_UPPER}_GENERATED_RESOURCES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
endif()
endif(QT_ON)

#..........................organize source/header files........................#
source_group("Source Files" FILES ${${TARGET_NAME_UPPER}_SOURCES})
source_group("Header Files" FILES ${${TARGET_NAME_UPPER}_HEADERS})

if(QT_ON)
source_group("Resource Files" FILES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
source_group("UI Files" FILES ${${TARGET_NAME_UPPER}_UI})
source_group("Generated Files" FILES ${${TARGET_NAME_UPPER}_GENERATED_RESOURCES} ${${TARGET_NAME_UPPER}_UI_HEADERS})
endif()

#---------------------------ADD TARGET-----------------------------------------#
set(ALL_${TARGET_NAME_UPPER}_FILES
${${TARGET_NAME_UPPER}_CMAKELISTS}
${${TARGET_NAME_UPPER}_SOURCES}
${${TARGET_NAME_UPPER}_HEADERS}
${${TARGET_NAME_UPPER}_RESOURCE_FILES}
${${TARGET_NAME_UPPER}_UI}
${${TARGET_NAME_UPPER}_GENERATED_RESOURCES}
)

if(${proj_type} STREQUAL "executable")
add_executable(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
elseif(${proj_type} STREQUAL "library")
add_library(${TARGET_NAME} STATIC ${ALL_${TARGET_NAME_UPPER}_FILES})
else()
add_custom_target(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
endif()

endmacro()

如果这还不够,以下是模块级 CMakeLists.txt 中包含子项目的方式:

foreach (MODULE_NAME ${MODULES})
add_subdirectory (${MODULE_NAME})
endforeach()

使用的 CMake 版本:3.1.3

最佳答案

如何使用 CMake 管理库之间的依赖关系?这应该使用 TARGET_LINK_LIBRARIES(myexe mylib1 mylib2)

关于c++ - 如何将 CMake 子项目中定义的静态库链接到其他子项目中的目标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28836941/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com