Открыть сервисСервис

Компилятор protoc

Protoc — это компилятор Protocol Buffers, предназначенный для генерации исходного кода на различных языках программирования на основе описаний структур данных, заданных в файлах .proto. Protoc является основным инструментом экосистемы Protocol Buffers (protobuf) — механизма сериализации структурированных данных, разработанного компанией Google и используемого для обмена данными между сервисами, хранения и межпроцессного взаимодействия.

История

Протокол буферы были созданы в Google в начале 2000-х годов для решения проблем, связанных с производительностью и сложностью XML-сериализации. Первая публичная версия (protobuf 2.0) была выпущена в 2008 году вместе с компилятором protoc. В 2016 году была представлена версия proto3, которая упростила синтаксис и добавила поддержку новых языков. С момента выхода protoc стал стандартом де-факто для генерации кода в микросервисных архитектурах, особенно в системах, использующих gRPC.

Архитектура и принцип работы

Protoc работает в несколько этапов:

  1. Парсингчтение файлов .proto, проверка синтаксиса и разрешение импортов.
  2. Построение промежуточного представления — создание внутреннего дерева разбора (AST) с полной информацией о сообщениях, полях, перечислениях и сервисах.
  3. Генерация кода — вызов плагинов, которые преобразуют AST в исходный код на целевом языке.

Компилятор не генерирует код сам — он делегирует эту задачу внешним плагинам (например, protoc-gen-go, protoc-gen-java). Это позволяет добавлять поддержку новых языков без изменения ядра protoc.

Поддерживаемые языки

Официальная поддержка Google включает следующие языки:

Для каждого языка существует отдельный плагин, который распространяется как часть соответствующей библиотеки protobuf. Кроме того, существуют сторонние плагины для Rust, Swift, Kotlin, TypeScript и других языков.

Синтаксис файлов .proto

Файлы .proto описывают структуры данных с использованием декларативного языка. Основные элементы:

Пример простого файла .proto:

```protobuf syntax = "proto3";

message Person { string name = 1; int32 id = 2; string email = 3; } ```

Использование protoc

Типичная команда для генерации кода выглядит следующим образом:

``bash protoc --proto_path=./protos --cpp_out=./gen person.proto ``

Основные флаги:

  • --proto_path (или -I) — путь к директории с .proto-файлами.
  • --cpp_out, --java_out, --go_out и т. д. — выходная директория для сгенерированного кода на соответствующем языке.
  • --plugin — путь к внешнему плагину, если он не установлен в системе.
  • --grpc_out — генерация gRPC-кода (требуется дополнительный плагин).

Protoc также поддерживает опцию --descriptor_set_out для генерации дескрипторов — бинарных файлов, описывающих схему данных без генерации кода.

Плагины и расширяемость

Protoc имеет встроенную систему плагинов. Плагин — это исполняемый файл, имя которого начинается с protoc-gen-. Например, плагин для Go называется protoc-gen-go. При запуске protoc передаёт плагину через stdin сериализованный объект CodeGeneratorRequest, а плагин возвращает через stdout CodeGeneratorResponse с сгенерированными файлами.

Эта архитектура позволяет:

  • добавлять поддержку новых языков;
  • генерировать не только код, но и документацию, схемы баз данных, конфигурации;
  • создавать кастомные кодогенераторы для специфических нужд проекта.

Версии и совместимость

Существует две основные версии синтаксиса: proto2 (устаревшая) и proto3 (актуальная). Protoc поддерживает обе, но по умолчанию использует proto3, если не указано syntax = "proto2". Версии протокола не полностью обратно совместимы — например, proto3 удалил поддержку пользовательских значений по умолчанию и required-полей.

Версии самого protoc нумеруются по схеме major.minor.patch. Начиная с версии 3.0.0, Google гарантирует, что сгенерированный код совместим с библиотеками той же мажорной версии.

Интеграция с системами сборки

Protoc часто интегрируется в процессы сборки через:

  • CMake — с помощью функции protobuf_generate.
  • Bazel — через правила proto_library.
  • Maven — через плагин protobuf-maven-plugin.
  • Gradle — через плагин com.google.protobuf.
  • Makefile — прямым вызовом protoc.

В современных проектах генерацию кода обычно автоматизируют, чтобы избежать ручного запуска protoc и гарантировать актуальность сгенерированных файлов при изменении .proto-схем.

Ограничения и критика

Несмотря на широкое распространение, protoc имеет ряд недостатков:

  • Сложность настройки — для каждого языка требуется отдельный плагин, а для gRPC — ещё один.
  • Размер сгенерированного кода — для больших схем генерируются объёмные файлы, что может замедлить компиляцию проекта.
  • Отсутствие встроенной поддержки валидации — protoc проверяет только синтаксис, но не семантику (например, уникальность имён полей в разных сообщениях).
  • Проблемы с версионированием — при обновлении protoc или библиотек protobuf могут возникать несовместимости.

Альтернативой protoc являются:

  • buf — современный инструмент для работы с protobuf, включающий линтер, брейкинг-детектор и генератор кода.
  • prototool — утилита для управления protobuf-проектами (сейчас менее популярна).
  • gRPC-Web — для генерации кода в веб-среде.

Применение в России

В российских компаниях protoc активно используется в микросервисных архитектурах, особенно в системах, построенных на gRPC. Крупные технологические компании (Яндекс, VK, СберТех) применяют protobuf и protoc для внутренних коммуникаций и API. В некоторых проектах protoc заменяется на buf из-за его более удобного интерфейса и встроенной проверки обратной совместимости.

Источники

  1. Protocol Buffers Documentation — Google Developers.
  2. Официальный репозиторий protobuf на GitHub (github.com/protocolbuffers/protobuf).
  3. Документация gRPC — grpc.io.
  4. Buf Documentation — buf.build.
  5. Книга «Designing Data-Intensive Applications» — Martin Kleppmann (глава о сериализации).