CMake:如何更改子目录项目目标的属性?

CMake: How do I change properties on subdirectory project targets?

本文关键字:目标 属性 项目 子目录 何更改 CMake      更新时间:2023-10-16

我正在尝试在我的子项目中组织目标(在本例中为 poco(,但我发现无法为 ALIAS 目标修改属性。我希望外部项目中的目标位于它们自己的文件夹中,而不是分散在项目树中的任何位置(例如 Visual Studio 生成器(。有没有更简单的方法可以使用我自己的属性添加项目?

所以代替:

- CMakePredefinedTargets
- ALL_BUILD
- INSTALL
- ...
- MyTargets
- SomeLibrary
- SomeExe
- CppUnit
- Crypto
- Data
- ...

我想要:

- CMakePredefinedTargets
- ALL_BUILD
- INSTALL
- ...
- MyTargets
- SomeLibrary
- SomeExe
- Poco
- CppUnit
- Crypto
- Data
- ...

我的尝试:

function(add_subdirectory_with_folder folder_name)
function(add_library name type)
_add_library(${ARGV})
set_target_properties(${name}
PROPERTIES
FOLDER "${folder_name}"
)
endfunction()
add_subdirectory(${ARGN})
endfunction()
# External Libs
add_subdirectory_with_folder("Poco" libs/poco)

poco 库中的示例目标:

add_library( "${LIBNAME}" ${LIB_MODE} ${SRCS} )
add_library( "${POCO_LIBNAME}" ALIAS "${LIBNAME}")
set_target_properties( "${LIBNAME}"
PROPERTIES
VERSION ${SHARED_LIBRARY_VERSION} SOVERSION ${SHARED_LIBRARY_VERSION}
OUTPUT_NAME ${POCO_LIBNAME}
DEFINE_SYMBOL JSON_EXPORTS
)

我的目标是做到这一点,这样我就不必分叉和维护我自己的库版本,我想只用于生活质量调整。是否有其他方法可用于组织 IDE 的项目树?我知道externalproject_add存在,但我认为这没有我正在寻找的设施。我将在未来以 git 子模块的形式添加其他项目,但根据是否有更简单的方法,我将探索其他途径。

编辑:

澄清一下,我已经为我自己项目的每个模块使用了一个单独的 CMakeLists.txt以及一个顶级 CMakeLists.txt将它们联系在一起,以及收集我的目标所依赖的外部库。我想修改外部库的目标,而不必自己分叉和维护它们,这样我在Visual Studio,xcode或其他方面就有了很好的文件夹结构。Linux显然并不重要,因为大多数编辑工具已经基于文件夹。

我已经尝试了您的示例,这是我的两个变体:

  1. 使用BUILDSYSTEM_TARGETSSUBDIRECTORIES目录属性评估目录中"不包含任何导入的目标或别名目标"的目标名称列表:

    cmake_minimum_required(VERSION 3.7)
    project(AliasFolderSub)
    set_property(GLOBAL PROPERTY USE_FOLDERS TRUE)
    function(get_all_targets _result _dir)
    get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
    foreach(_subdir IN LISTS _subdirs)
    get_all_targets(${_result} "${_subdir}")
    endforeach()
    get_property(_sub_targets DIRECTORY "${_dir}" PROPERTY BUILDSYSTEM_TARGETS)
    set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE)
    endfunction()
    function(add_subdirectory_with_folder _folder_name _folder)
    add_subdirectory(${_folder} ${ARGN})
    get_all_targets(_targets "${_folder}")
    foreach(_target IN LISTS _targets)
    set_target_properties(
    ${_target}
    PROPERTIES FOLDER "${_folder_name}"
    )
    endforeach()
    endfunction()
    # External Libs
    add_subdirectory_with_folder("Poco" libs/poco)
    
  2. 通过将FOLDER目标属性转换为从同名目录属性继承的内容。这可以使用define_property()FOLDER属性重新定义为INHERITED

    使用INHERITED选项,当请求的属性未在给定命令的范围内设置时,get_property(( 命令将链接到下一个更高的范围。DIRECTORY范围链到GLOBAL.TARGETSOURCETEST链到DIRECTORY

    cmake_minimum_required(VERSION 2.6)
    project(AliasFolderSub)
    set_property(GLOBAL PROPERTY USE_FOLDERS TRUE)
    define_property(
    TARGET
    PROPERTY FOLDER
    INHERITED
    BRIEF_DOCS "Set the folder name."
    FULL_DOCS  "Use to organize targets in an IDE."
    )
    function(add_subdirectory_with_folder _folder_name _folder)
    add_subdirectory(${_folder} ${ARGN})
    set_property(DIRECTORY "${_folder}" PROPERTY FOLDER "${_folder_name}")
    endfunction()
    # External Libs
    add_subdirectory_with_folder("Poco" libs/poco)
    

    注意:使用define_property()重新定义现有属性的范围是 CMake 的未记录行为。

引用

目录
  • 属性和子目录
  • 在CMake中等同于"make dist">
  • 如何使用 cmake 为嵌套子目录设置 Visual Studio 筛选器

https://github.com/andry81/tacklelib
https://github.com/andry81/tacklelib/blob/master/cmake/tacklelib/Project.cmake

cmake_minimum_required(VERSION 3.14)
# enable project folders
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
## cmake builtin search paths and includes
LIST(APPEND CMAKE_MODULE_PATH "${TACKLELIB_CMAKE_ROOT}")
include(tacklelib/Project)
include(tacklelib/EnableTargetsExtension)
project(MyApp)
set(MYLIB_ROOT ...)
# somewhere at the end ...
## project folders
tkl_set_target_folder(CMAKE_CURRENT_LIST_DIR . * .       UTILITY     . util)
tkl_set_target_folder(CMAKE_CURRENT_LIST_DIR . * "tests" EXECUTABLE  . exe)
tkl_set_target_folder(CMAKE_CURRENT_LIST_DIR . * .       "SHARED_LIBRARY;STATIC_LIBRARY" . lib)
tkl_set_target_folder(MYLIB_ROOT * * .       UTILITY     . _3dparty/utility/mylib/util)
tkl_set_target_folder(MYLIB_ROOT * * "tests" EXECUTABLE  . _3dparty/utility/mylib/exe)
tkl_set_target_folder(MYLIB_ROOT * * .       "SHARED_LIBRARY;STATIC_LIBRARY" . _3dparty/utility/mylib/lib)
tkl_set_target_folder(MYLIB_ROOT * "tests" . * . _3dparty/utility/mylib/tests)

CMake 命令行:

cmake.exe -G "..." "-DTACKLELIB_CMAKE_ROOT=.../_externals/tacklelib/cmake" ...

项目目录结构:

...
_externals/
_out/
include/
src/
CMakeLists.txt

_out- 具有 cmake 缓存和输出的目录

解决方案布局:

_3dparty
utility
mylib
lib
mylib
CMakePredefinedTargets
ALL_BUILD
INSTALL
ZERO_CHECK
exe
myapp
util
bundle