Qual é a maneira correta de usar o `pkg-config` do` cmake`?

Olhando em volta na net eu vi um monte de código como este:

include(FindPkgConfig) pkg_search_module(SDL2 REQUIRED sdl2) target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS} target_link_libraries(app ${SDL2_LIBRARIES}) 

No entanto, essa parece ser a maneira errada de fazê-lo, já que ele usa apenas os diretórios e bibliotecas de inclusão, mas ignora as definições, os caminhos da biblioteca e outros sinalizadores que podem ser retornados pelo pkg-config .

Qual seria a maneira correta de fazer isso e garantir que todos os sinalizadores de compilation e link retornados pelo pkg-config sejam usados ​​pelo app compilado? E existe um único comando para realizar isso, ou seja, algo como target_use(app SDL2) ?

Primeiro de, a chamada:

 include(FindPkgConfig) 

deve ser substituído por:

 find_package(PkgConfig) 

A chamada find_package() é mais flexível e permite opções como REQUIRED , que fazem coisas automaticamente que uma teria que fazer manualmente com include() .

Em segundo lugar, a chamada manual do pkg-config deve ser evitada sempre que possível. O CMake vem com um rico conjunto de definições de pacotes, encontrado no Linux em /usr/share/cmake-3.0/Modules/Find*cmake . Estes fornecem mais opções e opções para o usuário, em seguida, uma chamada bruta para pkg_search_module() .

Quanto ao comando target_use() hipotético mencionado, o CMake na verdade já tem esse build-in de uma forma com PUBLIC | PRIVATE | INTERFACE. Uma chamada como target_include_directories(mytarget PUBLIC ...) fará com que os diretórios include sejam usados ​​automaticamente em todos os destinos que usam mytarget , por exemplo, target_link_libraries(myapp mytarget) . No entanto, esse mecanismo parece ser apenas para bibliotecas criadas no arquivo CMakeLists.txt e não funciona para bibliotecas adquiridas com o pkg_search_module() . A chamada add_library(bar SHARED IMPORTED) pode ser usada para isso, mas ainda não examinei isso.

Quanto à questão principal, isso aqui funciona na maioria dos casos:

 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}) 

O SDL2_CFLAGS_OTHER contém define e outros sinalizadores necessários para uma compilation bem-sucedida. No SDL2_LIBRARY_DIRS sinalizadores SDL2_LIBRARY_DIRS e SDL2_LDFLAGS_OTHER ainda são ignorados, sem a menor idéia da freqüência com que isso se tornaria um problema.

Mais docu em http://www.cmake.org/cmake/help/v3.0/module/FindPkgConfig.html

É raro que alguém só precise vincular com o SDL2. A resposta atualmente popular usa pkg_search_module() que verifica os módulos dados e usa o primeiro funcional.

É mais provável que você queira linkar com SDL2 e SDL2_Mixer e SDL2_TTF, etc … pkg_check_modules() verifica todos os módulos fornecidos.

 # 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}) 

Disclaimer: Eu teria simplesmente comentado sobre a auto-resposta de Grumbel se eu tivesse creds de rua suficientes com stackoverflow.

  1. Não existe tal comando como target_use . Mas conheço vários projetos que escreveram um comando para seu uso interno. Mas todo projeto quer passar bandeiras adicionais ou define, assim não faz sentido tê-lo em geral CMake. Outra razão para não tê-lo são bibliotecas de modelos C ++ como Eigen, não há biblioteca, mas você só tem um monte de arquivos de inclusão.

  2. A maneira descrita é freqüentemente correta. Pode ser diferente para algumas bibliotecas, então você terá que adicionar _LDFLAGS ou _CFLAGS . Mais um motivo para não ter target_use . Se isso não funcionar para você, faça uma nova pergunta específica sobre o SDL2 ou qualquer outra biblioteca que você queira usar.

Se você estiver querendo adicionar definições da biblioteca também, a instrução add_definitions está lá para isso. Documentação pode ser encontrada aqui , junto com mais maneiras de adicionar sinalizadores de compilador.

O trecho de código a seguir usa essa instrução para adicionar o GTKGL ao projeto:

 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})