简体   繁体   English

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

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

I'm trying to organize the targets in my subproject (in this case poco), but I've come to find that properties can't be modified for ALIAS targets.我试图在我的子项目(在本例中为 poco)中组织目标,但我发现无法为 ALIAS 目标修改属性。 I want the targets in my external project to be in their own folder, instead of sprawled out everywhere in the project tree (say the visual studio generator).我希望我的外部项目中的目标位于它们自己的文件夹中,而不是散布在项目树中的任何地方(比如 visual studio 生成器)。 Is there an easier way to add projects with my own properties?有没有更简单的方法来添加具有我自己的属性的项目?

So instead of:所以不是:

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

I want:我想:

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

My attempt:我的尝试:

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)

Example target from the poco library:来自 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
    )

My goal is to make it so I don't have to fork and maintain my own versions of libraries that I want to use just for quality of life tweaks.我的目标是做到这一点,这样我就不必分叉和维护我自己的库版本,我只想使用这些库来调整生活质量。 Is there a different method I can use to organize the project tree for IDEs?我可以使用其他方法来组织 IDE 的项目树吗? I know externalproject_add exists, but I do not think this has the facilities I am looking for.我知道 externalproject_add 存在,但我认为它没有我正在寻找的设施。 I will be adding other projects in the future in the form of git-submodules, but depending on if there is an easier method for this I'll explore other avenues.我将在未来以 git-submodules 的形式添加其他项目,但取决于是否有更简单的方法,我将探索其他途径。

EDIT:编辑:

To clarify, I'm already using a separate CMakeLists.txt for each module of my own project, plus a top level CMakeLists.txt which ties them all together, as well as collecting external libraries that my targets rely on.澄清一下,我已经为我自己项目的每个模块使用了一个单独的 CMakeLists.txt,加上一个将它们联系在一起的顶级 CMakeLists.txt,以及收集我的目标所依赖的外部库。 I want to modify the targets of external libraries without having to fork and maintain them myself just so I have nice folder structures in visual studio, xcode, or others.我想修改外部库的目标而不必自己分叉和维护它们,这样我在 visual studio、xcode 或其他文件夹中就有了很好的文件夹结构。 Linux obviously doesn't matter as much since most editing tools are folder based already. Linux 显然无关紧要,因为大多数编辑工具已经基于文件夹。

I've given your example a try and here are my two variants: 我试试了你的例子,这是我的两个变种:

  1. Using the BUILDSYSTEM_TARGETS and SUBDIRECTORIES directory properties to evaluate a list of target names in the directory that "does not include any Imported Targets or Alias Targets": 使用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. By transforming the FOLDER target property into something that is inherited from a directory property of the same name. 通过将FOLDER目标属性转换为从同名的目录属性继承的内容。 This can be done using define_property() to redefine the FOLDER property as INHERITED : 这可以使用define_property()FOLDER属性重新定义为INHERITED

    With the INHERITED option the get_property() command will chain up to the next higher scope when the requested property is not set in the scope given to the command. 使用INHERITED选项时,如果未在命令的作用域中设置请求的属性,则get_property()命令将链接到下一个更高的作用域。 DIRECTORY scope chains to GLOBAL . DIRECTORY范围链到GLOBAL TARGET , SOURCE , and TEST chain to DIRECTORY . 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) 

    𝓝𝓸𝓽𝓮: Using define_property() to redefine an existing property's scope is an undocumented behavior of CMake. 𝓝𝓸𝓽𝓮:使用define_property()重新定义现有属性的范围是CMake的未记录行为。

References 参考

https://github.com/andry81/tacklelib https://github.com/andry81/tacklelib
https://github.com/andry81/tacklelib/blob/trunk/cmake/tacklelib/Project.cmake 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 command line: CMake 命令行:

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

Project directory structure:项目目录结构:

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

_out - directory with cmake cache and output _out - 具有 cmake 缓存和 output 的目录

Solution layout:解决方案布局:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM