【问题标题】:CMake: How do I change properties on subdirectory project targets?CMake:如何更改子目录项目目标的属性?
【发布时间】:2017-12-18 22:03:38
【问题描述】:

我正在尝试组织子项目(在本例中为 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-submodules 的形式添加其他项目,但取决于是否有更简单的方法,我会探索其他途径。

编辑:

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

【问题讨论】:

  • 您可以根据需要在每个目录中添加一个 CmakeLists.txt。为每个项目创建一个并包含来自主项目的目录。
  • @skypjack,你误会了。在我自己的项目中我已经这样做了,但是我想修改别人项目的属性而不修改项目本身。当我只需要生活质量时,就不需要分叉 Poco。

标签: c++ cmake poco-libraries build-tools


【解决方案1】:

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

  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 作用域链到 GLOBALTARGETSOURCETEST 链接到 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 模块中以获得更多控制,但这是一个好的开始。谢谢!
  • @BleuGamer 不客气。您使用哪个版本的 CMake?第一个选项至少需要 CMake 3.7 版。第二个版本的美妙之处在于,目录属性会自动传播到子目录。
  • @BleuGamer 更新了第一个选项以迭代子目录。
  • 我使用的是 3.9.0-rc5。是的,我确实让第一个使用与困扰我相同的方法工作,但第二个更优雅。尽管它没有记录,但一切都按预期工作,并且与我的其他第三方相处得很好。
【解决方案2】:

https://github.com/andry81/tacklelib
https://github.com/andry81/tacklelib/blob/trunk/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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多