Комментарии 34
add_definitions("-std=c++20")
Рассказывать про кроссплатформенность и ломать её на пятой строчке приложенного CMakeLists.txt - это сильно.
Нормальным способом было бы вот такое
set(CMAKE_CXX_STANDARD 20)
Или такое
set_property(TARGET app PROPERTY CXX_STANDARD 20)
file(GLOB...) использовать не рекоммендуется https://cmake.org/cmake/help/latest/command/file.html#filesystem
project(library)
И потом создаётся executable? Если это инструкция для новичка, то пускай она хотя-бы будет консистентной. Я уж не говорю о том, что советовать копипастить какие-то магические заклинания без их понимания - моветон
Нормальным способом было бы вот такое
Спасибо, подправил
file(GLOB...) использовать не рекомендуется
glob используется с определенной целью - не дублировать списки файлов с кодом для двух таргетов (приложение и тесты). Если вы знаете как сделать лучше, то было бы здорово услышать.
Если это инструкция для новичка, то пускай она хотя-бы будет консистентной.
Вы правы, привел названия проекта и исполняемых файлов в консистентный вид.
копипастить какие-то магические заклинания без их понимания - моветон
Ключевые аспекты я задокументировал, все остальное просто подгружает conan-wrapper
glob используется с определенной целью - не дублировать списки файлов с кодом для двух таргетов (приложение и тесты). Если вы знаете как сделать лучше, то было бы здорово услышать.
Составить список исходников вручную. Т.е.
set( SOURCE_LIST
main.cpp
component1.cpp
component2.cpp)
И потом использовать этот список так же, как сейчас. Это убирает один магический момент и решает проблему необходимости перезапуска cmake вручную для обнаружения новых файлов при их добавлении.
С точки зрения прозрачности может и так, однако... Подключать ручками каждый раз новые файлы грустновато на мой взгляд. И к тому же это ломает всю возможность "добавить CMakeLists.txt в существующий проект и полетели", что усложнило бы инструкцию.
Чтобы не копипастить списки файлов, можно использовать статическую библиотеку.
Ещё можно получить список файлов через get_target_properties. Можно сделать список, как выше посоветовали.
По идее, если вы хотите скомпилироваться с полным списком cpp-файлов, ваш выбор — статическая библиотека.
По идее, если вы хотите скомпилироваться с полным списком cpp-файлов, ваш выбор — статическая библиотека.
Тогда в инструкции для людей вчера запускавших код через IDE придется написать "а теперь мы сделаем статическую библиотеку для своего же кода, потому что пуристы решили что так идиоматически правильнее" =)
Не находите что это слишком сложновато будет?
"а теперь мы разобьём ваш main()
на 24 функции по 10 строк, т.к. пуристы решили, что так идеоматически правильнее"
Но, всё же, пуристом я себя не считаю. Да и про идиоматическую правильность готов поспорить: в условиях отсутствия кэша компилятора дважды включённые исходники должны компилиться дважды. А вот в случае статической библиотеки — не должны.
Тю. Я как-то писал библиотеку, с возможностью сборки и shared и static. Что бы не дублировать ничего я завел отдельный object target, который линковался в конечные статическую и динамическую библиотеку.
чтобы CMake мог перегенерировать проект
Так это и происходит в инструкции каждый раз перед сборкой: перегенерируется проект.
Составить список исходников вручную. Т.е.set( SOURCE_LIST ...
Modern CMake рекомендует использовать таргеты. Т.е.:
target_sources(test PRIVATE main.cpp component1.cpp component2.cpp)
не дублировать списки файлов с кодом для двух таргетов
Можно получить список файлов:
$<TARGET_PROPERTY:test , SOURCES>
target_compile_features(app PRIVATE cxx_std_17)
Это один из наиболее правильных путей, поскольку настройка будет связана с одной конкретной целью, а не всем проектом целиком.
Я недавно перешёл на vcpkg в режиме манифеста. Субъективно - проще и шустрее чем conan. Плюс не тянет за собой питон.
Насчёт file glob не соглашусь с комментариями выше (может и минусов отхвачу) - я не вижу ничего плохого в его использовании, если понимаешь что делаешь. Очень удобно для быстрорастущих проектов куда часто добавляются новые файлы. А на одном большом проекте у нас был простенький скрипт, который пробегался по каталогу с исходниками и считал хэш от суммы всех путей. Если хэш поменялся - значит надо переиндексировать файлы.
Ключевое здесь - если понимаешь, что делаешь.
Но статья - инструкция для новичков. Мне кажется, статья была бы чуточку лучше, если бы по поводу glob (да и не только его) было рассказано подробнее - что это, зачем это здесь, какие есть еще варианты.
Кому надо - тот прочитает и разберется. Кому это не надо - возьмёт и скопипастит исходный скрипт сборки, чтобы не заморачиваться и просто обеспечить сборку своего проекта.
Спасибо! Как раз начинаю новый проект и решил попробовать cmake, чтобы не привязывать коллег к одной IDE и упростить подключение библиотек.
Вот как раз вопрос есть - можно ли для основного проекта использовать один компилятор (кросс), а для тестов - другой (хост)? Или надо два раза запускать cmake с разными каталогами сборки и параметрами?
Это проблема отчасти порождается спорной практикой в обучении, когда код учат писать и запускать средствами IDE, таких как Visual Studio, Code::Blocks, и других. Поначалу такой подход работает, но лишь до первой реальной задачи сделать что-то, что запустится не только на вашем компьютере.
билдим что то в Visual Studio с static Run-Time Library и наш ехе запускается на любой windows машине. Ок, почти на любой если версия не супер древняя, но там зачастую достаточно поставить последний Redistributable Package.
Если проект в исходниках то билдится в студии на любой машине. Но опять же при наличии одинаковых версий SDK и DDK
Почти все популярные либы имеют встроенный солюшен для сборки через студию.
За 20+ лет ни разу не сталкивался с тем чтобы проект VisualStudio не переносился на другую машину с такой же операционкой windows.
99 из 100 переносится без каких либо танцев с бубнами. 1 из 100 танцы были связаны с кривыми руками владельца машины приемника когда в windows environment было всякого хлама понапрописано что вызывало конфликты в проекте.
Под Linux, Android и iOS умеет проекты собирать так же из коробки.
Поэтому у меня именно эта ваша фраза вызвала недоумение.
А как собрать ваш проект под macOS, под Ubuntu? Как собрать под той-же Windows в другой IDE, Code::Blocks или CLion например?
Вы описываете Windows-only решение, а статья про кроссплатформенный C++
А как собрать ваш проект под macOS,
из "коробки" идет поддержка macOS и iOS
Вы описываете Windows-only решение, а статья про кроссплатформенный C++
Windows, Android, iOS, Linux, Azure, macOS, tvOS XBox
Вот хоть глаза мне выколи но я не вижу Windows-only.
У меня, например, мой игровой инди проект сразу билдится под Windows, Android и iOS
Или надо два раза запускать cmake с разными каталогами сборки и параметрами?
А я сталкивался с чудной практикой установки библиотек глобально в директорию ОС и установкой зависимости от такого пути. Разумеется эти VS проекты были непереносимы.
Microsoft наборот продвигает CMake в последних версиях VS, кстати.
Я вижу разницу между загрузкой всего проекта ради VS solution и указанием зависимости в скрипте одной строчкой. Объясните, как в первом случае вы будете обновлять свой проект? Дайте угадаю, снова загрузите всю зависимость целиком...
Этот подход работает, но, увы, только если у вас проект уровня Hello World. Стоит докинуть пару усложнений вроде внешней зависимости не в вашем любимом пакетном менеджере или кодогенератора - и CMakeLists начинает шустро так распухать. Это усугубляется крайне убогим уровнем скриптового языка CMake. Один гигакостыль generator expressions чего стоит. К примеру, задача добавить в PATH или ещё куда пути всех зависимостей при запуске под отладчиком до сих пор решается руками.
В целом же, одна из основных проблем С++ - крайне фрагментированный тулинг. Интероп между разными системами сборки или пакетными менеджерами отсутствует как класс. Либо используешь фиксированный набор вроде CMake+VCPKG, либо вынужден покупать асбестовый стул.
С тем же успехом можно сказать, что они переезжают на conan, или на vcpkg, а самые большие проекты переезжают на собственные велосипеды, ибо никто снаружи компании не обслужит нужды сборки в компании лучше, чем её сотрудник.
Хотя, не буду скрывать, системы сборки/управления пакетами в C++ мне не нравятся. И да, я с завистью поглядываю в лагерь Rust с их Cargo.
Я не пишу на плюсах, и вообще мимокрокодил, но вот это
REGEX ".*Main.cpp$"
не доставит проблем, если будет какой-нибудь файл вроде ProductMain.cpp ?
Может быть, лучше поменять на ".*/Main.cpp$"
У Visual Studio, к примеру, сборщиком по умолчанию является MSBuild, а у CLion - CMake.
CMake не является системой сборки. Это генератор скриптов для системы сборки. Если вы используете Linux, то CMake по-умолчанию будет генерировать Makefile'ы. Если же вы сидите на Windows и у вас стоит VS, то CMake по-умолчанию генерирует скрипты для MSBuild. На маках так вообще две нативные системы: Makefiles и XCode (не знаю как он под капотом работает, может тоже через Makefiles).
Справедливо и другое: CLion может вызывать MSBuild, а Visual Studio может работать с Ninja.
Короче, гуглите про ключ -G для CMake.
conan есть, а ctest, cpack нет. project() не увидел.
и сразу conan который сам по себе тож зависимость? только теперь мы еще и навязываем его остальным.
Тайные знания: библиотеки для С++