oneTBB: интеграция и сборка через CMake
oneAPI Threading Building Blocks (oneTBB) — популярная библиотека для параллельного программирования на C++ с открытым исходным кодом, опубликована на GitHub. Пару лет назад команда разработки решилась на глобальный рефакторинг библиотеки (проект TBB revamp), в который удалось вписать долгожданную смену системы сборки с GNU Makefiles на CMake. Свежая версия вышла в релиз в рамках инициативы oneAPI, обновив имя на oneTBB. В этой статье я расскажу про то, как подключить oneTBB в CMake-проект и как собрать, протестировать и установить oneTBB.
Как подключить oneTBB в свой CMake-проект
Эта часть может быть полезна тем, кто хочет использовать библиотеку oneTBB в своём проекте.
Существует два основных способа подключения стороннего проекта: как готовый пакет и как исходный код.
Способ 1. Подключение готового пакета oneTBB
Для подключения пакета нужна функция find_package(TBB <...>)
. Такой способ работает для тех пакетов oneTBB, в которых есть соответствующая поддержка — TBBConfig-файлы. Официальные oneAPI пакеты распространяются с такой поддержкой из коробки. Архивы, прикреплённые к релизам oneTBB на GitHub, тоже поддерживают такой способ, но нужно дать CMake’у знать, куда распакован пакет, через переменную CMAKE_PREFIX_PATH
. Некоторые сторонние дистрибутивы oneTBB также поддерживают этот способ. На самом деле, поддержка TBBConfig-файлов появилась задолго до релиза oneTBB, это произошло в одном из обновлений TBB 2017. Реализация в oneTBB во многом совместима с реализацией из предыдущих версий.
После успешного вызова find_package(TBB <...>)
в проекте станут доступны импортированные таргеты TBB::tbb
, TBB::tbbmalloc
и т.д. в зависимости от запрошенных и доступных компонентов. Эти таргеты можно подключить к своему таргету — target_link_libraries(my_app PRIVATE TBB::tbb)
. Несмотря на «link» в названии функции, она добавит зависимость не только на стадию линковки, но и на стадию компиляции (путь до заголовочных файлов oneTBB подставится в строку компиляции).
Код
# Создаём приложение
add_executable(my_app)
target_sources(my_app PRIVATE my_app.cpp)
# Ищем готовый пакет oneTBB 2021.5.0 (или новее)
find_package(TBB 2021.5.0 REQUIRED)
# Подключаем импортированный таргет TBB::tbb к приложению
target_link_libraries(my_app PRIVATE TBB::tbb)
Детальнее посмотреть и попробовать этот способ можно на примере, в котором:
my_app.cpp — исходник приложения, вызывающего
TBB_runtime_version()
и печатающего результат в консоль;CMakeLists.txt — CMake-конфигурация для сборки приложения, где и показан способ подключения oneTBB;
run.sh — скрипт для запуска примера на линуксе;
README.md — небольшое описание примера.
В этом примере используется готовый пакет со страницы oneTBB/releases, который ставится в текущую папку. Такая CMake-конфигурация будет работать и в случае установки oneTBB из многих других источников.
Во время сборки можно заметить, как подключается библиотека:
на этапе компиляции подключаются заголовочные файлы:
-isystem <onetbb-root>/include
на этапе линковки проставляется
rpath
и подключается библиотека:-Wl,-rpath,<onetbb-root>/lib/intel64/gcc4.8 <onetbb-root>/lib/intel64/gcc4.8/libtbb.so.12
Так как путь до библиотеки уже есть в rpath
, для запуска не нужно выставлять какие-то дополнительные переменные окружения. С помощью ldd
можно проверить, что oneTBB «виден»:
> ldd ./build/my_app | grep tbb
libtbb.so.12 => <onetbb-root>/lib/intel64/gcc4.8/libtbb.so.12 (0x00007f867622c000)
Способ 2. Подключение oneTBB в виде исходного кода
Если подходящего пакета нет или требуется сборка с особыми параметрами, то можно использовать исходный код oneTBB, собирая его вместе с проектом.
До вызова функции, подключающей oneTBB, можно дополнительно настроить конфигурацию с помощью переменных, которые описаны в начале oneTBB/cmake/README.md (TBB_STRICT
, TBB_TEST
и т.д.), общие переменные CMAKE_BUILD_TYPE
, CMAKE_CXX_STANDARD
и другие также будут учитываться при построении oneTBB.
В самом простом варианте можно скачать исходники библиотеки в папку с проектом и добавить в CMakeLists.txt
команду add_subdirectory(<onetbb-sources-dir>)
. Дальше можно использовать таргеты из oneTBB проекта и подключать их к своим таргетам, как в способе 1 — target_link_libraries(my_app PRIVATE TBB::tbb)
.
Код
# Создаём приложение
add_executable(my_app)
target_sources(my_app PRIVATE my_app.cpp)
# Настраиваем конфигурацию oneTBB - явно отключаем тесты
option(TBB_TEST OFF)
# Подключаем в проект подпапку с исходниками oneTBB,
# которая должна быть предварительно скачана в проект
add_subdirectory(oneTBB)
# Подключаем таргет TBB::tbb к приложению
target_link_libraries(my_app PRIVATE TBB::tbb)
Вместо add_subdirectory
можно использовать функции FetchContent_Declare
и FetchContent_MakeAvailable
из модуля FetchContent, что позволит автоматически скачивать исходники oneTBB, например с GitHub.
Код
# Создаём таргет приложения
add_executable(my_app)
target_sources(my_app PRIVATE my_app.cpp)
# Загружаем исходники oneTBB 2021.5.0 с GitHub на этапе конфигурации
include(FetchContent)
FetchContent_Declare(
onetbb
GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git
GIT_TAG v2021.5.0
)
# Настраиваем конфигурацию oneTBB - явно отключаем тесты
option(TBB_TEST OFF)
# Делаем исходники oneTBB доступными в текущем проекте
# (аналогично add_subdirectory)
FetchContent_MakeAvailable(onetbb)
# Подключаем таргет TBB::tbb к приложению
target_link_libraries(my_app PRIVATE TBB::tbb)
Детальнее посмотреть и попробовать этот способ можно на примере, в котором:
my_app.cpp — исходник приложения, вызывающего
TBB_runtime_version()
и печатающего результат в консоль;CMakeLists.txt — CMake-конфигурация для сборки приложения, где и показан способ подключения oneTBB с помощью модуля
FetchContent
;run.sh — скрипт для запуска примера на линуксе;
README.md — небольшое описание примера.
При построении явно используется таргет my_app
, который через зависимость вызывает построение таргета TBB::tbb
. Если не использовать никакого таргета или использовать таргет all
, то построятся все таргеты из проекта oneTBB, попавшие в all
, а не только те, на которые есть зависимость.
Как сконфигурировать, построить и протестировать oneTBB
Эта часть может быть полезна тем, кто хочет самостоятельно собирать oneTBB, делать какие-то доработки и предлагать изменения в библиотеку.
Подробное и актуальное описание системы сборки можете найти в oneTBB/cmake/README.md. Ниже кратко опишу основные шаги.
Конфигурация
Конфигурируется проект типично — командой cmake
. Настроить конфигурацию можно как общими переменными (CMAKE_BUILD_TYPE
, CMAKE_CXX_STANDARD
и т.д.), так и проектными (TBB_STRICT
, TBB_TEST
и т.д.).
Построение
Строится проект также типично: например, командой cmake --build
. Проект включает в себя несколько компонентов, для каждого из которых есть таргет, если компонент поддерживается на системе и не отключен при конфигурации: tbb
, tbbmalloc
, tbbmalloc_proxy
, разные варианты tbbbind
. Каждый из этих таргетов строится в динамическую библиотеку. Статическую версию тоже можно построить (BUILD_SHARED_LIBS), но разработчики oneTBB не рекомендуют и официально не поддерживают такой вариант.
В проект входят Python-bindings (таргет python_build
), которые включаются опцией TBB4PY_BUILD
и собираются через Setuptools под капотом. Для сборки нужен Python 3.5+ и SWIG.
Если тесты не отключены через TBB_TEST=OFF
, то для каждого из них создаётся таргет, который можно построить отдельно.
Тестирование
При включенной опции TBB_TEST
в проект включаются тесты. Набор тестов зависит от включенных компонентов и от платформы. Тесты будут включать дополнительные сценарии, если в системе установлен Intel® Software Development Emulator. Построенные тесты можно запустить с помощью утилиты ctest
.
Установка
Подробная инструкция установки из исходников с примерами описана в oneTBB/INSTALL.md.
Для установки можно использовать таргет install
, либо напрямую вызывать cmake_install.cmake
скрипт, с помощью которого можно установить конкретный компонент:runtime
, devel
или tbb4py
.
Настроить путь установки можно на этапе конфигурации проекта через переменную CMAKE_INSTALL_PREFIX
. По умолчанию установится в /usr/local
на Unix и в C:\Program Files\TBB
на Windows.
Кроме того, в проекте реализована простая zip конфигурация для упаковщика CPack. После конфигурации и сборки проекта можно сделать oneTBB пакет в виде zip-архива. В распакованном виде такой пакет можно подключать к проектам, как описано выше в способе 1.
Более подробную и актуальную информацию о системе сборки (и не только) можно найти в репозитории oneTBB на GitHub. Проект активный, поэтому баг-репорты, фича-реквесты или просто вопросы приветствуются через Issues, а свой вклад можно внести через Pull Request.