Глобальные переменные в CMake для отслеживания зависимостей - PullRequest
0 голосов
/ 07 декабря 2010

Алло,

Я использую CMake в качестве системы сборки в одном из моих проектов, который довольно сложный. Проект включает в себя несколько библиотек и несколько приложений. Моя цель - сделать возможным следующее:

  1. Библиотеки могут быть построены по запросу пользователя (реализовано в кэшированной переменной CMake)
  2. Приложения создаются по запросу пользователя (см. Выше), но приложение может выбирать, какие библиотеки требуются, и создавать их, не выбирая их пользователем
  3. Это не должно изменять выбор кэшированного пользователя, для которого создаются библиотеки (чтобы отключить автоматическое создание библиотек, если сборка приложений отключена)

Моя компоновка системы сборки выглядит следующим образом: у меня есть родительский каталог, содержащий CMakeLists.txt, который добавляет библиотеки и приложения в качестве подкаталога. Каждая библиотека и приложение имеет свой собственный файл CmakeLists.txt, который определяет определяемые пользователем параметры конфигурации, которые будут храниться в кэше, целевые объекты, которые будут построены, и от каких других библиотек проекта это зависит. Приложения не обязательно находятся в следующем подкаталоге родительского каталога, но также могут быть на несколько уровней ниже, так что я не могу использовать PARENT_SCOPE, потому что родительский элемент не должен быть верхним родительским, а зависимости должны быть известны сверху.

Я попытался установить для GLOBAL свойства, такие как PROJECT_BUILD_SOMELIBRARY, установленный на on, и попытался получить их в CMakeLists.txt в SOMELIBRARY, чтобы решить, строить или нет, но свойства не передавались в библиотеку, поэтому он никогда не создавался, даже если на самом деле это было бы необходимо, потому что другая библиотека или приложение указали, что оно зависит от этой библиотеки. Использование LIST, содержащего имя каждого приложения или цели библиотеки, в зависимости от библиотеки и кэширования, которое внутри тоже не работает.

Подводя итог этим многим словам, я ищу способ повлиять на CMakeLists в каком-либо подкаталоге, ответственном за построение библиотеки с помощью CMakeLists в каком-либо другом подкаталоге (который не обязательно является тем же уровнем подкаталога, что и другой подкаталог). ) для создания этой библиотеки, даже если пользователь не указал ее явно с помощью параметра конфигурации при вызове cmake.

Кто-нибудь знает, как этого можно достичь или это невозможно с помощью CMake? Есть ли предложения для других подходов к этой проблеме, которые, однако, включают использование CMake? Знаете ли вы о какой-либо другой системе сборки, которая могла бы комфортно обрабатывать эти требования?

Большое спасибо, crispinus

Ответы [ 3 ]

2 голосов
/ 07 декабря 2010

Один из способов создания глобальных переменных CMake:

set(EXAMPLE_INCLUDE_DIRS CACHE INTERNAL "include directories" FORCE)

Чем когда вы хотите добавить или установить значение, используйте:

  set(EXAMPLE_INCLUDE_DIRS ${EXAMPLE_INCLUDE_DIRS } ${EXTRA_INCLUDE_DIRS }
CACHE INTERNAL "include directories") 
0 голосов
/ 20 декабря 2010

Тем временем я сам решил проблему. На самом деле, реализовать настройку, описанную выше, было довольно просто. Я использовал опцию EXCLUDE_FROM_ALL для всех целей в зависимости от того, были ли они явно выбраны пользователем (= пропустите EXCLUDE_FROM_ALL) или нет.

Параметр EXCLUDE_FROM_ALL приводит к тому, что цель не включена в общую цель, если только другая цель (которая не помечена как EXCLUDE_FROM_ALL) зависит от этой цели. Это работает даже над подкаталогами, потому что цели CMake действительно глобальны, и даже самый верхний родитель знает о цели самого нижнего подкаталога, и даже подкаталог того же уровня знает о целях другого подкаталога.

В моем макете каждая отдельная часть моего проекта содержит свой собственный файл CMakeLists.txt и добавляет свои собственные параметры в кэш, поэтому пример подпроекта будет выглядеть следующим образом:


SET(PART_NAME SAMPLE_PART)
SET(PART_TARGET_NAME samplepart)

SET(BUILD_${PART_NAME} off CACHE BOOL "Build part ${PART_NAME}")
SET(${PART_NAME}_FILES some_file.c another_file.c)

IF(NOT BUILD_${PART_NAME})
SET(EXCLUDE_${PART_NAME} EXCLUDE_FROM_ALL)
ENDIF(NOT BUILD_${PART_NAME})

ADD_LIBRARY(${PART_TARGET_NAME} SHARED ${EXCLUDE_SAMPLE_PART} ${PART_NAME}_FILES)
TARGET_LINK_LIBRARY(${PART_TARGET_NAME} some_other_target)

Таким образом, если пользователь выбирает BUILD_SAMPLE_PART, цель не установлена ​​в EXCLUDE_FROM_ALL и будет включена во все; в противном случае цель установлена ​​в EXCLUDE_FROM_ALL и будет построена, только если другая цель зависит от этого. Если эта цель является сборкой, будет также создан «some_other_target», независимо от того, включена она сама или нет.

0 голосов
/ 19 декабря 2010

Я создал пример онлайн, который пытается ответить на этот вопрос.Вы сможете загрузить его из моего репозитория GitHub по адресу bgoodrs-CMake-examples .Если вы щелкнете по этой ссылке, вы сможете прочитать документ (README.markdown в этом хранилище), в котором предпринята попытка сделать то же самое, что, я думаю, вы хотите сделать.Вы можете нажать кнопку загрузки, чтобы загрузить копию примеров для локальных экспериментов.Если это не так, прокомментируйте мой ответ, и я постараюсь улучшить пример соответствующим образом.

...