LINUX.ORG.RU

cmake добавить каталог заголовочных файлов к другим целям

 , ,


0

1

Добрый день.
В корне проекта есть каталог config. В нем есть файл config.h.in. Это шаблон конфигурационного файла на основе которого при сборке через механизм cmake configure_file() генерируется файл config.h который будет подключаться в исходниках целей через директиву

// Здесь не указываются пути, только имя файла
#include "config.h"

Также в каталоге config есть файл CMakeLists.txt следующего содержания (config.h.in добавляется к цели для того, чтобы отображаться в дереве проекта в IDE):

add_library(config config.h.in)
set_target_properties(config PROPERTIES LINKER_LANGUAGE CXX)
# или же можно установить свойства конкретного файла (с тем же эффектом)
# set_source_files_properties(config.h.in PROPERTIES LANGUAGE CXX HEADER_FILE_ONLY ON)

set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

configure_file(config.h.in config.h)
Без второй строки получаю ошибку:
CMake Error: Cannot determine link language for target "config".
CMake Error: CMake can not determine linker language for target: config
(это из-за того что cmake по расширению .in не может определить язык поэтому далее я указываю язык явно через set_target_properties())
Данный файл подключается в корневом файле CMakeLists.txt через команду
add_subdirectory("config")
Также есть подкаталог program со своим CMakeLists.txt который подключается в корневом CMakeLists.txt также через команду add_subdirectory(). Вот содержимое CMakeLists.txt из подкаталога program:
add_executable(program main.cpp)

target_link_libraries(program library0 library1 config)
В данном случае я добавил config в команду target_link_libraries() для того, чтобы добавить к текущей цели каталоги с заголовочными файлами из цели config.
При данной конфигурации сборка работает.
Вопрос: правильная ли это архитектура? Или добавить путь к конфигурационному файлу удобнее иначе? Например через команду cmake add_custom_target (через нее у меня не получилось, но возможно я делал это как-то не корректно)?

★★★★★

--- add_library(config config.h.in)
+++ add_library(config config.h)

Только даже это не поможет, скорее всего, так как хедеры обычно не содержат код, а значит, и компилироваться там нечему.

Тебе нужно что-то вроде такого:

config/CMakeLists.txt:

configure_file(config.h.in config.h)
set(CONFIG_SRCS config.h PARENT)

program/CMakeLists.txt:

add_executable(program main.cpp ${CONFIG_SRCS})
target_link_libraries(program library0 library1)

CMakeLists.txt:

project(MyProject)
set(CONFIG_SRCS "")
add_subdirectory(config)
add_subdirectory(program)

XMs ★★★★★ ()
Последнее исправление: XMs (всего исправлений: 1)
Ответ на: комментарий от XMs

0) Разве в таком виде program увидит config.h (т.е. разве в CMakeLists.txt у program не нужно теперь указать каталог с заголовочником config.h)?
1) В program подключение файла config.h в исходном коде в директиве #include будет с указанием каталога?
2) config.h.in в IDE теперь будет отображаться в каталоге program (или по ходу теперь он вообще не будет отображаться)?

rumgot ★★★★★ ()
Последнее исправление: rumgot (всего исправлений: 4)
Ответ на: комментарий от rumgot

Разве в таком виде program увидит config.h (т.е. разве в CMakeLists.txt у program не нужно теперь указать каталог с заголовочником config.h)?

Если не увидит, то можно сделать так:

set(CONFIG_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/config.h PARENT)


В program подключение файла config.h в исходном коде в директиве #include будет с указанием каталога?

Да. Чтобы можно было сделать #include <config.h>, можно вообще отказаться от config/CMakeLists.txt, сделав как-то так:

add_executable(program main.cpp)
target_link_libraries(program library0 library1)
target_include_directories(program PUBLIC ${CMAKE_SOURCE_DIR}/config)


config.h.in в IDE теперь будет отображаться в каталоге program (или по ходу теперь он вообще не будет отображаться)?

Он будет отображаться в config/ как обычный файл, хотя это уже от IDE зависит

XMs ★★★★★ ()
Ответ на: комментарий от XMs

Стояночка. config.h будет сгенерирован в каталоге CMAKE_CURRENT_BINARY_DIR. Но так или иначе удобная фишка cmake состоит в зависимостях между целями. Т.е. я определил цель config и ее каталог(и) для поиска заголовочных файлов и далее команда target_link_libraries автоматически добавляет каталоги поиска заголовочных файлов из цели config к цели program. А в твоем случае ты это вручную делаешь. И ладно сейчас каталог один, а вот было бы их несколько... А в случае, когда для нескольких целей нужно было бы добавить эти каталоги поиска заголовочных файлов... По мне, мой способ более масштабируемый.

rumgot ★★★★★ ()
Ответ на: комментарий от rumgot

config.h будет сгенерирован в каталоге CMAKE_CURRENT_BINARY_DIR

Точно. Нечасто с генерацией хедеров сталкиваюсь, подзабыл уже.


и далее команда target_link_libraries автоматически добавляет каталоги поиска заголовочных файлов из цели config к цели program

target_link_libraries, насколько я знаю, каталоги поиска заголовочных файлов не добавляет, она лишь указывает, с кем линковаться, да и зависимости между целями выстраивает, если в качестве библиотеки указана цель. Для каталогов поиска существует include_directories/target_include_directories, но оно не выстраивает зависимости. В случае, если бы у тебя в config/ были какие-то *.c/*.cpp-файлы, тогда да, твой способ был бы правильным — собрали либу и подключили (хотя я сомневаюсь насчёт инклюдов), но в примере header-only, поэтому я сомневаюсь, что оно будет работать

XMs ★★★★★ ()
Ответ на: комментарий от XMs

target_link_libraries выстраивает зависимости, в том числе и добавляет каталоги поиска заголовочных файлов из цели config. В моем случае команда

set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
как раз указывает то, что каталоги CMAKE_CURRENT_SOURCE_DIR и CMAKE_CURRENT_BINARY_DIR будут добавлены к каталогам поиска заголовочных файлов целей, которые будут зависимы от данной цели. В том то и удобство.

rumgot ★★★★★ ()
Ответ на: комментарий от XMs

семантически всё же правильней будет не через link_libraries

Согласен. И поэтому я хотел сделать через add_custom_target() и add_dependencies(). Но при этом каталоги из config не добаляются к цели program.

rumgot ★★★★★ ()
Последнее исправление: rumgot (всего исправлений: 1)