Как создать проект C / C ++ на основе Buck

Buck - это инструмент быстрой сборки, разработанный Facebook. Есть много причин выбрать Бак, но с чего начать?

Это пошаговое руководство будет охватывать:

  • Как организовать свой проект
  • Интеграция Google Test
  • Объяснение основных команд Buck

TL;DR

Просмотрите файлы проекта на GitHub или клонируйте их в свою систему:

git clone [email protected]:njlr/buck-cpp-example.git

Установите существующие порты Buck из Buckaroo.pm.

Как работает бак

Прежде чем мы начнем, может быть полезно понять, как работает Buck. Вместо того, чтобы восстанавливать старую почву, взгляните на этот доклад разработчиков Buck.

Установка Buck

Официальное руководство по установке Buck доступно на их веб-сайте. Однако самый быстрый способ - это использовать Homebrew или Linuxbrew.

После того, как вы установили «варево», добавьте кран Facebook и установите Buck:

brew tap facebook/fb
brew install --HEAD facebook/fb/buck

Проверьте вашу установку с помощью:

buck --version

Организация ваших файлов

После установки Buck пора создать папки проекта. Buck упрощает поддержку любой структуры папок, которая вам нравится, но в этой демонстрации мы будем следовать соглашению C / C ++ о папках src и include.

Этот проект будет состоять из двух частей:

  • demo - исполняемый файл, который вычисляет 3 + 4и печатает результат
  • mathutils - библиотека, обеспечивающая простую функциональность добавления

Примечание: это простой пример для демонстрационных целей; Бак умеет создавать сложные проекты на C / C ++!

Сначала создайте следующую структуру где-нибудь на вашем диске:

.
├── .buckconfig
├── BUCK
└── demo
    ├── include
    └── src
        └── main.cpp

Используя командную строку:

touch .buckconfig
touch BUCK
mkdir demo
mkdir demo/include
mkdir demo/src
touch demo/src/main.cpp

Файлов довольно много - давайте пробежимся по ним:

  • Перед запуском любых команд Buck требуется .buckconfig. Он сообщает Buck, где находится корень вашего проекта, а также может использоваться для настройки любых параметров, которые являются глобальными для вашего проекта. А пока мы можем оставить его пустым.
  • В файле BUCK мы определим цель для нашего двоичного файла. В проекте Buck может быть несколько BUCK файлов, что полезно, когда вы хотите разделить логику сборки для различных аспектов вашего проекта, таких как библиотеки и тесты.
  • demo/include - это то место, куда мы будем помещать любые заголовки, используемые двоичным файлом.
  • demo/src - это то место, где мы будем размещать наши единицы перевода (в данном случае .cpp файлов) для двоичного файла.
  • demo/src/main.cpp будет точкой входа для нашего приложения.

main.cpp

Для начала напишем простую программу hello-world. Вставьте следующее в main.cpp:

БАК

Чтобы построить main.cpp файл, нам нужно написать для него цель Buck. В файл BUCK вставьте следующее:

BUCK файлы написаны на диалекте Python 2 с некоторыми расширениями. Когда вы вызываете buck build, Бак выполнит Python и запишет все определенные цели. После того, как список целей решен, каждая цель строится в соответствии со своим типом.

Вы можете увидеть полный список целевых типов в документации Buck, но наиболее важными для C / C ++ являются cxx_binary, cxx_library и prebuilt_cxx_library.

  • cxx_binary - набор модулей перевода и заголовков C / C ++, которые содержат точку входа (например, int main()). cxx_binary может быть выполнен после компиляции. Это не должно быть зависимости.
  • cxx_library - набор модулей трансляции C / C ++, которые могут использоваться другими целями. В отличие от cxx_binary, библиотека также определяет список exported_headers, которые представляют собой файлы заголовков, доступные для его зависимых элементов.
  • prebuilt_cxx_library - как cxx_library, но с необязательным объектным файлом вместо единиц перевода. Библиотеки только для заголовков реализованы как prebuilt_cxx_library без объектного файла.

Buck Команды

Теперь, когда файл BUCK на месте, Бак может построить цель. Выполните следующее:

buck build //:demo

Команда указывает Баку построить цель :demo, найденную в BUCK файле рядом с .buckconfig.

Бак использует простую систему адресации для целей, основанную на фактической структуре папок проекта. Например, //examples/basic/:demo относится к цели demo, определенной в examples/basic/BUCK.

После завершения сборки вы должны найти исполняемый файл в buck-out/gen/demo. Вы можете собрать и запустить это, используя:

buck build //:demo && ./buck-out/gen/demo

Или Бак может сделать это за вас:

buck run //:buck-cpp-example

Вы заметите, что второй запуск сборки выполняется очень быстро. Это потому, что Бак кэширует все, включая вывод скриптов Python!

Добавление зависимости

Давайте реализуем mathutils, чтобы мы могли использовать его в демонстрационном приложении.

Создайте в своем проекте следующую структуру папок:

.
└── mathutils
    ├── BUCK
    ├── include
    │   └── add.hpp
    └── src
        └── add.cpp

Используя командную строку:

mkdir mathutils
mkdir mathutils/include
mkdir mathutils/src
touch mathutils/BUCK
touch mathutils/include/add.hpp
touch mathutils/src/add.cpp

И сами файлы:

У этого BUCK файла есть несколько важных моментов:

  • header_namespace установлен на 'mathutils'. Это помещает каждый файл заголовка, который экспортирует библиотека, в папку с этим именем, что снижает вероятность конфликтов имен файлов с другими библиотеками.
  • Правила glob базируются на файле BUCK, поэтому src/**/*.cpp фактически соответствует mathutils/src/**/*.cpp из корня проекта.
  • Видимость установлена ​​на //..., чтобы цель могла быть принята как зависимость для всех других целей в проекте. На английском это означает, что «эта библиотека видна всем целям ниже корневого».

Использование функции добавления

Теперь мы можем использовать библиотеку mathutils в исполняемом файле demo.

Сначала объявите зависимость demo от mathutils. Измените файл BUCK в корне проекта на:

Теперь обновите main.cpp до:

Используйте Buck, чтобы запустить demo, чтобы увидеть результат. Вы заметите, что Бак знает, как связать mathutils за вас.

Google Test

Наше приложение работает, но для усердия стоит добавить несколько юнит-тестов!

Buck поддерживает все среды тестирования C / C ++ через buck run, но обеспечивает дополнительную интеграцию с Google Test.

Получение исходного кода Google Test

Git предоставляет простой способ получить исходный код Google Test с помощью подмодулей. Мы будем использовать вилку, содержащую BUCK файл, но вы можете использовать мастер и при желании написать свой собственный.

git submodule add [email protected]:njlr/googletest.git
cd googletest/
git checkout 48072820e47a607d000b101c05d796ebf9c4aad2
cd ../

Теперь нам нужно сообщить Баку, где найти исходные коды Google Test. Откройте .buckconfig и добавьте следующее:

Это сообщает Buck, где найти цель Google Test, которую он может использовать для ваших тестов. Есть и другие свойства конфигурации, которые можно установить; загляните в Документы Buck.

Написание теста

Мы поместим тесты в mathutils/test, рядом сmathutils/src и mathutils/include:

.
└── mathutils
    ├── BUCK
    ├── include
    │   └── add.hpp
    ├── src
    │   └── add.cpp
    └── test
        ├── BUCK
        └── add.cpp

Используя командную строку:

mkdir mathutils/test
touch mathutils/test/add.cpp

И сам тест:

Наконец, нам нужно объявить тест в файле BUCK:

Теперь тесты можно запускать с помощью Buck:

buck test //mathutils/test:add

Или, чтобы запустить все тесты:

buck test

Вывод

И это все! Buck - это мощный инструмент, который сэкономит вам часы ожидания в течение цикла разработки проекта. Чтобы узнать больше, прочтите документацию или посмотрите некоторые из презентаций Buck.

Если есть библиотека, которую нужно перенести на Buck, загляните на Buckaroo.pm. Мы уже портировали 300 проектов и работаем над еще большим!

Хакерский полдень - это то, с чего хакеры начинают свои дни. Мы часть семьи @AMI. Сейчас мы принимаем заявки и рады обсуждать рекламные и спонсорские возможности.

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