Как правильно использовать '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)?

4 ответов


во-первых, вызов:

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() command, CMake на самом деле уже имеет эту сборку в пути с PUBLIC|PRIVATE|INTERFACE. Звонок типа target_include_directories(mytarget PUBLIC ...) приведет к тому, что каталоги include будут автоматически использоваться в каждой цели, которая использует mytarget, например,target_link_libraries(myapp mytarget). Однако этот механизм, похоже, предназначен только для библиотек, созданных в и не работает для библиотек, приобретенных с 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 содержит определения и другие флаги, необходимые для успешной компиляции. Флаги!--17--> и SDL2_LDFLAGS_OTHER однако все еще игнорируются, не знаю, как часто это станет проблемой.

больше docu на http://www.cmake.org/cmake/help/v3.0/module/FindPkgConfig.html


редко, что нужно будет только связать с 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.


  1. нет такой команды как target_use. Но я знаю несколько проектов, которые написали такую команду для внутреннего пользования. Но каждый проект хочет передать дополнительные флаги или определяет, таким образом, не имеет смысла иметь его вообще CMake. Еще одна причина не иметь его-это библиотеки шаблонов C++, такие как Eigen, нет библиотеки, но у вас есть только куча файлов include.

  2. описанный способ часто бывает правильным. Это может отличаться для некоторых библиотеки, тогда вам придется добавить _LDFLAGS или _CFLAGS. Еще одна причина не иметь target_use. Если это не работает для вас, задайте новый вопрос о SDL2 или любой библиотеке, которую вы хотите использовать.


Если вы хотите добавить определения из библиотеки, а также 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})