macのpkg-config & CMakeでlibraryが見つからずハマった

CMakeでプロジェクトのビルド周りを管理しているのだが、外部のライブラリがCMakeのfind_package()に対応していない場合は自分でライブラリを直接パスで設定する必要がある。リンクしたいライブラリが多数のライブラリに依存していたらかなり骨の折れる作業となる。しかし、もしpkg-configに対応しているのであれば自分でパスを設定する必要がない。pkg-configはシステムにインストールされているライブラリを検索し、そのライブラリをリンクするために必要なビルド時のオプションを生成してくれるツールだ。例えば以下のような具合に動作する。

pkg-config --libs poppler-glib
>>> -L/usr/local/lib -L/usr/local/Cellar/glib/2.62.3/lib -L/usr/local/opt/gettext/lib -L/usr/local/Cellar/cairo/1.16.0_2/lib -lpoppler-glib -lgobject-2.0 -lglib-2.0 -lintl -lcairo

これがCMakeにも対応しているので、CMakeに対応していなくても煩雑な設定を行うことなくライブラリをリンクさせることが出来る。CMakeの中では以下のように書く。

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIB_POPPLER REQUIRED poppler-glib)
add_executable(sample main.cpp)
target_link_libraries(sample ${LIB_POPPLER_LIBRARIES})
target_include_directories(main PRIVATE ${LIB_POPPLER_INCLUDE_DIRS})

使用可能なライブラリはpkg-config --list-allで確認できる。ここで一つ注意点がある。OSがlinuxであれば上記のもので問題なく動くのだが、macだとうまく動いてくれなかった。エラーでは以下のようにライブラリが見つからないと怒られる。

ld: library not found for -lpoppler-glib

macの場合では-lpoppler-glibという形でリンクするライブラリの指定を行っても見つけてくれないのが原因だ。cmakeで生成されたMakefilemake VERBOSE=1で確認すると、他のライブラリは-lにて.dylibや.a等のファイルのバスが指定されているが、エラーになっているものはそうなっていない。なのでそのようにしたら良い。この作業に相当するオプションはpkg-config自体にはないのだが、CMake上では以下の二行目のように用意されているのでそちらに差し替えたら良い。

<XXX>_LIBRARIES ... only the libraries (without the '-l')
<XXX>_LINK_LIBRARIES ... the libraries and their absolute paths

先のサンプルを例にするとこのようになる。

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIB_POPPLER REQUIRED poppler-glib)
add_executable(sample main.cpp)
target_link_libraries(sample ${LIB_POPPLER_LINK_LIBRARIES})
target_include_directories(main PRIVATE ${LIB_POPPLER_INCLUDE_DIRS})

https://cmake.org/cmake/help/v3.12/module/FindPkgConfig.html