it-swarm.com.de

Was ist der richtige Weg, `pkg-config` von` cmake` zu ​​verwenden?

Ich habe mich im Internet umgesehen und so viel Code gesehen:

include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)

target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS}
target_link_libraries(app ${SDL2_LIBRARIES})

Dies scheint jedoch der falsche Weg zu sein, da nur die Include-Verzeichnisse und -Bibliotheken verwendet werden. Ignoriert definiert jedoch Bibliothekspfade und andere Flags, die möglicherweise von pkg-config zurückgegeben werden.

Was wäre der richtige Weg, um dies zu tun und sicherzustellen, dass alle von pkg-config zurückgegebenen Compile- und Link-Flags von der kompilierten app verwendet werden? Und gibt es einen einzigen Befehl, um dies zu bewerkstelligen, d. H. Etwas wie target_use(app SDL2)?

47
Grumbel

Zunächst der Aufruf:

include(FindPkgConfig)

sollte ersetzt werden durch:

find_package(PkgConfig)

Der Aufruf von find_package() ist flexibler und ermöglicht Optionen wie REQUIRED, die Dinge automatisch erledigen, die man manuell mit include() erledigen müsste.

Zweitens sollte das manuelle Aufrufen von pkg-config Nach Möglichkeit vermieden werden. CMake enthält eine Vielzahl von Paketdefinitionen, die unter Linux unter /usr/share/cmake-3.0/Modules/Find*cmake Verfügbar sind. Diese bieten dem Benutzer mehr Optionen und Auswahlmöglichkeiten als ein roher Aufruf von pkg_search_module().

Was den erwähnten hypothetischen Befehl target_use() betrifft, hat CMake diesen bereits in einer Weise mit PUBLIC | PRIVATE | INTERFACE eingebaut. Ein Aufruf wie target_include_directories(mytarget PUBLIC ...) bewirkt, dass die Include-Verzeichnisse automatisch in jedem Ziel verwendet werden, das mytarget verwendet, z. target_link_libraries(myapp mytarget). Dieser Mechanismus scheint jedoch nur für Bibliotheken zu gelten, die in der Datei CMakeLists.txt Erstellt wurden, und funktioniert nicht für Bibliotheken, die mit pkg_search_module() erworben wurden. Der Aufruf add_library(bar SHARED IMPORTED) könnte dafür verwendet werden, aber ich habe das noch nicht untersucht.

Was die Hauptfrage betrifft, so funktioniert dies in den meisten Fällen:

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

Das SDL2_CFLAGS_OTHER Enthält definierte und andere Flags, die für eine erfolgreiche Kompilierung erforderlich sind. Die Flags SDL2_LIBRARY_DIRS Und SDL2_LDFLAGS_OTHER Werden jedoch weiterhin ignoriert, keine Ahnung, wie oft das zu einem Problem werden würde.

Weitere Dokumentation hier http://www.cmake.org/cmake/help/v3.0/module/FindPkgConfig.html

44
Grumbel

Es ist selten, dass man nur mit SDL2 verbinden muss. Die derzeit beliebte Antwort verwendet pkg_search_module(), die nach bestimmten Modulen sucht und das erste funktionierende verwendet.

Es ist wahrscheinlicher, dass Sie eine Verknüpfung mit SDL2 und SDL2_Mixer und SDL2_TTF herstellen möchten, etc ... pkg_check_modules() für alle angegebenen Module.

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

Haftungsausschluss: Ich hätte Grumbels Antwort einfach kommentiert, wenn ich genug Straßencreds mit stackoverflow gehabt hätte.

5
fluxrider

Andere unten gezeigte Methoden können die Linkerpfade für die gemeinsam genutzten Bibliotheken nicht konfigurieren, die nicht unter den normalerweise installierten Speicherorten gefunden werden (z. B./usr/lib). Der resultierende Linkerfehler war /usr/bin/ld: cannot find -llibrary-1.0. In meinem Fall wurden die pkg-config-Dateien ebenfalls nicht installiert, und die pkg-config-Pfade für das Projekt wurden mit der Umgebungsvariablen PKG_CONFIG_PATH hinzugefügt. Dies ist eine abgespeckte Version einer funktionierenden 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)
1
activedecay

Die meisten verfügbaren Antworten können die Header für die Bibliothek pkg-config nicht konfigurieren. Nach dem Meditieren über Dokumentation für FindPkgConfig habe ich eine Lösung gefunden, die diese auch bietet:

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

( Ersetzen Sie Ihr Ziel anstelle von <my-target> und die Bibliothek anstelle von <some-lib> entsprechend. )

Die Option IMPORTED_TARGET scheint der Schlüssel zu sein und macht dann alles unter dem Namensraum PkgConfig:: verfügbar. Dies war alles, was benötigt wurde und auch alles, was benötigt werden sollte .

0
Eero Aaltonen
  1. Es gibt keinen solchen Befehl wie target_use. Ich kenne jedoch mehrere Projekte, die einen solchen Befehl für den internen Gebrauch geschrieben haben. Jedes Projekt möchte jedoch zusätzliche Flags oder Definitionen übergeben, daher macht es keinen Sinn, es allgemein CMake zu haben. Ein weiterer Grund, es nicht zu haben, sind in C++ erstellte Bibliotheken wie Eigen. Es gibt keine Bibliothek, aber Sie haben nur eine Reihe von Include-Dateien.

  2. Der beschriebene Weg ist oft richtig. Bei einigen Bibliotheken kann es anders sein, dann müssen Sie _LDFLAGS oder _CFLAGS hinzufügen. Ein Grund mehr, target_use nicht zu haben. Wenn es für Sie nicht funktioniert, stellen Sie eine neue Frage zu SDL2 oder zur gewünschten Bibliothek.

0
usr1234567