CMake: IMPORTEDターゲット

# はじめに
CMakeプロジェクト以外でビルドされた既存のライブラリや、プロプライエタリなライブラリでソースコードが公開されていないライブラリを、CMakeプロジェクトで利用したいケースがあります。

このようなライブラリをCMakeのターゲットとして扱うための仕組みが IMPORTED ターゲットです。
（ライブラリだけでなく、実行ファイルをIMPORTEDターゲットとして定義することもできます）

他にも、package-config.cmakeを記述する際に、インストールツリーのライブラリファイルをIMPORTEDターゲットとして定義するという使い道もあります。実際に、install(EXPORT) コマンドが生成するexport.cmakeはIMPORTEDターゲットを使用しています。

## IMPORTED なライブラリを定義する

add_library() コマンドに IMPORTED オプションを指定すると、ターゲットをIMPORTEDなターゲットとして定義できます。なお、通常は意識する必要はありませんが、ターゲット・プロパティに `IMPORTED` が定義されます。

```cmake
add_library(foo SHARED IMPORTED)
```

厳密な構文は下記になります。

```cmake
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>` プロパティ）を設定します。

```cmake:IMPORTED_LOCATIONの設定
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)](http://www.cmake.org/cmake/help/v3.0/prop_tgt/IMPORTED_LOCATION.html#prop_tgt:IMPORTED_LOCATION)

## 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 で指定したディレクトリが付与されます。

```cmake
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` プロパティに指定することで、インポートしたライブラリをリンクする際に、このプロパティに指定したライブラリ群を同時にリンクできます。

```raw:note
詳細は追えていませんが、 `INTERFACE_LINK_LIBRARIES` という2.8.12から導入された新しいプロパティがあり、同様の動作をします。（INTERFACE_LINK_LIBRARIES に置き換えられた、IMPORTED_LINK_INTERFACE_LIBRARIES というプロパティもあります）
```