LINUX.ORG.RU

Подпроект из исходников

 


0

3

Добрый вечер, ЛОР.

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

Вопрос: как то же самое сделать в cmake? Официальная документация наталкивает на мысль, что в родительском проекте нужно вызвать add_subdirectory(). А вот как при такой схеме написать CMakeLists.txt для каталога-библиотеки?

Гугление «cmake подпроекты» находит только примеры с подпроектами, являющимися самостоятельными библиотеками. Ну ещё нашлась тема на кутешном форуме шестилетней давности, где ТС ответа так и не получил.

В крайнем случае я могу, конечно, плюнуть и вместо библиотеки исходников сделать обычную статическую либу. Но ЕМНИП, последний раз, когда я этим занимался, я огрёб кучу геморроя с отслеживанием изменений из этой либы. Всё же, в статическую либу имеет смысл помещать код, который не просто повторно используется, а стабилизировался и относительно редко меняется. В моём случае это условие не выполняется.

★★★★★

Всё назначение папки - не собирать какой-то объект, а просто содержать исходники? Тогда свой CMakeLists.txt там особо не нужен.

O02eg ★★★★★ ()

А вот как при такой схеме написать CMakeLists.txt для каталога-библиотеки?

Пишешь там add_library(libraryname STATIC file1.cc file2.cc ...) и так далее. Собирается статическая библиотека, которую потом можно линковать к разным целям.

Если не хочешь, чтобы библиотека на самом деле собиралась, а была только некой логической единицей, есть https://cmake.org/Wiki/CMake/Tutorials/Object_Library

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

Вообще, обычно, разбираясь с каким-то инструментом, проникаешься его логикой и красотой. С cmake у меня такого не получается: чем больше смотрю, тем больше ощущение, что система-то мощная и скорее всего, незаменимая, но синтаксис отвратный, и всё это можно было сделать намного красивее.

Кажется, что вместо собственного языка cmake-скрипты вполне можно было бы писать на питоне или луа, присобачив к ним соответствующую библиотеку, и получилось бы примерно то же самое. Для элементарных вещей надо писать много буков. Слишком многое завязано на установку переменных, при этом опечатки в именах переменных никто не контролирует. Я сначала было поручил разбираться с cmake своему студенту, потом увидел, что он написал «set(CMAKE_IN_SOURSCE_BUILD TRUE)» (и это прокатило), и сел разбираться сам. Успеет ещё покалечить себе психику другими способами.

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

вместо собственного языка cmake-скрипты вполне можно было бы писать на питоне

Scons

или луа

http://lua-users.org/wiki/LuaBuildSystems

опечатки в именах переменных никто не контролирует

Аналогичные проблемы будут и в других скриптовых языках.

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

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

А вообще да, CMake ужасен. Сначала всё просто и декларативно. Просто указываешь, из чего собирать, что с чем линковать, всё работает. А потом появляется необходимость добавить ещё какую-нибудь мелочь, и начинается ад с нагромождением конструкций для казалось бы простых действий.

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

В общем, Object Library сработал, но остались вещи, вызывающие недоумение:

1) Если для проекта, лежащего в одном каталоге, в include_directories достаточно указать ${QT_INCLUDE_DIR}, то для составного - исходники из Object Library не видят ни одного заголовочного файла Qt. Приходится вставлять в include_directories полный список из ${QT_INCLUDE_DIR}/QtCore, ${QT_INCLUDE_DIR}/QtGui и т.д. В чём закономерность, я так и не понял. В find_package все компоненты перечислил явно;

2) Если какой-то из файлов Object Library надо включить в MOC_HEADERS, это приходится делать в головном CMakeLists.txt. В библиотечном set, похоже, не срабатывает. Включил в головной, но это явный костыль, с которым надо что-то делать...

А в целом - программа, наконец, собралась, спасибо.

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

в include_directories

Они, наследуются. В корневом CMakeLists.txt указываешь общие вещи, в поддиректориях эти настройки доступны. Но вот если в поддиректориях что-то меняешь, изменения видны потомкам, но не предкам.

MOC_HEADERS

Я вообще с Qt как-то совсем не знаком, но на глаза попадалась такая штука: https://cmake.org/cmake/help/v3.0/manual/cmake-qt.7.html. Думаю, это должно упростить скрипты.

i-rinat ★★★★★ ()
Ответ на: комментарий от hobbit

можешь попробовать boost build v2. он более логичен. но его тоже надо изучать.

я тоже много юзала CMake одно время. на работе он нужен был. но всегда оставалось ощущение, что это что-то нескладное.

Iron_Bug ★★★★★ ()
Ответ на: комментарий от i-rinat

Это я понял. Там две цели, одна требует Qt4, другая Qt5. Мне-то интереснее сделать выбор между тем и другим. Ну ладно, это уже следующий шаг.

Видимо, ты намекал на имеющуюся там переменную CMAKE_AUTOMOC - попробую...

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

Если для проекта, лежащего в одном каталоге, в include_directories

Во-первых, include_directories это эхо из прошлого, которое перестали использовать где-то с третьей версии CMake. Правильно так: target_link_libraries(mylib Qt5::Core Qt5::Gui ...).

Во-вторых, тут действительно подойдёт обычная статическая библиотека. Никаких проблем с зависимостями быть не должно. Нужно помнить, что библиотека в CMake это больше чем .so или .a файл. С библиотекой автоматически подтягиваются опции компиляции, include-директории, другие модули, с которыми библиотека была слинкована. Смотреть target_compile_options(), target_include_directories(), target_link_libraries(), конкретнее аргумент INTERFACE.

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

boost-build более логичен чем cmake? Ёшки-матрешки, помню как я пытался пофиксить билдсистему буста в генте, как же я матерился.

У меня такого мата даже километровые портянки в autotools не вызывали. Лично для меня boost-build держит звание одной из самых черезжопных систем сборки наряду с waf.

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

если ты не знаешь эту систему сборки, то с налёту ты там ничего не пофиксишь. но он гораздо логичнее CMake'а. и гибче. он нацелен на сборки с разными зависимостями, с множественными библиотеками, объектниками и т.д. в нём можно настроить всё, причём довольно малыми усилиями. и он сделан так, что изменения в одном подпроекте не затрагивают ничего, кроме настроек этого подпроекта.

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

А в Makefile-ах это делалось просто

Вручную поддерживать в актуальном состоянии Makefile для проекта из 20-30 файлов - это мазохизм.

Вот qmake мне, в принципе, хватало. Но я хочу воспользоваться возможностями cpack.

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

include_directories это эхо из прошлого, которое перестали использовать где-то с третьей версии CMake.

Это всё хорошо, но у меня ещё и такие проекты есть (не тот, который прямо сейчас ковыряю, другие), где нужно заботиться о совместимости аж с cmake 2.4. Так-то сейчас я с 3.0.2 работаю...

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

Так там использовать можно регулярки. Не для каждого же файла заводить цель, как делает, например, QMake.

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

include_directories это эхо из прошлого, которое перестали использовать где-то с третьей версии CMake. Правильно так: target_link_libraries(mylib Qt5::Core Qt5::Gui ...).

Разве? А по-моему, это вещи несколько разные. target_link_libraries отвечает за линковку. И у меня, кстати, в проекте написано:

target_link_libraries(doublecontact ${QT_LIBRARIES})

Но это никак не помогает при поиске Qt-шных заголовочных файлов. А вот с include_directories они прекрасно находятся.

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

target_link_libraries отвечает за линковку

Если аргумент это путь к библиотеке, то да, просто линковка. А если это target в CMake, то из него также подтягиваются экспортированные зависимости: другие таргеты, include-директории, опции компиляции. Всё что отмечено через PUBLIC или INTERFACE в target_compile_options() и target_include_directories().

Dendy ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.