Получение компилятора для поиска файла, созданного Cmake
Я использую configure_file
Команда в 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
создается в исходном каталоге? Или я должен изменить его, чтобы добавить каталог сборки к пути включения? (И действительно, зачем мне вообще с этим справляться? [Полу риторический вопрос])
Этот вопрос касается аналогичной проблемы, но оба варианта предлагаются в качестве возможных решений; Я хочу знать, есть ли стандартная практика, или это указывает, что я что-то упускаю из-за того, как Cmake предназначен для использования.
2 ответа
Сохранять исходное дерево "нетронутым" правильно, а не делать "неправильно", если вы хотите, например, выполнить несколько разных сборок, или если вы хотите иметь возможность очистить сборку, выполнив команду 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
Я не думаю, что есть стандартный способ справиться с этим, но из моего собственного ограниченного взгляда на другие проекты, на самом деле, кажется, что подавляющее большинство так или иначе. Если бы я догадался, я бы подумал, что более распространенным является размещение сгенерированного файла в дереве сборки, а не в дереве исходного кода.
Я бы предпочел поместить его в подкаталог, например ${CMAKE_CURRENT_BINARY_DIR}/GeneratedFiles/config.h
для ясности. Это позволяет избежать всех подкаталогов ${CMAKE_CURRENT_BINARY_DIR}
появляются в списках автозаполнения IDE, таких как Visual Studio. Это также делает ваш корень сборки немного чище, особенно если вы получите несколько сгенерированных файлов. Сначала вы должны создать каталог:
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 или нет.