Каков правильный способ использования `pkg-config` из` cmake`?
Оглядываясь в сети, я видел много такого кода:
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS}
target_link_libraries(app ${SDL2_LIBRARIES})
Однако это кажется неправильным способом, поскольку он использует только каталоги и библиотеки include, но игнорирует определения, пути к библиотекам и другие флаги, которые могут быть возвращены pkg-config
.
Как правильно сделать это и убедиться, что все флаги компиляции и ссылки, возвращаемые pkg-config
, используются скомпилированным app
? И есть ли одна команда для этого, то есть что-то вроде target_use(app SDL2)
?
ссылка:
Ответы
Ответ 1
Другие методы, показанные ниже, не могут настроить пути компоновщика для тех общих библиотек, которые не находятся в типичных установленных местах (например,/usr/lib). В результате возникла ошибка компоновщика /usr/bin/ld: cannot find -llibrary-1.0
. В моем случае файлы pkg-config также не были установлены, а пути pkg-config для проекта были добавлены с помощью переменной среды PKG_CONFIG_PATH. Это развернутая версия рабочего CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(ya-project C)
find_package(PkgConfig REQUIRED)
pkg_check_modules(MY_PKG REQUIRED IMPORTED_TARGET any-package)
pkg_check_modules(YOUR_PKG REQUIRED IMPORTED_TARGET ya-package)
add_executable(program-name file.c ya.c)
target_link_libraries(program-name
PkgConfig::MY_PKG
PkgConfig::YOUR_PKG)
Ответ 2
Во-первых, звонок:
include(FindPkgConfig)
следует заменить на:
find_package(PkgConfig)
Вызов find_package()
является более гибким и позволяет использовать такие опции, как REQUIRED
, которые автоматически выполняют действия, которые нужно было бы делать вручную с include()
.
Во-вторых, следует избегать ручного вызова pkg-config
, когда это возможно. CMake поставляется с богатым набором определений пакетов, которые можно найти в Linux под /usr/share/cmake-3.0/Modules/Find*cmake
. Они предоставляют больше возможностей и выбора для пользователя, чем необработанный вызов pkg_search_module()
.
Что касается упомянутой гипотетической команды target_use()
, CMake уже имеет такую встроенную функцию с помощью PUBLIC | PRIVATE | INTERFACE. Такой вызов, как target_include_directories(mytarget PUBLIC ...)
, приведет к тому, что включаемые каталоги будут автоматически использоваться в каждой цели, которая использует mytarget
, например, target_link_libraries(myapp mytarget)
. Однако этот механизм, по-видимому, предназначен только для библиотек, созданных в файле CMakeLists.txt
, и не работает для библиотек, приобретенных с помощью pkg_search_module()
. Для этого можно использовать вызов add_library(bar SHARED IMPORTED)
, но я еще не рассматривал это.
Что касается основного вопроса, то здесь это работает в большинстве случаев:
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
...
target_link_libraries(testapp ${SDL2_LIBRARIES})
target_include_directories(testapp PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(testapp PUBLIC ${SDL2_CFLAGS_OTHER})
SDL2_CFLAGS_OTHER
содержит определения и другие флаги, необходимые для успешной компиляции. Флаги SDL2_LIBRARY_DIRS
и SDL2_LDFLAGS_OTHER
, тем не менее, по-прежнему игнорируются, не зная, как часто это станет проблемой.
Больше документации здесь http://www.cmake.org/cmake/help/v3.0/module/FindPkgConfig.html
Ответ 3
Редко, что нужно было бы связать только с SDL2. В популярном в настоящее время ответе используется pkg_search_module()
, который проверяет данные модули и использует первый рабочий.
Скорее всего, вы хотите установить связь с SDL2 и SDL2_Mixer и SDL2_TTF и т.д. pkg_check_modules()
проверяет все данные модули.
# sdl2 linking variables
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_ttf SDL2_mixer SDL2_image)
# your app
file(GLOB SRC "my_app/*.c")
add_executable(my_app ${SRC})
target_link_libraries(my_app ${SDL2_LIBRARIES})
target_include_directories(my_app PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(my_app PUBLIC ${SDL2_CFLAGS_OTHER})
Отказ от ответственности: я бы просто прокомментировал сам ответ Громбеля, если у меня было достаточно уличных кредитов с помощью stackoverflow.
Ответ 4
Большинству доступных ответов не удается настроить заголовки для библиотеки pkg-config
. После размышления над Документацией для FindPkgConfig я пришел к решению, которое также обеспечивает это:
include(FindPkgConfig)
if(NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "pkg-config not found!" )
endif()
pkg_check_modules(<some-lib> REQUIRED IMPORTED_TARGET <some-lib>)
target_link_libraries(<my-target> PkgConfig::<some-lib>)
(Замените вашу цель вместо <my-target>
и любую библиотеку вместо <some-lib>
, соответственно.)
Опция IMPORTED_TARGET
кажется ключевой и делает все PkgConfig::
пространстве имен PkgConfig::
. Это было все, что требовалось, а также все, что требовалось.
Ответ 5
-
Нет такой команды, как target_use
. Но я знаю несколько проектов, которые написали такую команду для их внутреннего использования. Но каждый проект хочет передать дополнительные флаги или определяет, поэтому нет смысла иметь его вообще в CMake. Еще одна причина, по которой это не так: С++-шаблонные библиотеки, такие как Eigen, нет библиотеки, но у вас есть только куча включенных файлов.
-
Описанный способ часто бывает правильным. Это может различаться для некоторых библиотек, тогда вам придется добавить _LDFLAGS
или _CFLAGS
. Еще одна причина отсутствия target_use
. Если это не сработает для вас, задайте новый вопрос, касающийся SDL2 или любой другой библиотеки, которую вы хотите использовать.
Ответ 6
Если вы хотите добавить определения из библиотеки, для этого есть инструкция add_definitions
. Документацию можно найти здесь, а также дополнительные способы добавления флагов компилятора.
Следующий фрагмент кода использует эту инструкцию для добавления GTKGL в проект:
pkg_check_modules(GTKGL REQUIRED gtkglext-1.0)
include_directories(${GTKGL_INCLUDE_DIRS})
link_directories(${GTKGL_LIBRARY_DIRS})
add_definitions(${GTKGL_CFLAGS_OTHER})
set(LIBS ${LIBS} ${GTKGL_LIBRARIES})
target_link_libraries([insert name of program] ${LIBS})