Подключение системных библиотек в CMake через pkg-config
Решил попробовать примитивно потыкаться в работу с векторной графикой.
Вроде бы все свой путь в программировании начинают с рисования квадратов и кругов, а я проскочил данный этап в угоду неясно чему слабым калькуляторам.
Все привычно – создал проект на cmake, собираюсь подключать следующие вещи: Cairo , CairoMM (обвязка для C++), SDL2.
И тут вдруг выясняется, что для этих библиотек не существует готовых модулей для find_package
😱.
Ну и что, не писать же их вручную, в самом же деле?
Готовые файлы FindCairo.cmake
были обнаружены в проектах Qtwebkit, poppler, но это значит выдергивать файлы из чужих проектов, лицензии, адаптация, фу.
Есть альтернативный ход – воспользоваться “пакетным менеджером” для C++, например, vcpkg. В его структуре есть рецепты для cairo и sdl2. Однако на простецкий проект тащить целый vcpkg не хочется – я уже установил библиотеки в систему, зачем мне дополнительный слой костылей?
И тут вспоминаю о том, что вообще-то есть способ запросить у системы список установленных библиотек, флаги для компиляции, пути к хэдерам и т.д.
Имя этому способу – pkg-config
.
Он позволяет выяснить вышеперечисленные параметры о библиотеках, которые предоставляют в своем дистрибутиве файл <package.pc>
.
Может его можно как-то использовать внутри CMake?
Можно!
И для этого даже не требуется самостоятельно писать функции с доступом к этой утилите.
Воспользуемся модулем FindPkgConfig
:
find_package(PkgConfig)
Нам имеет смысл воспользоваться одной из двух функций:
pkg_search_module
– проверяет существование модуля и использует первый найденный;pkg_check_module
– провеяет все совпадающие с запросом модулию
Воспользуемся этим знанием и поищем библиотеки CairoMM (какую есть) и SDL2 старше версии 2.0.1:
pkg_search_module(CAIRO REQUIRED cairomm-1.0)
pkg_search_module(SDL REQUIRED sdl2>=2.0.1)
И вуаля! Теперь эти библиотеки (при условии, что они установлены в систему, конечно) доступны под ожидаемыми переменными:
target_include_directories(test_exe PRIVATE ${CAIRO_INCLUDE_DIRS})
target_link_libraries(test_exe PRIVATE ${CAIRO_LIBRARIES})
target_include_directories(test_exe PRIVATE ${SDL_INCLUDE_DIRS})
target_link_libraries(test_exe PRIVATE ${SDL_LIBRARIES})
Победа! 🎉
Оказывается, что таким же образом подключается библиотека libmodbus
, с подключением которой ранее пришлось повозиться.
Жаль все правильные мысли сразу в голову не приходят.