Есть несколько проектов, у каждого свой CMakeLists.txt, в каждом — несколько таргетов.
Хочу собрать всё в один проект, и что-то не очень понятно, как это сделать.
В MSVC я бы просто сделал .sln, и включил бы туда какие угодно проекты, и оно бы без плясок просто собиралось
Да, вмешиваться в структуру каталогов не хочется, и не хочется все эти проекты втащивать в супер-проект — супер-проект лежит рядом, на том же уровне иерархии, и когда я делаю add_subdirectory, CMake'у это не нравится, и он просит указать ещё какой-то доп путь
Далее, в проектах у меня так:
project(project1 C CXX)
set(PRJ_ROOT "${CMAKE_CURRENT_LIST_DIR}")
set(LIB_ROOT "${PRJ_ROOT}/lib")
add_subdirectory(${LIB_ROOT}/mylib1)
add_subdirectory(${LIB_ROOT}/mylib2)
Здравствуйте, пффф, Вы писали:
П>Да, вмешиваться в структуру каталогов не хочется, и не хочется все эти проекты втащивать в супер-проект — супер-проект лежит рядом, на том же уровне иерархии, и когда я делаю add_subdirectory, CMake'у это не нравится, и он просит указать ещё какой-то доп путь
add_subdirectory лучше звать для subdirectory и с относительным именем (CMAKE_CURRENT* — это НЕ относительный путь). Если это не subdirectory, то надо бы указать bindir, но разный для каждого. Тут идет всякий дроч вприсядку, с которым разбираться так себе.
Здравствуйте, Великий Реверс, Вы писали:
ВР>поэтому юзается экстернал проект
С этим вариантом (который в рамках cmake и называется superproject) есть свои боли. В частности, он не очень легко импортируется во всякие ide. И еще такие external должны уметь инсталлиться, чтобы их можно было подхватить из следующего по цепочке, чего в непубличных наколленных CMakeLists.txt обычно нет. И еще детект изменений и их пересборка тоже похрамывает, но тут есть разные варианты.
У меня проект себя рекурсивно зовет с несколькими стадиями. Первая — 3rdparty с инсталлами в единую stage dir. Потом основной проект, который всякими вариациями find_* добывает себе эти либы.
Нужно именно все собрать в кучу, чтобы в один корень в IDE засунуть? Если нет, то можно пробегаться по всем папкам скриптом и билдить все проекты отдельно.
А если нужно поддерживать все логически как солюшен, то и иерархию имеет смысл строить иначе: солюшен и его симейк, а рядом подпаски с проектами – так логичнее и симейк все корректно будет воспринимать.
Здравствуйте, andrey.desman, Вы писали:
AD>С этим вариантом (который в рамках cmake и называется superproject) есть свои боли.
Где в документации CMake определен термин "superproject"?
AD>В частности, он не очень легко импортируется во всякие ide.
Это проблемы твоей IDE.
AD>И еще такие external должны уметь инсталлиться, чтобы их можно было подхватить из следующего по цепочке, чего в непубличных наколленных CMakeLists.txt обычно нет. И еще детект изменений и их пересборка тоже похрамывает, но тут есть разные варианты.
Управление сборкой после изменений — это собственно то, ради чего CMake и существует, если что-то не работает, то это фундаментальный баг. Приводи восроизводимый пример.
AD>У меня проект себя рекурсивно зовет с несколькими стадиями. Первая — 3rdparty с инсталлами в единую stage dir. Потом основной проект, который всякими вариациями find_* добывает себе эти либы.
Месье знает толк...
add_subdirectory нормально работает только с подкатологами (сюрприз), так что со всеми остальными решениями будут проблемы.
Еще можно посмотреть что твоя IDE предлагает. Например, в QtCreator есть понятие "сессии" — набор открытых проектов и т.п. В рамках сессии можно задать зависимости между проектами. Практический эффект примерно такой же.
Здравствуйте, Skorodum, Вы писали:
AD>>С этим вариантом (который в рамках cmake и называется superproject) есть свои боли. S>Где в документации CMake определен термин "superproject"?
Нигде, это паттерн. superbuild его называют, но смысл тот же.
AD>>В частности, он не очень легко импортируется во всякие ide. S>Это проблемы твоей IDE.
У меня нет IDE, значит и нет проблем. А кто IDE юзает, так там external project не факт, что импортятся, например CLion не может. https://youtrack.jetbrains.com/issue/CPP-11484/Better-support-for-CMake-superbuild-pattern
AD>>И еще такие external должны уметь инсталлиться, чтобы их можно было подхватить из следующего по цепочке, чего в непубличных наколленных CMakeLists.txt обычно нет. И еще детект изменений и их пересборка тоже похрамывает, но тут есть разные варианты. S>Управление сборкой после изменений — это собственно то, ради чего CMake и существует, если что-то не работает, то это фундаментальный баг. Приводи восроизводимый пример.
Ты не про то вообще. Речь об externalproject и их пересборке. А так же об остальных тулах типа autotools, bazel и ninja, которые этот externalproject собирает.
AD>>У меня проект себя рекурсивно зовет с несколькими стадиями. Первая — 3rdparty с инсталлами в единую stage dir. Потом основной проект, который всякими вариациями find_* добывает себе эти либы. S>Месье знает толк...
Вот че сказать хотел? Гавна набросил, а полезного в посте ноль.
Я знаю толк, да. Таков путь если юзаешь CMake и собираешь что-то посложнее библиотеки.
Здравствуйте, Skorodum, Вы писали:
S>add_subdirectory нормально работает только с подкатологами (сюрприз), так что со всеми остальными решениями будут проблемы.
Я подозревал, но надеялся, что сработает
S>Еще можно посмотреть что твоя IDE предлагает. Например, в QtCreator есть понятие "сессии" — набор открытых проектов и т.п. В рамках сессии можно задать зависимости между проектами. Практический эффект примерно такой же.
Это обычно вроде workspace называют. В Eclipse, или CodeBlocks, например.
В MSVS этому аналог — солюшн. В VSCode, если открывать CMakeLists.txt, сам CMakeLists.txt работает, как солюшн.
Но в MSVS я каждый экзешник или либу делал в отдельном файле проекта, и добавлял этот проект в разные произвольные солюшены, то при использовании CMakeLists.txt так не получается
Здравствуйте, andrey.desman, Вы писали:
AD>Нигде, это паттерн. superbuild его называют, но смысл тот же.
Это антипаттерн. И имя ему кривой костыль, отсюда и боль.
AD>У меня нет IDE, значит и нет проблем. А кто IDE юзает, так там external project не факт, что импортятся, например CLion не может. https://youtrack.jetbrains.com/issue/CPP-11484/Better-support-for-CMake-superbuild-pattern
Это смешение проблем управления зависимостями, системы сборки и IDE.
Если очень хочется собирать все зависимости вместе с проектом, то vcpkg делает именно это. Далее смотрим на интеграцию vcpkg и CMake (e.g. manifest mode) и, в последнюю очередь, решаем проблемы интеграции системы сборки с IDE (и все большие IDE умеют в CMake уже несколько лет).
AD>Ты не про то вообще. Речь об externalproject и их пересборке. А так же об остальных тулах типа autotools, bazel и ninja, которые этот externalproject собирает.
Что подразумевается под externalproject? Зависимости а-ля boost, Qt которые нужно скомпилировать вместе с проектом?
Если хочется собирать из исходников то vcpkg делает именно это, или устанвливать бинари явно, пути передавать через CMake preset. В чем проблема-то?
AD>Вот че сказать хотел? Гавна набросил, а полезного в посте ноль.
По существу я ТС-у ответил.
AD>Я знаю толк, да. Таков путь если юзаешь CMake и собираешь что-то посложнее библиотеки.
в рамках cmake и называется superproject
У меня проект себя рекурсивно зовет с несколькими стадиями.
Потом основной проект, который всякими вариациями find_* добывает себе эти либы.
Хорошая иллюстрация того, что управление сборкой проектов в С++ — сложная задача, при решении которой кривые костыли появляются еще чаще, чем в С++ коде.
З.Ы. Мы собираем в облаке для x86_64, ARM32/64, 8051, BA22, Win, Linux, macOS, в зависимостях и boost, и Qt, и десятки других библиотек, генеряться питоновские обвязки и т.д. Все работает на CMake и vcpkg. IDE — проблема разработчиков, но оно "просто работает". Люди пользуются студией, VS Code, QtCreator, CLion, Vim без проблем на винде маке и линухе.
Здравствуйте, Skorodum, Вы писали:
AD>>Нигде, это паттерн. superbuild его называют, но смысл тот же. S>Это антипаттерн. И имя ему кривой костыль, отсюда и боль.
Нет, не антипаттерн, и боль только у CLion, которому поприседать приходится для импорта. Да и та небольшая.
AD>>У меня нет IDE, значит и нет проблем. А кто IDE юзает, так там external project не факт, что импортятся, например CLion не может. https://youtrack.jetbrains.com/issue/CPP-11484/Better-support-for-CMake-superbuild-pattern S>Это смешение проблем управления зависимостями, системы сборки и IDE. S>Если очень хочется собирать все зависимости вместе с проектом, то vcpkg делает именно это. Далее смотрим на интеграцию vcpkg и CMake (e.g. manifest mode) и, в последнюю очередь, решаем проблемы интеграции системы сборки с IDE (и все большие IDE умеют в CMake уже несколько лет).
Да какая разница, будет это vcpkg, conan или сам хоть на шелл скриптах собирать будешь.
Все равно у CMake 2 стадии, как и у autotools каких-нибудь: конфигур и сборка. Вот на этапе конфигура все зависимости должны быть уже собраны и доступны, чтобы find_package работал. Конечно, можно собирать зависимости на этапе конфигура, но там свои подводные камни и вообще это не тру.
Так или иначе, придется приседать вручную: запускать vcpkg или conan, чтобы они слили и собрали зависимости, и только потом запускать cmake configure и build.
Вот супербилд — это способ не делать это вручную. Он просто билдит последовательно 2 проекта, не через add_subdirectory, а через externalproject. Можно, конечно, и на скриптах это сделать. Или еще на чем-нибудь, ну это дело вкуса и требований.
Вот такой супербилд не содержит исходников сам по себе, пожтому его импорт в IDE не имеет смысла. Импортировать надо главный подпроект, но после того, как зависимости скачались/собрались.
AD>>Ты не про то вообще. Речь об externalproject и их пересборке. А так же об остальных тулах типа autotools, bazel и ninja, которые этот externalproject собирает. S>Что подразумевается под externalproject? Зависимости а-ля boost, Qt которые нужно скомпилировать вместе с проектом?
ExternalProject позволяет что-то где-то взять/скачать (на этапе конфигура) и потом собрать (на этапе билда) условно "в отдельном процессе". В том числе и другие cmake проекты, не добавляя их явно через add_subdirectory (и не страдая от тех же коллизий имен).
Вот так можно разделить сборку на стадии.
S>Если хочется собирать из исходников то vcpkg делает именно это, или устанвливать бинари явно, пути передавать через CMake preset. В чем проблема-то?
А у меня и нет проблем. Я лишь говорил, что ТС в его случае это не нужно (было предложение выше).
S>Хорошая иллюстрация того, что управление сборкой проектов в С++ — сложная задача, при решении которой кривые костыли появляются еще чаще, чем в С++ коде.
Да всё решаемо. Но вот с CMake так. Не то чтобы это был какой-то костыль. Норм паттерн в целом, не хуже других.
S>З.Ы. Мы собираем в облаке для x86_64, ARM32/64, 8051, BA22, Win, Linux, macOS, в зависимостях и boost, и Qt, и десятки других библиотек, генеряться питоновские обвязки и т.д. Все работает на CMake и vcpkg. IDE — проблема разработчиков, но оно "просто работает". Люди пользуются студией, VS Code, QtCreator, CLion, Vim без проблем на винде маке и линухе.
Вот не хочется писать рецепт в разных системах сборки, да еще потом и в README, и синкать всё это.
Здравствуйте, andrey.desman, Вы писали:
AD>Так или иначе, придется приседать вручную: запускать vcpkg или conan, чтобы они слили и собрали зависимости, и только потом запускать cmake configure и build.
Нет, в этом и суть, что manifest mode делает это на этапе конфигурации:
Notice how the project's dependencies are automatically installed while configuring the project.
При этом для сборки зависимостей будут использованы тот же набор средств (toolchain) что и для основного проекта.
AD>Вот супербилд — это способ не делать это вручную.
Так ты вручную прописываешь как собирать, пути к компиляторам, версии и т.д, пути. То, что ты называешь "супербилд" — самописный велосипед. Такое имело право на существование лет 5-10 назад до прихода более-менее стандартных средств. Особенно, если у ТС используется CMake.
AD>Он просто билдит последовательно 2 проекта, не через add_subdirectory, а через externalproject. Можно, конечно, и на скриптах это сделать. Или еще на чем-нибудь, ну это дело вкуса и требований. AD>Вот такой супербилд не содержит исходников сам по себе, пожтому его импорт в IDE не имеет смысла. Импортировать надо главный подпроект, но после того, как зависимости скачались/собрались.
Как в твоих самописных скриптах задаются версии зависимостей?
Как задаются пути к средствам сборки?
Как задается порядок сборки?
Как синхронизируются настройки компилятора?
и т.д. и т.п.
AD>ExternalProject позволяет что-то где-то взять/скачать (на этапе конфигура) и потом собрать (на этапе билда) условно "в отдельном процессе". В том числе и другие cmake проекты, не добавляя их явно через add_subdirectory (и не страдая от тех же коллизий имен).
Это называется "сборка зависимостей из исходников", стандартное решение для такого подхода при использовании CMake — vcpkg.
AD>А у меня и нет проблем. Я лишь говорил, что ТС в его случае это не нужно (было предложение выше).
В описанном тобой решении — вагон и маленькая тележка проблем.
AD>Да всё решаемо. Но вот с CMake так. Не то чтобы это был какой-то костыль. Норм паттерн в целом, не хуже других.
Можешь привести пример как твой подход используется? Для простоты пусть будет С++ проект в котором требуется что-то компилируемое из буста + какие-нибудь глобальные настройки компилятора.
S>>З.Ы. Мы собираем в облаке для x86_64, ARM32/64, 8051, BA22, Win, Linux, macOS, в зависимостях и boost, и Qt, и десятки других библиотек, генеряться питоновские обвязки и т.д. Все работает на CMake и vcpkg. IDE — проблема разработчиков, но оно "просто работает". Люди пользуются студией, VS Code, QtCreator, CLion, Vim без проблем на винде маке и линухе.
AD>Вот не хочется писать рецепт в разных системах сборки, да еще потом и в README, и синкать всё это.
1. У нас система сборки одна — CMake, управление зависимостями — vcpkg, но ее даже явно вызывать не надо. Есть опция не собирать некоторые части, а использовать предустановленные пакеты.
2. Твоя альетернатива — писать свои скрипты, которые на другой машине работать не будут и которые следующий разработчик перепишет.
Здравствуйте, Skorodum, Вы писали:
S>add_subdirectory нормально работает только с подкатологами (сюрприз), так что со всеми остальными решениями будут проблемы.
Это верно в случае, если указывать только поддиректорию. Если указывать binary директорию, то можно без проблем ссылаться на подпроекты выше корня. У меня это делается и работает без проблем:
Add a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.txt and code files are located. If it is a relative path it will be evaluated with respect to the current directory (the typical usage), but it may also be an absolute path. The binary_dir specifies the directory in which to place the output files. If it is a relative path it will be evaluated with respect to the current output directory, but it may also be an absolute path. If binary_dir is not specified, the value of source_dir, before expanding any relative path, will be used (the typical usage). The CMakeLists.txt file in the specified source directory will be processed immediately by CMake before processing in the current input file continues beyond this command.
Здравствуйте, Videoman, Вы писали:
V>Это верно в случае, если указывать только поддиректорию. Если указывать binary директорию, то можно без проблем ссылаться на подпроекты выше корня. У меня это делается и работает без проблем: V>
Здравствуйте, Skorodum, Вы писали:
S>Нет, в этом и суть, что manifest mode делает это на этапе конфигурации: S>
S>Notice how the project's dependencies are automatically installed while configuring the project.
S>При этом для сборки зависимостей будут использованы тот же набор средств (toolchain) что и для основного проекта.
Сборка на этапе конфига — это костыль и есть.
AD>>Вот супербилд — это способ не делать это вручную. S>Так ты вручную прописываешь как собирать, пути к компиляторам, версии и т.д, пути. То, что ты называешь "супербилд" — самописный велосипед. Такое имело право на существование лет 5-10 назад до прихода более-менее стандартных средств. Особенно, если у ТС используется CMake.
Ты путаешь. Я зависимости собираю сам, потому что мне так удобнее. Все библиотеки лежат в git-lfs, и и какой-то менеджер пакетов здесь лишний. Но это не важно. Супербилд — это управление подпроектами, а не зависимостями и пакетами. Подпроектом может быть любой билд, в том числе и установка из vcpkg/conan, компиляция из исходников и прочее. Зачем мы будем обсуждать кака я собираю зависимости, если супербилд не об этом?
S>Как в твоих самописных скриптах задаются версии зависимостей?
У меня как раз нет самописных скриптов, ты как-то не то читаешь. Наоборот, всё собирается через cmake. При том без внешних зависимостей от conan или vcpkg.
Версии не задаются, сюрпризов нет. Все библиотеки собираются явно из явных архивов. Нет такого, что я указываю собрать ffmpeg 7.0, а он транзитивно тянет, что хочет в конфиге, который кто-то другой прописал. Только то, что мне нужно, что я положил в репу и настроил.
S>Как задаются пути к средствам сборки? S>Как задается порядок сборки? S>Как синхронизируются настройки компилятора? S>и т.д. и т.п.
Это все делается средствами cmake. Да, в супербилде надо основные какие-то настройки передать в подпроекты явно.
AD>>ExternalProject позволяет что-то где-то взять/скачать (на этапе конфигура) и потом собрать (на этапе билда) условно "в отдельном процессе". В том числе и другие cmake проекты, не добавляя их явно через add_subdirectory (и не страдая от тех же коллизий имен). S>Это называется "сборка зависимостей из исходников", стандартное решение для такого подхода при использовании CMake — vcpkg.
Почему vcpkg? Нет стандартного решения. Где-то vcpkg подойдет, не вопрос.
AD>>А у меня и нет проблем. Я лишь говорил, что ТС в его случае это не нужно (было предложение выше). S>В описанном тобой решении — вагон и маленькая тележка проблем.
Нет никаких проблем.
AD>>Да всё решаемо. Но вот с CMake так. Не то чтобы это был какой-то костыль. Норм паттерн в целом, не хуже других. S>Можешь привести пример как твой подход используется? Для простоты пусть будет С++ проект в котором требуется что-то компилируемое из буста + какие-нибудь глобальные настройки компилятора.
Условно, рут CMakeLists.txt делает externalproject_add с 3rdparty/CMakeLists.txt, который собирает все зависимости. Этот CMakeLists.txt мог бы вызывать и vcpkg, или conan, но у меня собирает сам, потому что это проще. Все 3rdparty инсталлятся в определенную директорию навроде ${build}/3rdparty/usr/local.
Так же Рут добавляет таргет через externalproject_add на подпроект, который в общем-то основной, и зависит от 3rdparty. По определению, собирается позже 3rdparty, и уже имеет все .cmake и .pc файлы для поиска библиотек в том самом ${build}/3rdparty/usr/local.
В минимально простом варианте можно глянуть тут: https://github.com/Sarcasm/cmake-superbuild
Хотя мне и не нравится, что он сделан в виде списка ( в смысле, что он использует свой инстанс для чего-то кроме управления билдами).
AD>>Вот не хочется писать рецепт в разных системах сборки, да еще потом и в README, и синкать всё это. S>1. У нас система сборки одна — CMake, управление зависимостями — vcpkg, но ее даже явно вызывать не надо. Есть опция не собирать некоторые части, а использовать предустановленные пакеты.
Работает и хватает — и хорошо. Мне часто требуется добавлять патчи и включать/выключать опции. Это можно сделать через пакетный менеджер, но бороться с ним приходится чаще, чем получать выгоду.
S>2. Твоя альетернатива — писать свои скрипты, которые на другой машине работать не будут и которые следующий разработчик перепишет.
И опять же, ты что-то путаешь, у меня нет скриптов. Супербилд как раз от них избавляет.
Здравствуйте, andrey.desman, Вы писали:
AD>Сборка на этапе конфига — это костыль и есть.
Нет, т.к. CMake + vcpkg это наиболее популярное решение промышленном С++ мире сейчас.
AD>>>Вот супербилд — это способ не делать это вручную. S>>Так ты вручную прописываешь как собирать, пути к компиляторам, версии и т.д, пути. То, что ты называешь "супербилд" — самописный велосипед. Такое имело право на существование лет 5-10 назад до прихода более-менее стандартных средств. Особенно, если у ТС используется CMake. AD>Ты путаешь.
Что именно? Какое утверждение не верно?
AD>Я зависимости собираю сам, потому что мне так удобнее.
Когда ты один разработчик под одну платформу на одном хосте — ты можешь делать как угодно. Я же про промышленное управление сборкой говорю, особенно когда надо поддерживать разные компиляторы, платформы и т.д.
AD>Все библиотеки лежат в git-lfs, и и какой-то менеджер пакетов здесь лишний.
Т.е. ты используешь git-lfs в роли бинарного кэша и вместа чего-то стандартного типа "apt/vcpkg install" пользователь должен делать "git clone". Интересное решение.
AD>У меня как раз нет самописных скриптов, ты как-то не то читаешь. Наоборот, всё собирается через cmake. При том без внешних зависимостей от conan или vcpkg.
Ну т.е. никак, когда нужна новая версия ты ручками пересобираешь под все платформы. Ты же понимаешь, что это не масштабируемое решение.
S>>Как задаются пути к средствам сборки? S>>Как задается порядок сборки? S>>Как синхронизируются настройки компилятора? S>>и т.д. и т.п.
AD>Это все делается средствами cmake. Да, в супербилде надо основные какие-то настройки передать в подпроекты явно.
А как ты синхронизируешь эти настройки со сборкой зависимостей? Допустим тебе надо собрать все каким-то особым компилятором или с особым ключом, сколько раз тебе придется повторять это параметер? При нормально использовании CMake — один раз в toolchain файле.
AD>В минимально простом варианте можно глянуть тут: https://github.com/Sarcasm/cmake-superbuild
...11 years ago..
11 лет назад это имело право на существование, сейчас это очень плохое решение.
Для примера сейчас это решается vcpkg.json:
И стандартное cmake && cmake --build будет работать везде где есть vcpkg.
AD>И опять же, ты что-то путаешь, у меня нет скриптов. Супербилд как раз от них избавляет.
Заметь, ты все время пишеше "у меня", а я "у нас".
Скажи пожалуйста, сколько компиляторов тебе надо поддерживать? Сколько людей работает над кодом, какие хосты и целевые платформы?
Скорее всего, у нас очень разные требования к проектам поэтому и нет понимания.