Ninja linux что это

Обновлено: 06.07.2024

Ninja — ещё одна система сборки. Она анализирует зависимости между входными и выходными файлами (обычно это исходный код и исполняемые файлы, соответственно) и запускает сборку.

Задача Ninja — быть быстрой. Она создана исходя из потребностей браузера Chromium, состоящего из более 30,000 исходных файлов. Другим системам сборки требуется около 10 секунд для анализа зависимостей и запуска сборки, тогда как Ninja требуется меньше секунды.

Другие пакеты, относящиеся к ninja-build

  • зависимости
  • рекомендации
  • предложения
  • enhances
  • dep: libc6 (>= 2.15) [amd64, mips64el, ppc64, s390x, sparc64] библиотека GNU C: динамически подключаемые библиотеки
    также виртуальный пакет, предоставляемый libc6-udeb dep: libc6 (>= 2.16) [x32] dep: libc6 (>= 2.17) [arm64, ppc64el] dep: libc6 (>= 2.27) [riscv64] dep: libc6 (>= 2.28) [armel, armhf, hppa, i386, m68k, mipsel] dep: libc6 (>= 2.31) [sh4]
  • dep: libc6.1 (>= 2.15) [alpha] библиотека GNU C: динамически подключаемые библиотеки
    также виртуальный пакет, предоставляемый libc6.1-udeb dep: libc6.1 (>= 2.31) [ia64]
  • dep: libgcc-s1 (>= 3.5) [armel, armhf] вспомогательная библиотека GCC dep: libgcc-s1 (>= 4.2) [i386, ia64, mipsel, sh4]
  • dep: libgcc-s2 (>= 4.2.1) [m68k] вспомогательная библиотека GCC
  • dep: libgcc-s4 (>= 4.1.1) [hppa] вспомогательная библиотека GCC
  • dep: libstdc++6 (>= 5.2) стандартная библиотека GNU C++ версии 3
  • sug: python3 интерактивный высокоуровневый объектно-ориентированный язык (версия python3 по умолчанию)

Загрузка ninja-build

Загрузить для всех доступных архитектур
Архитектура Размер пакета В установленном виде Файлы
alpha (неофициальный перенос) 111,7 Кб391,0 Кб [список файлов]
amd64 109,6 Кб347,0 Кб [список файлов]
arm64 104,3 Кб335,0 Кб [список файлов]
armel 95,5 Кб310,0 Кб [список файлов]
armhf 97,1 Кб250,0 Кб [список файлов]
hppa (неофициальный перенос) 105,9 Кб327,0 Кб [список файлов]
i386 122,8 Кб385,0 Кб [список файлов]
ia64 (неофициальный перенос) 134,9 Кб586,0 Кб [список файлов]
m68k (неофициальный перенос) 87,8 Кб293,0 Кб [список файлов]
mips64el 102,8 Кб366,0 Кб [список файлов]
mipsel 103,4 Кб363,0 Кб [список файлов]
ppc64 (неофициальный перенос) 118,1 Кб433,0 Кб [список файлов]
ppc64el 118,5 Кб431,0 Кб [список файлов]
riscv64 (неофициальный перенос) 100,2 Кб263,0 Кб [список файлов]
s390x 102,0 Кб359,0 Кб [список файлов]
sh4 (неофициальный перенос) 107,1 Кб273,0 Кб [список файлов]
sparc64 (неофициальный перенос) 92,3 Кб322,0 Кб [список файлов]
x32 (неофициальный перенос) 108,7 Кб330,0 Кб [список файлов]

Эта страница также доступна на следующих языках (Как установить язык по умолчанию):

Авторские права © 1997 - 2021 SPI Inc.; См. условия лицензии. Debian это торговый знак компании SPI Inc. Об этом сайте.


Привет, Хабр!

Недавно я задумался, ковыряя очередную бесплатную систему сборки, «А нельзя ли взять и самому написать такую систему? Ведь это просто — взять ту же Ninja, прикрутить разделение на препроцессинг и компиляцию, да и передавать по сети файлы туда-сюда. Куда уж проще?»

Просто — не просто, как самому сделать подобную систему — расскажу под катом.

Этап 0. Формулировка задачи

Disclaimer: Статья отмечена как tutorial, но это не совсем пошаговое руководство, скопипастив код из которого получится готовый продукт. Это скорее инструкция — как спланировать и куда копать.

Сперва определимся, какой общий алгоритм работы должен получиться:

  1. Прототип 1. Программа имитирует компилятор, разделяя команду на 2, и самостоятельно вызывая компилятор.
  2. Прототип 2. К этому добавим пересылку команды на компиляцию по сети, без самого файла.
  3. Прототип 3. Пройдемся по графу сборки Ninja, выводя потенциально разбиваемые команды.

Этап 1. Разбиваем командную строку

Для прототипа остановимся на компиляторе GCC (или Clang, нет большой разницы), т.к. его командную строку проще разбирать.

Пусть у нас программа вызывается через команду «test -c hello.cpp -o hello.o». Будем считать, что после ключа "-c" (компиляция в объектный код) всегда идет имя входного файла, хоть это и не так. Так же пока остановимся только на работе в локальной директории.

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

Что ж, теперь у нас есть маленький эмулятор компилятора, который дергает настоящий компилятор. Едем дальше :)

Дальнейшее развитие прототипа:

  • Учитывать и абсолютные имена файлов;
  • Использовать одну из библиотек для работы с процессами: Boost.Process, QProcess, или Ninja Subprocess;
  • Реализовать поддержку разделения команд для MSVC;
  • Сделать API для выполнения команд асинхронным, а выполнение вынести в отдельный поток.

Этап 2. Сетевая подсистема

Прототип сетевого обмена сделаем на BSD Sockets (Сокеты Беркли)

Сокет это дословно «дырка», в которую можно писать данные и считывать из неё. Чтобы подключиться к удаленному серверу, алгоритм следующий:

  • Создать сокет нужного типа (TCP) с помощью функции socket();
  • После создания, выставить нужные флаги, например неблокирующий режим с помощью setsockopt();
  • Получить адрес в нужном формате для BSD сокетов с помощью getaddrinfo();
  • Подключиться к TCP-хосту с помощью функции connect(), передав туда подготовленный адрес;
  • Вызывать функции read/send для чтения и записи;
  • После окончания работы — вызвать close().


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

Допустим, сокет у нас готов, как будет примерно выглядеть клиент и сервер компилятора?


Да, не все исходники показаны, например TcpConnectionParams или ByteArrayHolder, но это достаточно примитивные структуры.

После отладки этого прототипа, у нас есть небольшой сервис, который может локально компилировать препроцессированные файлы (при некоторых допущениях, например, что рабочая директория клиента и сервера совпадают).

Дальнейшее развитие прототипа:

Этап 3. Интеграция с Ninja

Для начала, необходимо ознакомиться с принципами работы Ninja. Предполагается, что вы уже собирали с её помощью какие-либо проекты и примерно представляете, как выглядит build.ninja.
Используемые понятия:


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

Как мы видим, для того, чтобы внести свои изменения в систему сборки, нам нужно переписать State, разбив Edges на два в нужных местах и добавив новые узлы (препроцессированные файлы).
Предположим, у нас уже есть исходники ninja, мы их собираем, и все в собранном виде работает.
Добавим в ninja.cc следующий фрагмент кода:


Саму функцию RewriteStateRules можно унести в отдельный файл, либо объявить здесь же, в ninja.cc как:


Некоторые нудные фрагменты вырезаны, полный код можно посмотреть здесь.

  • Скорее всего, первый вариант InvocationRewriter не заработает, нужно будет учитывать много вещей — например, то что аргумент компиляции "-c" может быть задан " -c ", ну и я уже молчу про то что он не обязательно предваряет исходный файл.
  • Может быть много дополнительных флагов, которые отмечают какие-то файлы, так что не всё то, что «не флаг» — это файл.
  • После создания разделённого графа, если он успешно собирается в две фазы «препроцессинг и компиляция» — нужно будет проинтегрировать удаленное выполнение по сети с нашим сетевым слоем. Собственно цикл сборки в Ninja находится в build.cc в функции Builder::Build. В нее можно добавить по аналогии с
    «if (failures_allowed && command_runner_->CanRunMore())» и «if (pending_commands)» свои этапы для распределённой сборки.

Этап X. Что дальше?

После успешного создания прототипа, нужно двигаться маленькими шажками к созданию продукта:

  • Конфигурирование всех модулей — как сетевой подсистемы, так и InvocationRewriter-а;
  • Поддержка любых комбинаций опций под разными компиляторами;
  • Поддержка сжатия при передаче файлов;
  • Разнообразная диагностика в виде логов;
  • Написание координатора, который сможет обслуживать подключение к нескольким серверам сборки;
  • Написание балансировщика, который будет учитывать то, что серверами пользуется сразу несколько клиентов (и не перегружать их сверх меры);
  • Написать интеграцию с другими системами сборки, не только Ninja.

Что умеет Wuild:

  • Распределённая сборка с возможностью кросс-компиляции (Clang) под Win, Mac, Linux;
  • Интеграция с Ninja и Make.

Статья носит скорее образовательный характер, а проект — предостерегательный (как делать не надо, в смысле NIH-синдрома — делайте меньше велосипедов).

Кто хочет — форкайте, делайте пулл-реквесты, используйте в любых страшных целях!


Привет, Хабр!

Недавно я задумался, ковыряя очередную бесплатную систему сборки, «А нельзя ли взять и самому написать такую систему? Ведь это просто — взять ту же Ninja, прикрутить разделение на препроцессинг и компиляцию, да и передавать по сети файлы туда-сюда. Куда уж проще?»

Просто — не просто, как самому сделать подобную систему — расскажу под катом.

Этап 0. Формулировка задачи

Disclaimer: Статья отмечена как tutorial, но это не совсем пошаговое руководство, скопипастив код из которого получится готовый продукт. Это скорее инструкция — как спланировать и куда копать.

Сперва определимся, какой общий алгоритм работы должен получиться:

  1. Прототип 1. Программа имитирует компилятор, разделяя команду на 2, и самостоятельно вызывая компилятор.
  2. Прототип 2. К этому добавим пересылку команды на компиляцию по сети, без самого файла.
  3. Прототип 3. Пройдемся по графу сборки Ninja, выводя потенциально разбиваемые команды.

Этап 1. Разбиваем командную строку

Для прототипа остановимся на компиляторе GCC (или Clang, нет большой разницы), т.к. его командную строку проще разбирать.

Пусть у нас программа вызывается через команду «test -c hello.cpp -o hello.o». Будем считать, что после ключа "-c" (компиляция в объектный код) всегда идет имя входного файла, хоть это и не так. Так же пока остановимся только на работе в локальной директории.

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

Что ж, теперь у нас есть маленький эмулятор компилятора, который дергает настоящий компилятор. Едем дальше :)

Дальнейшее развитие прототипа:

  • Учитывать и абсолютные имена файлов;
  • Использовать одну из библиотек для работы с процессами: Boost.Process, QProcess, или Ninja Subprocess;
  • Реализовать поддержку разделения команд для MSVC;
  • Сделать API для выполнения команд асинхронным, а выполнение вынести в отдельный поток.

Этап 2. Сетевая подсистема

Прототип сетевого обмена сделаем на BSD Sockets (Сокеты Беркли)

Сокет это дословно «дырка», в которую можно писать данные и считывать из неё. Чтобы подключиться к удаленному серверу, алгоритм следующий:

  • Создать сокет нужного типа (TCP) с помощью функции socket();
  • После создания, выставить нужные флаги, например неблокирующий режим с помощью setsockopt();
  • Получить адрес в нужном формате для BSD сокетов с помощью getaddrinfo();
  • Подключиться к TCP-хосту с помощью функции connect(), передав туда подготовленный адрес;
  • Вызывать функции read/send для чтения и записи;
  • После окончания работы — вызвать close().


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

Допустим, сокет у нас готов, как будет примерно выглядеть клиент и сервер компилятора?


Да, не все исходники показаны, например TcpConnectionParams или ByteArrayHolder, но это достаточно примитивные структуры.

После отладки этого прототипа, у нас есть небольшой сервис, который может локально компилировать препроцессированные файлы (при некоторых допущениях, например, что рабочая директория клиента и сервера совпадают).

Дальнейшее развитие прототипа:

Этап 3. Интеграция с Ninja

Для начала, необходимо ознакомиться с принципами работы Ninja. Предполагается, что вы уже собирали с её помощью какие-либо проекты и примерно представляете, как выглядит build.ninja.
Используемые понятия:


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

Как мы видим, для того, чтобы внести свои изменения в систему сборки, нам нужно переписать State, разбив Edges на два в нужных местах и добавив новые узлы (препроцессированные файлы).
Предположим, у нас уже есть исходники ninja, мы их собираем, и все в собранном виде работает.
Добавим в ninja.cc следующий фрагмент кода:


Саму функцию RewriteStateRules можно унести в отдельный файл, либо объявить здесь же, в ninja.cc как:


Некоторые нудные фрагменты вырезаны, полный код можно посмотреть здесь.

  • Скорее всего, первый вариант InvocationRewriter не заработает, нужно будет учитывать много вещей — например, то что аргумент компиляции "-c" может быть задан " -c ", ну и я уже молчу про то что он не обязательно предваряет исходный файл.
  • Может быть много дополнительных флагов, которые отмечают какие-то файлы, так что не всё то, что «не флаг» — это файл.
  • После создания разделённого графа, если он успешно собирается в две фазы «препроцессинг и компиляция» — нужно будет проинтегрировать удаленное выполнение по сети с нашим сетевым слоем. Собственно цикл сборки в Ninja находится в build.cc в функции Builder::Build. В нее можно добавить по аналогии с
    «if (failures_allowed && command_runner_->CanRunMore())» и «if (pending_commands)» свои этапы для распределённой сборки.

Этап X. Что дальше?

После успешного создания прототипа, нужно двигаться маленькими шажками к созданию продукта:

  • Конфигурирование всех модулей — как сетевой подсистемы, так и InvocationRewriter-а;
  • Поддержка любых комбинаций опций под разными компиляторами;
  • Поддержка сжатия при передаче файлов;
  • Разнообразная диагностика в виде логов;
  • Написание координатора, который сможет обслуживать подключение к нескольким серверам сборки;
  • Написание балансировщика, который будет учитывать то, что серверами пользуется сразу несколько клиентов (и не перегружать их сверх меры);
  • Написать интеграцию с другими системами сборки, не только Ninja.

Что умеет Wuild:

  • Распределённая сборка с возможностью кросс-компиляции (Clang) под Win, Mac, Linux;
  • Интеграция с Ninja и Make.

Статья носит скорее образовательный характер, а проект — предостерегательный (как делать не надо, в смысле NIH-синдрома — делайте меньше велосипедов).

Кто хочет — форкайте, делайте пулл-реквесты, используйте в любых страшных целях!

Сегодня я хотел начать рассказ об одном интересном продукте представляемой мной на хабре компании Tibbo. Продукт этот может оказаться полезен широкому кругу IT-профессионалов, включая системных администраторов, специалистов по информационной безопасности, и, наконец, простых разработчиков, которым нет-нет, да и приходится программировать общение с устройствами и другой низкоуровневый ввод/вывод.

Разговор пойдёт про программируемый терминал/сниффер IO Ninja (здесь и далее я буду опускать слово «эмулятор» и говорить просто «терминал»). Подозреваю, что само определение «терминал/сниффер» может выглядеть достаточно непривычно, если не сказать странно. Поэтому начнём с истории возникновения IO Ninja.

ioninja

Самым первым продуктом нашей компании был встраиваемый модуль (embedded module) EM100 для преобразования последовательного интерфейса Serial RS232 в Ethernet 10BASE-T (сейчас его аналогом являются модуль EM1206).

ioninja

На этом устройстве были опробованы и обкатаны протоколы взаимодействия между прошивкой (на модулях) и драйверами виртуальных портов, а также конфигурационными утилитами (на PC).

  • Serial терминал;
  • TCP терминал;
  • UDP терминал;
  • Serial монитор;
  • Ethernet сниффер.
  • Слушать и принимать входящие TCP соединения;
  • Отправлять широковещательные (broadcast) UDP пакеты;
  • Принимать ответы на них со множественных узлов;
  • Отправлять и уметь отображать в шестнадцатеричном виде бинарные данные.

Именно после безуспешного поиска и родилась идея создать универсальную утилиту для отладки коммуникационных протоколов, которая умела бы делать всё вышеперечисленное и делала бы это хорошо. Да ещё – мечтать так мечтать! – была бы программируемой и позволяла с лёгкостью дописывать анализаторы наших собственных протоколов и тестовые скрипты (такие как, например, ждать команды и отправлять динамически генерируемые по определённым правилам ответы на них).

Мечты о программируемости, конечно, длительное время оставались просто мечтами. А вот утилитка для посылки и отображения бинарных данных, при этом с поддержкой приёма TCP соединений и широковещательной UDP рассылки была сляпана достаточно быстро. Называлась она бесхитростно – SockTerm – и выглядела вот так:

sockterm

Помимо поддержки отсутствующих в стандартных терминалах режимов работы с сокетами, данная утилита продемонстрировала чрезвычайное удобство реализованного в ней подхода к логгированию, а именно шестнадцатеричной «простыни» с приклеиванием новых пакетов к предыдущим.

Работа над утилитой продолжалась в свободное от основных проектов и задач время в течение пары лет. Модуль логгирования был постепенно доработан, расширен и в итоге реорганизован в виде полноценного движка (о его возможностях будет более подробно рассказано далее). Данный движок был вполне пригоден для использования как в терминалах, так и в снифферах – что и было с энтузиазмом воплощено в жизнь. Результатом стало появление первой версии IO Ninja.

ioninja-1.8.6

Эта утилита позволяла работать со всеми интересующими нас транспортами (Serial, TCP, UDP) как в режиме сниффера для пассивного прослушивания, так и в режиме терминала для направленной передачи и приёма данных. Множественные режимы работы были реализованы в виде плагинов (написанных, как и сама IO Ninja, на С++), что в теории позволяло нам с достаточной лёгкостью допиливать поддержку новых режимов, а в перспективе вообще опубликовать SDK и дать клиентам возможность делать это самим. Однако на практике последнее так и не было воплощено – нам не давали покоя те самые мечты о программируемости, а плагины на C++ – в данном случае не самая лучшая архитектура.

Что нам нужно было вместо этого, так это сделать ниндзю скриптованной. Но вот незадача – в языках без указателей и адресной арифметики работа с бинарными данными (а это неотъемлемая часть любого анализатора протоколов) превращается в кошмар типа «вытащить байт по индексу N, сдвинуть на 8 бит влево, сложить с байтом по индексу N + 1 и т.д.». А скриптовых языков с указателями в природе не существует. Точнее, не существовало раньше – мы исправили это досадное недоразумение, создав язык Jancy.

ioninja-2.3.5

При этом данный язык спроектирован настолько бинарно совместимым с C/C++, что возможен прямой вызов между Jancy и С++, а это приводит, во-первых, к высокой эффективность взаимодействия между скриптом и хостовым C++ приложением, а во-вторых, к лёгкости создания на C/C++ библиотек для использования из Jancy-скриптов. Помимо ABI (бинарной) совместимости, Jancy также обладает высокой степенью совместимости на уровне исходных кодов, что позволяет копировать и использовать (зачастую вообще без каких-либо модификаций) код на языке C, взятый из общедоступных источников.

В 2014 году была закончена работа над созданием и выпуском третьей версии IO Ninja, основанной на языке Jancy. О ней и пойдёт речь далее.

  • Программируемость;
  • Движок логгирования;
  • Строитель пакетов;
  • Универсальный редиректор;
  • Объединение всех видов утилит для отладки коммуникаций в одном продукте.

Движок логгирования ещё со времён непрограммируемой первой версии IO Ninja предлагал то, что не было доступно в других терминалах и снифферах. Выделяется этот движок прежде всего самим подходом к отображению данных лога.

log

При этом, несмотря на фактическую неограниченность размера лога (реально он ограничен лишь свободным пространством на диске), движок IO Ninja предоставляет «гладкую» прокрутку, при этом без прямой зависимости объёма потребляемой памяти от размера лога.

Одной из причин ухода от стандартных терминалов было отсутствие удобных средств для работы с бинарными данными, поэтому совсем неудивительно, что логгирующий движок IO Ninja буквально «заточен» под эту задачу.

log settings

Бинарные данные можно отображать в шестнадцатеричном или текстовом виде, с настраиваемой шириной строки и табуляции и в любой из UTF-кодировок (включая вариации с обратным порядком следования байтов). Пакеты одного типа (например, входящие) опционально склеиваются друг с другом. Склеивание можно сконфигурировать на «всегда», «никогда» и «если интервал не превышает некий порог». Места склеивания подсвечиваются (опять-таки, опционально) цветом – шашечками.

Лог IO Ninja также поддерживает схлопывание/разворачивание записей, что может быть необходимо для переключения между кратким и полным описанием и используется, например, в сетевом сниффере:

log

Говоря о поддержке работы с бинарными данными, нельзя не упомянуть о средствах IO Ninja для подготовки исходящих пакетов.

packet template editor

Строитель пакетов является одной из сильнейших сторон IO Ninja, доступных «из коробки». Помимо современного шестнадцатеричного редактора с поддержкой всех UTF-кодировок, редактирования нибблов (полубайтов), ограничений на размер пакета сверху и снизу, удобной подсветкой выделения, а также всех других возможностей, которые можно ожидать от хорошего редактора (insert, overwrite, copy, paste, undo, redo) – в IO Ninja присутствует инструмент для создания пакетов по шаблону.

Помните, мы говорили про высокую степень совместимости между Jancy и C? Подготовка бинарных пакетов – это одно из мест, где пожинаются плоды этой совместимости.

Фаза 1: найти исходники реализации нужного нам протокола на C в общедоступных источниках;

Фаза 2: скопировать описания структур пакетов в IO Ninja и, возможно, чуть-чуть подретушировать (в конце концов, Jancy и C это разные языки);

Фаза 4: ПРОФИТ! Можно заполнять поля пакета из редактора свойств (property grid)!

packet template editor

На этом закончим вводный обзор, а в следующей части статьи продемонстрируем несколько реальных сценариев из жизни нашей компании, в которых IO Ninja помогал решать определённые практические задачи лучше аналогов.

Читайте также: