Я пытаюсь организовать цели в моем подпроекте (в данном случае poco), но обнаружил, что свойства не могут быть изменены для целей ALIAS. Я хочу, чтобы цели в моем внешнем проекте находились в своей собственной папке, а не расползались повсюду в дереве проекта (скажем, в генераторе визуальной студии). Есть ли более простой способ добавить проекты с моими собственными свойствами?

Так что вместо:

- 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, очевидно, не имеет большого значения, поскольку большинство инструментов редактирования уже основаны на папках.

7
BleuGamer 14 Июл 2017 в 02:03
1
Вы можете добавить CmakeLists.txt в каждый каталог, если хотите. Создайте по одному для каждого проекта и включите каталоги из основного.
 – 
skypjack
14 Июл 2017 в 08:54
@skypjack, вы неправильно поняли. В моем собственном проекте я уже делаю это, но я хочу изменить свойства чужого проекта, не изменяя сам проект. Нет необходимости форк Poco, когда все, что мне нужно, - это качество жизни.
 – 
BleuGamer
14 Июл 2017 в 20:31

1 ответ

Лучший ответ

Я попробовал ваш пример, и вот два моих варианта:

  1. Используя BUILDSYSTEM_TARGETS и SUBDIRECTORIES свойства каталога для оценки списка целевых имен в каталоге, который" не включает любые импортированные цели или псевдонимы ":

    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. TARGET, SOURCE и TEST подключаются к 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.

Ссылки

10
Florian 19 Июл 2017 в 22:48
Первый вариант не сработал, но второй сделал именно то, что я хотел. В конце концов, я перенесу их в модули / cmake для большего контроля, но это послужит хорошим началом. Спасибо!
 – 
BleuGamer
19 Июл 2017 в 03:32
Пожалуйста. А какую версию CMake вы используете? Для первого варианта требуется как минимум CMake версии 3.7. Прелесть второй версии в том, что свойства каталога автоматически распространяются на подкаталоги.
 – 
Florian
19 Июл 2017 в 22:04
Обновлен первый вариант, чтобы также перебирать подкаталоги.
 – 
Florian
19 Июл 2017 в 22:17
Я использую 3.9.0-rc5. Да, я добился того, что первый работает тем же методом, что и меня, но второй гораздо более элегантен. Несмотря на то, что это недокументировано, все работает так, как задумано, и хорошо работает с другими моими третьими сторонами.
 – 
BleuGamer
19 Июл 2017 в 22:28