раздел 02 · инструменты
ОТ MAKE ДО BAZEL
Один и тот же проект — четыре способа его описать. Сравним синтаксис, философию и скорость главных инструментов экосистемы.
2.1
Один проект — четыре описания
CXX := g++
CXXFLAGS := -std=c++20 -Wall -O2
SRC := main.cpp parser.cpp engine.cpp
OBJ := $(SRC:.cpp=.o)
app: $(OBJ)
$(CXX) $(CXXFLAGS) -o $@ $^
%.o: %.cpp parser.h engine.h
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f app $(OBJ)Сильные стороны
- есть в любой UNIX-системе из коробки
- нулевой порог входа для пары файлов
- полный контроль над каждой командой
Слабые стороны
- зависимости приходится поддерживать вручную
- нет абстракции целей и переносимости на Windows
- сложные проекты превращаются в спагетти
cmake_minimum_required(VERSION 3.25)
project(engine_lab CXX)
add_library(core
src/parser.cpp
src/engine.cpp)
target_include_directories(core PUBLIC include)
target_compile_features(core PRIVATE cxx_std_20)
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE core)Сильные стороны
- стандарт индустрии: почти все библиотеки «говорят» на нём
- цели несут свойства: флаги, инклуды, зависимости — всё наследуется
- генерирует проекты для любого нативного инструмента
Слабые стороны
- исторический синтаксис требует дисциплины
- легко выстрелить в ногу глобальными переменными
# обычно генерирует CMake — руками не пишут
rule cc
command = g++ -std=c++20 -O2 -MMD -c $in -o $out
depfile = $out.d
description = CC $out
rule link
command = g++ $in -o $out
description = LINK $out
build main.o: cc main.cpp
build parser.o: cc parser.cpp
build app: link main.o parser.oСильные стороны
- экстремально быстрый старт даже на десятках тысяч целей
- точный учёт зависимостей через .d-файлы компилятора
- минимализм: только исполнение графа
Слабые стороны
- не предназначен для ручного написания
- нет абстракций: библиотеки, флаги — всё этажом выше
project('engine_lab', 'cpp',
default_options : ['cpp_std=c++20', 'buildtype=release'])
src = ['src/main.cpp', 'src/parser.cpp', 'src/engine.cpp']
inc = include_directories('include')
executable('app', src,
include_directories : inc,
install : true)Сильные стороны
- человекочитаемый синтаксис в духе Python
- скорость Ninja под капотом по умолчанию
- внятные сообщения об ошибках
Слабые стороны
- экосистема скромнее, чем у CMake
- меньше примеров и ответов на stackoverflow
2.2
Сравнительная таблица
| Инструмент | Уровень | Язык описания | Скорость | Кроссплатформа | Экосистема |
|---|---|---|---|---|---|
| Make | низкий | Makefile | ●●●●● | ●●●●● | ●●●●● |
| CMake | высокий | CMake-скрипт | ●●●●● | ●●●●● | ●●●●● |
| Ninja | генератор | генерируемый | ●●●●● | ●●●●● | ●●●●● |
| Meson | высокий | Python-подобный | ●●●●● | ●●●●● | ●●●●● |
| Bazel | монорепо | Starlark | ●●●●● | ●●●●● | ●●●●● |
2.3
Что выбрать
// новый проект
Библиотека или приложение с прицелом на рост и интеграции.
→ CMake + генератор Ninja// монорепозиторий
Сотни пакетов, много команд, нужна герметичность и удалённое кэширование.
→ Bazel / Buck2// embedded и минимализм
Мало файлов, нестандартный тулчейн, хочется контролировать каждый флаг.
→ Make или xmake