LINUX.ORG.RU

C++ проект, как корректно подключить к проекту при помощи cmake 2 папочки с одинаковым названием (хедер онли либы) ?

 , , , ,


0

1

Суть, на самом деле, очень простая. Есть большой проект, который содержит по сути app_1 и app_2, которое наследуется от app_1. В проекте нужно сделать поддержку версионности, чтобы каждый app печатал свою версию, для этого сделаны хедер онли библиотеки (копипастой) для каждого app, куда просто в строковые константы (APP_1_VERSION и APP_2_VERSION) грузится версия с гита.

Структура проекта:

app_2

version

—->app_1

—->version

В папке version есть CMakeLists.txt следующего содержания [code]

cmake_minimum_required(VERSION 3.0) project(version)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/version.hpp) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.json.in ${CMAKE_CURRENT_BINARY_DIR}/version.json)

add_library(${PROJECT_NAME} INTERFACE) target_sources(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/version.hpp)

[/code]

В другой папке версион тот же самый код, за исключением того, что там project(app_2_version)

Так вот, ПРОБЛЕМА, если я просто собираю app_1, то все нормально, если же я собираю app_2, которое триггерит сборку app_1, то он мне пишет

… …..app_1/main-app1.cpp…. error: ‘APP_1_VERSION’ was not declared in this scope; did you mean ‘APP_2_VERSION’? 68 | APP_1_VERSION.c_str())); | ^~~~~~~~~~~~~~~~~~~

И действительно, я чекаю, вот даже в vscode вот эта строчка #include <version/version.hpp> какого-то дьявола включает хедер с константами из app_2 Как я понимаю, ему там все пути расшарены и он выбирает включать то, что лежит выше

Короче гайс, кто шарит в cmake помогите, пожалуйста, как это сделать нормально, чтобы все работало, я пытался честно разбираться в cmake, интерфейсы там какие-то, паблик прайват, че-то там еще, по итогу толком ничего не понял, время идет, а решение нужно уже вот прям ЩАС или даже вчера

АААААА, хелп, 0 помощи (Папку переименовывать не предлагать) Если нужно ответить на какие-то уточняющие вопросы, то пишите, постараюсь быстро ответить (но я щас в галере сижу, так что не уверен, что прям мега быстро)



Последнее исправление: Brynjolf (всего исправлений: 8)

Скорее всего у вас не осилили target_ команды, а вместо этого меняете глобальное состояние (target_include_directories vs include_directories).

Первый способ: настроить для каждого приложения свои области видимости заголовочных путей: target_include_directories(app_1 PRIVATE ...) (со вторым приложением аналогично).

Второй способ: если в заголовочном файле только макрос с версией, то можно передать его напрямую из cmake: target_compile_definitions(app_1 PRIVATE APP_VERSION="1.0.0").

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

Пару вопросов,

  1. а можешь подсказать, зачем тут нужно PRIVATE? То есть почему не просто target_include_directories(app_1…)

  2. У меня в самом основном верхнем cmake есть такие строчки include_directories(«.») include_directories(«${CMAKE_CURRENT_BINARY_DIR}»)

И я понимаю зачем, там куча директорий с конфигами, тестами и прочим, так вот (!): дочерним модулям нужно иметь к ним доступ, а как иначе..

А если я напишу то, что ты предлагаешь, то все это будет включаться только для target (основного проекта короче) и будет облом, нет

Brynjolf
() автор топика
Ответ на: комментарий от anonymous

То есть форматирование поста ты не осилил, зато понял как поставить автограф? Продолжай в том же духе, но не надейся на помощь.

anonymous
()
Ответ на: комментарий от Brynjolf

private нужен, чтобы при вызове target_link_libraries с app_1 не экпортировались его инклюды. Соответственно если в app_2 используются хедеры из app_1, то нужно будет полный путь прописывать <app_1/header.hpp>.

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

Ivan_qrt ★★★★★
()

И действительно, я чекаю, вот даже в vscode вот эта строчка #include <version/version.hpp> какого-то дьявола включает хедер с константами из app_2

все правильно, он действует именно так как ты ему указал.

Хедеры подключаются не через target_sources(), а через target_include_directories(). Хедер version/version.hpp для app2 кажется лежит в корневой папке (кстати отформатируй пост нормально, а то не понятно ни черта) и он его видит из коробки. Хедер для app1 - ну ты понял.

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

Спасибо вам за ответы, НО(!)

Что делать с проблемой из пункта 2, про которую я написал выше. То есть если я убираю include_directories(«.») и заменяю на target_include_directories(….), то все идет по П, т.к. внутри мейн проекта есть модули разные, например, модуль A и конфиг Б, модулю А нужен конфиг Б для сборки, а он его перестает видеть, т.к. корневая директория перестает шариться. Исправлять везде на target_sources(…) сказали не варинт, т.к. там все придется менять, а проект большой рили

То есть мне как-то нужно сделать так, чтобы вся корневая папка шарилась просто (именно сама корневая папка, то есть пути подключения в коде будут submoduleX/X.hpp), но чтобы при этом version/version.hpp шарился в отличие от всех файлов персонально через таржет именно этому app1 или этому app2

Есть идеи?

Brynjolf
() автор топика
Ответ на: комментарий от Brynjolf

В теории можно сделать target_include_directories(${PROJECT_NAME} PRIVATE version)

Но тогда будет просто include version.hpp вместо include <version/version.hpp>

но это как будто не очень, везде-то нормальные инклюды

Brynjolf
() автор топика
Ответ на: комментарий от Brynjolf

Тебе надо сделать target_include_directories(target_name PRIVATE ${CMAKE_CURRENT_SOURCE_DIRECTORY}) для каждого таргета в проекте. ${CMAKE_CURRENT_SOURCE_DIRECTORY} - это та же директория, что и «.», по идее.

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

Не вчитываясь в отвратительно оформленный ТС пост… Можно же на законных основаниях в обоих CMakeLists.txt задать директиву project, после чего свободно оперировать переменными:

  • CMAKE_PROJECT_VERSION - будет хранить версию из top-level CMakeLists, можно считать, что это версия всего проекта
  • PROJECT_VERSION - будет хранить версию, установленную ближайшим вызовом project
  • <PROJECT-NAME>_VERSION - аналогично предыдущему, но с учётом имени проекта. Тут я не вдавался в детали, но вроде как, если будут по стеку указны несколько project с разными именами, то они все будут доступны, а если будут с одинаковыми, то последний будет перекрывать предыдущие.

Аналогично, автоматом будут доступны (с нюансами) и составляющие версии: MAJOR, MINOR, PATCH, TWEAK.

После чего всё это дело можно передать таргету:

project(app_1 ... VERSION 0.1.2)
...
add_executable(app_1 ...)
...
target_compile_definitions(app_1 PRIVATE APP_VERSION="${app_1_PROJECT_VERSION}")
hatred ★★★
()