web-dev-qa-db-ja.com

「cmake」から「pkg-config」を使用する適切な方法は何ですか?

ネットを見てみると、次のようなコードがたくさん見られました。

_include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)

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

ただし、インクルードディレクトリとライブラリのみを使用し、_pkg-config_によって返される可能性のある定義、ライブラリパス、およびその他のフラグを無視するため、これは間違った方法のようです。

これを実行し、_pkg-config_によって返されるすべてのコンパイルおよびリンクフラグが、コンパイルされたappで使用されるようにする正しい方法は何でしょうか。そして、これを達成するための単一のコマンド、つまりtarget_use(app SDL2)のようなものはありますか?

ref:

56
Grumbel

以下に示す他の方法では、一般的なインストール場所(/ usr/libなど)にない共有ライブラリのリンカーパスを構成できません。結果のリンカーエラーは/usr/bin/ld: cannot find -llibrary-1.0。私の場合、pkg-configファイルもインストールされず、PKG_CONFIG_PATH環境変数を使用してプロジェクトのpkg-configパスが追加されました。これは、機能する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

まず、呼び出し:

_include(FindPkgConfig)
_

次のものに置き換える必要があります。

_find_package(PkgConfig)
_

find_package()呼び出しはより柔軟で、include()を使用して手動で行う必要があることを自動的に行うREQUIREDなどのオプションを許可します。

第二に、_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を使用するすべてのターゲットでincludeディレクトリが自動的に使用されます。 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

44
Grumbel

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で十分なストリートクレデンスがあれば、Grumbelの自己回答についてコメントしただけです。

7
fluxrider

利用可能な回答のほとんどは、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::名前空間の下ですべてが利用可能になります。これが必要なすべてであり、すべてshouldも必要でした。

2
Eero Aaltonen
  1. target_useなどのコマンドはありません。しかし、私は、内部で使用するためにそのようなコマンドを作成したいくつかのプロジェクトを知っています。しかし、すべてのプロジェクトは追加のフラグまたは定義を渡したいため、一般的なCMakeでそれを使用することは意味がありません。それを持たないもう1つの理由は、EigenのようなC++テンプレートライブラリです。ライブラリはありませんが、インクルードファイルの束しかありません。

  2. 説明されている方法は、多くの場合正しいです。一部のライブラリでは異なる場合があるため、_LDFLAGSまたは_CFLAGSを追加する必要があります。 target_useがないもう1つの理由。うまくいかない場合は、SDL2または使用したいライブラリについて特定の新しい質問をしてください。

0
usr1234567