Это нормально баловать себя как разработчика. Я серьезно. Упростите себе задачу. Показательный пример: ограничьте количество вещей, которые вам нужно сделать в жизненном цикле разработки.

В этой статье я описываю, как настроить рабочий процесс C++/CMake, который будет автоматически создавать, компилировать и тестировать вашу программу, когда вы нажмете СОХРАНИТЬ.

Это будет окончательный результат:

Он не отображается, но я сохраняю файл (через vim) с помощью escape + :w. Когда я это делаю, правая сторона начинает брызгать.

Сделать это проще

Я помню, как впервые увидел автоматическую сборку приложений React. Я думал, что это обман. Я внесу изменения, нажму «Сохранить» и сразу же увижу их в браузере. Более того, я мог написать модульные тесты, сохранить файл и сразу же посмотреть, пройден ли тест.

Итак, представьте 💡 момент, когда я начал разработку проекта C++. В колледже я, конечно, ничего не знал о системах сборки. тогда CMake даже не существовало, а до Docker оставалось еще пару лет, так что все приходилось делать по старинке: gcc program.c -o program. К счастью, я был пользователем Linux, но я уверен, что студенты, изучающие Windows, разочаровываются больше.

Хватит дней Дикого Дикого Запада g++ 🤠. Приступим к самой интересной части автоматизации! 😝

Для нетерпеливых

Есть репозиторий с этим примером, который можно использовать как шаблонный код: https://github.com/src-r-r/cmake-automation-example.

Монтирование томов

Моей первой задачей было организовать оптимизированную сборку.

Я выбрал образ докера danger89/cmake, так как он уже имел CMake и казался довольно стабильным.

Затем мне нужен был способ построить мой проект в докере.

Это невозможно сделать в Dockerfile. Если вы скопируете свой проект с помощью COPY , он будет скопирован в контейнер докера и не изменится. Должен быть способ обновить код в контейнере докеров, когда хост изменит его.

Итак, вместо этого проект должен быть смонтирован как том:

$ docker run -v ./my_project/my_project danger89/cmake

Или, поскольку мне лень, в файле компоновки:

Нам нужен собственный Dockerfile

Совсем маленький… в базовой сборке danger89/cmake не установлено entr. Если вы не хотите использовать файл dockerfile, включите некоторый код, чтобы проверить, установлен ли он в сценарии init.sh (показан ниже), прежде чем запускать его.

Автоматизация сборки и тестирования

Теперь мы переходим к самой интересной части: запуск сборки (и тестирования) при сохранении файла.

Пока мы редактируем что-либо в каталоге ./my_project, это возможно.

Если вы используете node, вы, вероятно, пересекались с инструментом под названием nodemon, который отслеживает изменения в файловой системе, а затем запускает команду при изменении любого отслеживаемого файла.

Я начал думать, что это был билет. Однако вскоре я обнаружил, что это не так.

Чтобы начать автоматическую сборку, мне нужно было сделать следующее:

  • Следите за изменениями в CMakeLists.txt, затем запустите cmake .
  • Следите за изменениями под src, затем запустите make и тестовый исполняемый файл.

Nodemon отслеживает расширения пути, поэтому мне нужно следить за txt и предоставлять команду для этого, затем отслеживать cpp и предоставлять команду для этого, затем отслеживать hpp и предоставлять команду для этого. Слишком много незавершенных вопросов и недостаточно детализации.

Введите ввод

Вместо этого есть утилита Linux под названием entr, которая позволяет вам следить за изменениями файловой системы и запускать команду.

Итак, чтобы отслеживать изменения для CMakeLists.txt и любых файлов src, выполните следующее:

$ ls ${PROJ_ROOT}/CMakeLists.txt ${PROJ_ROOT}/src/* | entr -d "/init.sh"

Где ${PROJ_ROOT} — это (конечно) корень проекта.

Что в Инит?

В рамках init.sh мы будем запускать cmake, make, а затем запускать тесты.

Теперь некоторые из вас, «экспертов», вероятно, будут ругать меня за сборку и компиляцию как на этапе сборки, так и на этапе компиляции. Правда, если бы мы делали это «правильно», мы бы наблюдали за CMakeLists.txt и выполняли cmake, затем наблюдали за src (параллельно) и запускали make.

Но заставить эти параллельные процессы работать — кошмар. Так что на данный момент этого достаточно.

Ну, почти…

Выход при ошибке

Прямо сейчас этот скрипт будет запускать cmake, make и test , безоговорочно делая то, что ему сказано. Это то, чего мы хотим? Нет, мы хотим выйти из-за ошибки.

Мы делаем это, устанавливая set -e вверху файла:

Таким образом, если какая-либо из этих команд завершится ошибкой, сценарий не будет работать.

И не беспокойтесь о enter … он продолжит просмотр файлов и снова запустит /init.sh, если что-то изменится.

Наводим порядок 🎁

До сих пор мы будем видеть МНОГО входных данных.

Мы беспокоимся только тогда, когда все идет хорошо… так почему бы просто не показать нам сцену, когда что-то пойдет не так?

Если вы использовали терминал, вы, несомненно, использовали clear для очистки терминала или reset для сброса сеанса терминала.

В сценариях BASH есть еще один менее известный протокол очистки, который делает это намного чище: printf "\033c" . Это в основном делает жесткую очистку экрана терминала.

Итак, давайте включим его в наш скрипт инициализации:

И мы совершенно нормально делаем это… потому что, помните, мы используем set -e , поэтому, например, если cmake терпит неудачу, сценарий BASH завершается прямо здесь, поэтому строка printf не затрагивается.

Интеграция в Докер

Теперь, куда мы поместим эти скрипты?

Приведенный выше сценарий инициализации я поместил в init.sh , который смонтирован на томе докера /init.sh.

Команду для enter я поместил в скрипт под названием watch.sh, который монтируется в /watch.sh в докере.

Таким образом, файл компоновки с этими смонтированными файлами будет выглядеть так:

Убедитесь, что эти файлы имеют права на выполнение на хосте.

Теперь мы можем легко запустить контейнер my_project и сразу начать просмотр файлов (помните, мы уже запускали docker-compose build ).

Если вы не запускали docker-compose build, не волнуйтесь — вы получите тот же результат… просто это займет больше времени.

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

Теперь мы можем запустить docker compose:

$ docker-compose up

И теперь, как по волшебству, проект собирается, компилируется и запускает модульные тесты каждый раз, когда мы сохраняем файл!

Использование без докера

Если по какой-то причине вы не хотите использовать докер или хотите взять что-то из докера для отладки «в автономном режиме», скрипт будет работать точно так же.

Все, что вам нужно сделать, это изменить некоторые пути в watch.sh и init.sh. Одна вещь, которую я обычно люблю делать, — это получить текущий каталог скрипта и добавить его в начало скрипта BASH (благодаря легенде Dave Dopson at StackOverflow):

Убедитесь, что PROJ_DIR назначено ${DIR} в сценариях init.sh и watch.sh (убедитесь, что приведенный выше фрагмент находится в ОБОИХ), и вы должны быть золотыми.

Теперь запустите ./watch.sh и (если вы все установили) проект должен автоматизировать сборку.

В этой статье я подробно описал, как настроить систему для автоматической сборки, компиляции и запуска проекта C++/CMake всякий раз, когда вы сохраняете файл.

Как указано выше, код примера доступен здесь: https://github.com/src-r-r/cmake-automation-example. Не стесняйтесь использовать его в своем собственном проекте

Если вам понравилась эта статья, пожалуйста, поделитесь ею с несколькими друзьями. Прокомментируйте, что вы нашли интересным, разочаровывающим или странным.

❤️❤️❤️

Если вы хотите получать больше статей (и получать их на 2 дня раньше!), рассмотрите возможность стать сторонником ko-fi:

https://ko-fi.com/damngood/tiers.

❤️❤️❤️