cmake tutorialその5:デフォルトリンク動作の制御
cmakeチュートリアルその5
昨日も今日もcmake。たぶん明日も明後日も。
共有ライブラリのリンク
- Mixing Static and Shared (Step 9)の内容
- 改修内容としてはMathFunctionsライブラリを必ず使うようにする
- MathFunctionsのビルド時にユーザー定義の
mysqrt.cxx
を利用するかcmath
のものを利用するかを選択するようにする - 結果的にライブラリの依存関係は↓こんなかんじ。
tutorial.cxx
MathFunctions.cxx
mysqrt.cxxのsqrt()
(USE_MYMATHがONの場合)cmathの
sqrt()`(USE_MYMATHがONではない場合)
MathFunctions
でビルド時にユーザー定義のmysqrtかcmathのどちらのsqrtを呼ぶかを決定する- このビルド要件をcmakeで記述する。
- MathFunctionsのビルド時にユーザー定義の
- ビルド方針
- mysqrt.cxxを
SqrtLibrary
という静的ライブラリのターゲットにする MathFunctions
は共有ライブラリにする- tutorial.cxxはそのままexecutable
- mysqrt.cxxを
source | type | target name |
---|---|---|
mysqrt.cxx | STATIC libary | SqrtLibrary |
MathFunctions.cxx | SHARED library | MathFunctions |
tutorial.cxx | executable | Tutorial |
build
実際のビルド時に利用するcmakeの技術詳細
BUILD_SHARED_LIBS
変数によってadd_library
のデフォルト挙動を制御できる- 補足:デフォルト挙動=[STATIC | SHARED | MODULE]の指定がないコマンド実行のこと
# control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
CMAKE_<target type>_OUTPUT_DIRECTORY
でビルド結果(中間結果含む)のビルド結果を置くディレクトリを指定する。*RUNTIME*
の場所にはadd_executable()
で指定したtargetが置かれる*LIBRARY*
の場所にはadd_library()
をMODULE
オプションを指定した場合のもの(*.so
)が置かれる*ARCHIVE*
の場所にはadd_library()
をSTATIC
オプションを指定した場合のもの(*.lib
or*.a
)が置かれる
- 今回はArchive library runtime全てプロジェクトのバイナリディレクトリを指定しているのでそこに全部配置される
- ビルド後のビルドディレクトリにビルド成果、中間結果が配置される
:~/Documents/study/cmake-sandbox/CMake/Help/guide/tutorial/build$ ll *.a *.so Tutorial -rwxr-xr-x 1 yabu yabu 14880 12月 4 18:14 Tutorial* -rwxr-xr-x 1 yabu yabu 8904 12月 4 18:14 libMathFunctions.so* -rw-r--r-- 1 yabu yabu 3922 12月 4 18:14 libSqrtLibrary.a
愚痴:target_link_librariesで指定するlibのtypo
- タイポでビルド失敗(typo:MathFunctiuons)
target_link_libraries(Tutorial PUBLIC MathFunctiuons)
- このときのビルドエラーが↓なんだけど、
.h
が見つかりません、じゃなくてそんなlibないよ。くらいのエラーメッセージ出してくれてもいいのに。
$ cmake --build . -- Configuring done -- Generating done -- Build files have been written to: /home/yabu/Documents/study/cmake-sandbox/CMake/Help/guide/tutorial/build [ 11%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o /home/yabu/Documents/study/cmake-sandbox/CMake/Help/guide/tutorial/devlop/tutorial.cxx:7:10: fatal error: MathFunctions.h: No such file or directory #include "MathFunctions.h" ^~~~~~~~~~~~~~~~~ compilation terminated. CMakeFiles/Tutorial.dir/build.make:62: recipe for target 'CMakeFiles/Tutorial.dir/tutorial.cxx.o' failed make[2]: *** [CMakeFiles/Tutorial.dir/tutorial.cxx.o] Error 1 CMakeFiles/Makefile2:370: recipe for target 'CMakeFiles/Tutorial.dir/all' failed make[1]: *** [CMakeFiles/Tutorial.dir/all] Error 2 Makefile:162: recipe for target 'all' failed
- ちょっとぐぐってみると、公式フォーラムっぽいところに私と同意見があった
It's intended. If the library name is not a target then it is simply forwarded to the linker (e.g.
-lbaz
). The target_link_libraries documentation explains all the ways various names are treated.
- バグではなく想定した仕様らしい。
- https://cmake.org/cmake/help/v3.16/command/target_link_libraries.html
- 公式ドキュメントによるとライブラリ名を書く
- の箇所はtarget以外にもライブラリ名を直接書くことができる。
- 公式ドキュメントによるとライブラリ名を書く
target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
- 社内の詳しい人に聞いたところ、itemとmatchするtargetが見つからない場合に、library名で見に行くらしい。
- ちょっとまだ理解しきれてないのでこのへんで説明は切り上げます。
愚痴2:勝手にソース変更ヤメテ(チュートリアル)
cmakeに対する文句じゃないけどチュートリアルで勝手にincludeするやつを変えてる
勝手に
include<iostrteam>
をinclude<sstream>
に変えないで。- ビルドエラーには関係なかったけど全ファイルでdiff取ったときに出てきた。変えたならちゃんと説明して。
// A simple program that computes the square root of a number #include <cmath> #include <sstream> #include <string>
まとめ
- top-leveのCMakeLists.txtに定義した
BUILD_SHARED_LIBS
でadd_library
のデフォルト機能を抑制できる CMAKE_<アーティファクト種類>_OUTPUT_DIRECTORY
でビルド成果の格納場所を指定可能- 依存先の解決は各target_link_librariesにtarget名を使っているのでこの変数に設定した値は特に利用していない(というのが私の理解)