はじめに
CMakeプロジェクト以外でビルドされた既存のライブラリや、プロプライエタリなライブラリでソースコードが公開されていないライブラリを、CMakeプロジェクトで利用したいケースがあります。
このようなライブラリをCMakeのターゲットとして扱うための仕組みが IMPORTED ターゲットです。
(ライブラリだけでなく、実行ファイルをIMPORTEDターゲットとして定義することもできます)
他にも、package-config.cmakeを記述する際に、インストールツリーのライブラリファイルをIMPORTEDターゲットとして定義するという使い道もあります。実際に、install(EXPORT) コマンドが生成するexport.cmakeはIMPORTEDターゲットを使用しています。
IMPORTED なライブラリを定義する
add_library() コマンドに IMPORTED オプションを指定すると、ターゲットをIMPORTEDなターゲットとして定義できます。なお、通常は意識する必要はありませんが、ターゲット・プロパティに IMPORTED
が定義されます。
add_library(foo SHARED IMPORTED)
厳密な構文は下記になります。
add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED [GLOBAL])
IMPORTEDなターゲットは、定義したディレクトリか、その配下の(つまりadd_subdirectoryした)ディレクトリで参照できます。上位のディレクトリからは参照できません。
もし、上位のディレクトリから参照したい場合は、GLOBALオプションを付与します。
ライブラリファイルの格納場所を指定する (IMPORTED_LOCATION
プロパティ)
add_library(<name> ... IMPORTED)
としただけでは、実際のライブラリファイルの格納場所をCMakeが知ることができないため、ユーザーは明示的にライブラリファイルの格納場所をCMakeに伝える必要があります。
ライブラリファイルの格納場所を伝えるには、以下のように、IMPORTED_LOCATION
プロパティ(または IMPORTED_LOCATION_<CONFIG>
プロパティ)を設定します。
set_target_properties(foo
PROPERTIES
IMPORTED_LOCATION /path/to/real/library/libfoo.so)
なおDLL環境でSHAREDライブラリの格納場所をIMPORTED_LOCATION
に指定する際には、.lib
ファイルでなく、.dll
ファイルを指定します。インポートライブラリ(.lib
)ファイルの格納場所は、IMPORTED_IMPLIB
または IMPORTED_IMPLIB_<CONFIG>
で指定します。
IMPORTED_LOCATION のドキュメント(CMake 3.0)
SONAMEを指定する (IMPORTED_SONAME
)
IMPORTED_SONAME
または IMPORTED_SONAME_<config>
プロパティを使用すると、SONAMEを指定できます。
クライアントターゲットが使用すべきインクルードディレクトリを指定する(INTERFACE_INCLUDE_DIRECTORIES
)
IMPORTEDライブラリを使用するプログラムをコンパイルする際に、所定のインクルードディレクトリに存在するヘッダファイルの include を要するケースがままあります。
INTERFACE_INCLUDE_DIRECTORIES
プロパティを指定すると、target_link_libraries(client foo)
のように foo
ライブラリをリンク指定することで、client
ターゲットに target_include_directories で foo
のINTERFACE_INCLUDE_DIRECTORIES で指定したディレクトリが付与されます。
set_target_properties(foo PROPERTIES INTERFACE_INCLUDE_DIRECTORIES /path/to/foo/headers)
# べつのどこか
add_executable(client client.cc)
target_link_libraries(client foo)
# 以下を省略できる
# target_include_directories(client /path/to/foo/headers)
このようにINTERFACE_INCLUDE_DIRECTORIES
を活用すると、/path/to/foo/headers
を変数foo_INCLUDE_DIRECTORIES
に設定して、個々のターゲットに target_include_directories
コマンドで付与するという煩雑な作業を省略できます。
クライアントターゲットが使用すべきコンパイラ定義を指定する INTERFACE_COMPILE_DEFINITIONS
このライブラリをリンクする実行ファイルや他のライブラリをコンパイルする際に付与すべきコンパイラ定義を指定します。
IMPORTEDターゲット以外でも使用できますが、その場合は、ライブラリターゲットにtarget_compile_definitions()
コマンドで指定する際に、PUBLIC
や INTERFACE
オプションを付与することで、このプロパティが自動的に設定されます。
クライアントターゲットが使用すべきコンパイラオプションを指定するINTERFACE_COMPILE_OPTIONS
このライブラリをリンクする実行ファイルや他のライブラリをコンパイルする際に付与すべきコンパイラオプションを指定します。IMPORTEDターゲット以外でも使用できます。
ターゲットがIMPORTED
ターゲットでなければ、target_compile_options
コマンドにINTERFACE
または PUBLIC
オプションを付与することで、自動的に設定できます。
依存ライブラリを指定する (IMPORTED_LINK_DEPENDENT_LIBRARIES
)
インポートするライブラリ自体が他のライブラリに依存していることがあります。
依存しているライブラリ群を IMPORTED_LINK_DEPENDENT_LIBRARIES
プロパティに指定することで、インポートしたライブラリをリンクする際に、このプロパティに指定したライブラリ群を同時にリンクできます。
詳細は追えていませんが、 `INTERFACE_LINK_LIBRARIES` という2.8.12から導入された新しいプロパティがあり、同様の動作をします。(INTERFACE_LINK_LIBRARIES に置き換えられた、IMPORTED_LINK_INTERFACE_LIBRARIES というプロパティもあります)