CMake - リンク
概要
ターゲットのリンク
例えば、ライブラリAがライブラリBを必要とする時、ライブラリ間に存在し得る依存関係には、いくつかの異なる種類がある。
- PRIVATE
- プライベートな依存関係とは、ライブラリAが自身の内部実装でライブラリBを使用することを指定する。
- ライブラリAにリンクする他のものは、ライブラリBについて知る必要はない。なぜなら、ライブラリBはライブラリAの内部実装だからである。
- PUBLIC
- パブリックな依存関係とは、ライブラリAが内部でライブラリBを使用するだけでなく、そのインターフェイスでもライブラリBを使用することを指定する。
- 例えば、ライブラリAで定義された関数が、ライブラリBで定義・実装された型のパラメータを少なくとも1つ持つ場合、
- ライブラリBの型を持つパラメータを提供しなければ、ライブラリAからその関数を呼び出すことができない。
- INTERFACE
- インターフェースな依存関係とは、ライブラリAを使用するために、ライブラリBの一部も使用しなければならないことを指定する。
- これは、ライブラリAが内部的にライブラリBを必要とせず、そのインターフェイスでライブラリBを使用するだけであるという点で、
PUBLIC
とは異なる。 add_library
コマンドのINTERFACE形式を使用して定義されたライブラリターゲットを使用する場合に便利である。- 例えば、ヘッダファイルのみのライブラリの依存関係を表すためにターゲットを使用する場合等が挙げられる。
target_link_libraries
コマンドを使用して、リンクだけではなく、依存関係を捉えることができる。
target_link_libraries(
<ターゲット名>
<PRIVATE または PUBLIC または INTERFACE>
item 1
item 2
# ...略
[<PRIVATE または PUBLIC または INTERFACE>]
item 3
item 4
# ...略
)
これにより、あるライブラリが他のライブラリにどのように依存するかをプロジェクトで定義することができる。
CMakeは、この方法でリンクされたライブラリの連鎖を通して依存関係を管理する。
以下の例では、uiライブラリはPUBLIC
としてcollectorライブラリとリンクされているため、myAppが直接collectorにリンクしているだけでも、そのPUBLIC
関係からmyAppはuiにもリンクされる。
一方、algoライブラリとengineライブラリは、PRIVATE
としてcollectorにリンクされているため、myAppはそれらに直接リンクされるわけではない。
これらのコマンドにより、ターゲット間でtarget_link_libraries
コマンドで接続された場合、コンパイラやリンカのフラグやヘッダ検索パスもターゲット間で伝達されるようになる。
add_library(collector src1.cpp)
add_library(algo src2.cpp)
add_library(engine src3.cpp)
add_library(ui src4.cpp)
add_executable(myApp main.cpp)
target_link_libraries(
collector
PUBLIC ui
PRIVATE algo engine
)
target_link_libraries(myApp PRIVATE collector)
このような場合、target_link_libraries
コマンドで使用するターゲット名は、
target_link_libraries
コマンドが呼び出されている同じディレクトリにおいて、add_executable
コマンドまたはadd_library
コマンドにより定義されている必要がある。
非ターゲットのリンク (target_link_librariesコマンド)
target_link_libraries
コマンドを呼び出す時は、常に、PRIVATE
、PUBLIC
、INTERFACE
オプションを指定する。
target_link_libraries
コマンドは、CMakeのターゲット以外にも、以下に示すものを指定することが可能である。
- ライブラリファイルへのフルパス
- CMakeはそのライブラリファイルをリンカコマンドに追加する。
- ライブラリファイルが変更された場合、CMakeはその変更を検出して、ターゲットを再リンクする。
- CMake 3.3以降では、リンカコマンドは指定されたフルパスを使用するが、CMake 3.2以前では、CMakeが代わりにライブラリを検索するようリンカに要求する場合がある。
- (例. /usr/lib/libfoo.soファイルを-lfooに置換する等)
- 単純なライブラリ名
- パスなしでライブラリ名だけを指定する場合、リンカコマンドはそのライブラリを検索する。
- (例えば、プラットフォームによって、fooは-lfoo、または、foo.libになる)
- リンクフラグ
- 特殊なケースとして、-lや-framework以外のハイフンで始まる項目は、リンカコマンドに追加されるフラグとして扱われる。
- ただし、これらは
PRIVATE
項目にのみ使用するように警告している。 PUBLIC
やINTERFACE
として定義する場合は、他のターゲットに引き継がれてしまい、必ずしも安全とは言えないからである。
上記に加え、項目の前にdebug
、optimized
、general
のいずれかのオプションを付加することができる。
これらのオプションは、ビルドがデバッグビルドとして設定されているかどうかに基づいて、それに続く項目が含まれるべき時をさらに絞り込むことである。
ただし、これらのオプションは、同様の機能をより明確で柔軟かつ堅牢な方法が別に存在するため、現在は使用しない方がよい。
- debugオプション
- 項目の前にdebugオプションを付加する場合、そのビルドがデバッグビルドである場合にのみ追加される。
- optimizedオプション
- 項目の前にoptimizedオプションを付加する場合、ビルドがデバッグビルドでない場合のみ追加される。
- generalオプション
- 項目の前にgeneralオプションを付加する場合、全てのビルド構成に対して項目を追加するように指定する。