как правильно использовать директиву CMake "project" - PullRequest
9 голосов
/ 21 декабря 2011

У меня есть кодовая база большого размера, которая создает несколько десятков библиотек и несколько исполняемых файлов.

База кода разбита иерархически, а библиотеки создаются практически на каждом уровне.

У меня естьпрошел и разместил файл CMakeLists.txt в каждом каталоге для создания каждой библиотеки.

В каждом CMakeLists.txt я использовал директиву project (xxx).Это определило для меня переменные PROJECT_NAME, PROJECT_SOURCE_DIR и PROJECT_BINARY_DIR, которые я разумно использую.

Однако один из членов команды недоволен этим подходом, поскольку он не может найти реальных примеров того, как кто-то еще сделал это.Он часто цитирует примеры KitWare как не использующие этот подход, и поэтому мы не должны.

Альтернативный подход, который он защищает, состоит в том, чтобы установить эти переменные в каждом make-файле, что очень похоже на то, что дает вам «проект».

Я действительно не вижу его смысла и мало зарабатываюубедить его в обратном.Может ли кто-нибудь пролить свет на недостатки использования директивы проекта таким образом.

Я доверяю вашей коллективной мудрости?

Ответы [ 3 ]

12 голосов
/ 21 декабря 2011

Во-первых, это позволяет вам использовать <projectName>_BINARY_DIR и <projectName>_SOURCE_DIR, но это не главное преимущество. Если вы дадите CMake имя проекта, он сгенерирует цели сборки для каждого из подпроектов в своих собственных каталогах. Это означает, что независимо от того, используете ли вы GNU Make, Eclipse CDT, XCode или любой другой поддерживаемый генератор, вы можете создавать подпроекты индивидуально. Например, с GNU Make каждый подпроект имеет свою собственную полную систему сборки из своего собственного каталога.

Вы можете получить доступ к имени текущего проекта через PROJECT_NAME, а имя корневого проекта - CMAKE_PROJECT_NAME.

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

Предположим, у меня есть библиотека C ++, и я могу сгенерировать три двоичных исполняемых файла; Main и tests/test1 и examples/ex1. Я могу либо запустить make в каталоге, из которого я назвал CMake, с целью ALL, запустить make ex1, либо я могу изменить каталог на examples/ и построить примеры с make из этого каталога. Это создаст все зависимые проекты и библиотеки, даже если они находятся где-то еще в структуре каталогов, но не создаст Main или tests/test1 или любые библиотеки, которые зависят от того, что examples/ex1 не делает. Если я затем запустите make из основного каталога, он не перестроит ни одну из библиотек, от которых зависит examples/ex1, если только их источник не изменился.

0 голосов
/ 20 мая 2016

Сегодня я нашел хороший пример использования именно этого: добавление документации по Doxygen.

Я использую CMake (и Ninja) для создания своих личных проектов на C ++.Я решил прихотиться, чтобы добавить документацию по Doxygen к одной из моих почти полных, но недокументированных работ.Я также подумал, что было бы неплохо добавить его в другие проекты, как только я разберусь, как сделать его как можно более универсальным.

Для начала я создал стандартный шаблон Doxygen и переименовалit.

cd my_projects/projectx
doxygen -g Doxyfile
mv Doxyfile Doxyfile.in

Обратите внимание на расширение .in.Вероятно, не обязательно, но обычно, если я правильно понимаю.

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

FIND_PACKAGE(Doxygen)
IF("${DOXYGEN_FOUND}" MATCHES "^YES$")
    CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
                    ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
                    @ONLY)
    ADD_CUSTOM_TARGET(  doc ALL
                        COMMAND ${DOXYGEN_EXECUTABLE}
                        ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
                        COMMENT "Doxygenating..."
                        VERBATIM)
ENDIF()

Создает новую цель с именем doc.Указание ALL добавляет его к цели по умолчанию «all», но это необязательно.Указание @ONLY гарантирует, что любые переменные типа «$ {variable}» не будут расширены с помощью CONFIGURE_FILE, только типы «@ variable @».Несколько запутанно (по крайней мере для меня), CMAKE_CURRENT_SOURCE_DIR, по-видимому, ссылается на каталог проекта, а CMAKE_CURRENT_BINARY_DIR - на каталог сборки.

Наконец, именно здесь PROJECT_NAME и др., Я отредактировал Doxyfile.in.

Это начало моего нового Doxyfile.in:

DOXYFILE_ENCODING      = UTF-8
PROJECT_NAME           = "@PROJECT_NAME@"
PROJECT_NUMBER         = @PROJECT_VERSION_TWEAK@
PROJECT_BRIEF          =
PROJECT_LOGO           = @CMAKE_CURRENT_SOURCE_DIR@/res/doc_logo-200x55.png
OUTPUT_DIRECTORY       = @CMAKE_CURRENT_SOURCE_DIR@/doc

Вы, я думаю, поняли идею.Как только это будет полностью обобщено (это слово?), Я могу скопировать его в другие мои проекты, и, пока я помечу свой код, у меня будет отличная документация повсюду.

Обратите внимание, что PROJECT_BRIEF не указан.Я еще не закончил с этим, и есть еще несколько пробелов, о которых я могу подумать.Например, PROJECT_VERSION_TWEAK на самом деле еще ничего не содержит.Мне нужно будет найти способ, чтобы получить мой номер сборки там.

0 голосов
/ 21 декабря 2011

Если библиотеки действительно независимые проекты, то имеет смысл использовать команду project. Однако, если это не так, я бы просто добавил их в качестве подкаталогов в вашем корне CmakeLists.txt. Вы можете использовать переменные CMAKE_CURRENT_SOURCE_DIR и CMAKE_CURRENT_BINARY_DIR , если вам нужно знать каталоги, которые в данный момент обрабатываются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...