2014-09-25 3 views
2

Я использую команду configure_file в Cmake в режиме проверки доступности функции, как описано on this page. Эта страница предлагает использовать команду:Получение компилятора для создания созданного Cmake файла

configure_file(config.h.in config.h) 

, который будет переводить ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in на ${CMAKE_CURRENT_BINARY_DIR}/config.h. Но когда я компилирую свою программу, компилятор выглядит только в ${CMAKE_CURRENT_SOURCE_DIR} для заголовков (например, config.h), а не в ${CMAKE_CURRENT_BINARY_DIR}. Поэтому, естественно, компилятор не находит config.h, где он был сгенерирован, и сборка завершилась неудачей.

Каков стандартный способ решения этой проблемы? Должен ли я изменить CMakeLists.txt так, чтобы config.h был создан в исходном каталоге? Или я должен изменить его, чтобы добавить каталог сборки в путь include? (И действительно, почему мне приходится вообще обходиться с этим вообще? [Полу-риторический вопрос])

This question относится к аналогичной проблеме, но оба варианта предлагаются в качестве возможных решений; Я хочу знать, существует ли стандартная практика, или если это указывает на то, что мне не хватает чего-то о том, как Cmake предназначен для использования.

+0

Ибо из источника сборки, добавьте 'include_directories ($ {CMAKE_CURRENT_BINARY_DIR})'. –

ответ

6

Сохранение исходного дерева «нетронутым» является правильным, и не делать этого «неправильно», если вы хотите сделать несколько разных сборок, например, или хотите, чтобы вы могли очистить сборку, build dir (недостаточно, если вы генерируете материал в исходный каталог).

Сгенерируйте его в дереве сборки и добавьте путь включения.

Установить переменные

set(CMAKE_INCLUDE_CURRENT_DIR ON) 
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) 

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

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#build-specification-and-usage-requirements

3

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

Мое собственное предпочтение было бы поместить его в подкаталог, например ${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles/config.h, для ясности. Это позволяет избежать всех подкаталогов ${CMAKE_CURRENT_BINARY_DIR}, появляющихся в списках автозаполнения IDE, таких как Visual Studio. Это также упрощает создание root root, особенно если вы закончите с несколькими сгенерированными файлами. Вы должны были бы создать каталог первой:

set(GeneratedFilesDir "${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles") 
file(MAKE_DIRECTORY ${GeneratedFilesDir}) 

set(ConfigFile "${GeneratedFilesDir}/config.h") 
configure_file(config.h.in ${ConfigFile}) 


Вы можете тогда, возможно, сделать немного больше «ограничение ущерба» с помощью target_include_directories, а не include_directories. Например, если config.h только используется внутри библиотеки MyLib, вы можете сделать:

add_library(MyLib ${ConfigFile} ... other sources ...) 
target_include_directories(MyLib 
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${GeneratedFilesDir} 
    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) 

В отличие от использования include_directories, это позволяет избежать всех целей, имеющих ${GeneratedFilesDir} как включаемый путь.


Вещи становятся более спорно, когда сгенерированный файл должен быть разоблачен как общественный заголовок, или добавить к install команды. В конечном счете, я не думаю, что здесь есть «неправильный» вариант. Это сводится к тому, считаете ли вы, что лучше сохранить исходное дерево нетронутым за счет более сложной установки CMake или нет.

Смежные вопросы