ところで、CMakeで管理された別のライブラリを、自動的にコンパイルして、リンクまでするためにはどうすればいいんだろう。 今のISSでそれを実現するために、とりあえず簡単なモデルを作って勉強してみることにした。
プロジェクトの構成
$ tree . . ├── CMakeLists.txt ├── main.c └── vendor ├── CMakeLists.txt ├── library.c └── library.h
メインのプログラムがmain.cだ。
- main.c
#include <stdio.h> #include "./vendor/library.h" int main () { volatile int a = 100, b = 200; printf ("call_add(%d, %d) = %d\n", a, b, call_add (a, b)); return 0; }
- vendor/library.c
int call_add (int a, int b) { return a + b; }
main()の中で、vendor/library.c で定義されているcall_add()を読んでいる。このlibraryは、別のCMakeLists.txt (あるいは別のリポジトリ)で管理されていて、mainをビルドするときに、一緒にlibraryもビルドされるようにしたい。
CMakeLists.txtの構成
CMakeLists.txtは、以下のようにしてみた。
- ./CMakeLists.txt
add_executable (main main.c) add_subdirectory (./vendor/) target_link_libraries (main library) link_directories (./vendor/)
- ./vendor/CMakeLists.txt
add_library (library STATIC library.c)
とりあえずは、library側は通常通りライブラリをビルドするためのCMakeLists.txtを記述する。肝となるのは、main側のCMakeLists.txtだ。
- subdirectoryにより、別の場所にライブラリが存在することを示す。
- target_link_libraries により、main がlibraryを使用することを示す。
- link_directory により、リンク時にvendorディレクトリを参照するように指定する。
おそらく肝になっているのはsubdirectoryなのかな? subdirectory中に入っているlibraryを使うためには、vendor側のCMakeLists.txtも実行しないといけない、というカラクリになっているのか。
$ cmake . -- The C compiler identification is GNU 4.9.2 -- The CXX compiler identification is GNU 4.9.2 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done CMake Warning (dev) at CMakeLists.txt:6 (link_directories): This command specifies the relative path ./vendor as a link directory. Policy CMP0015 is not set: link_directories() treats paths relative to the source dir. Run "cmake --help-policy CMP0015" for policy details. Use the cmake_policy command to set the policy and suppress this warning. This warning is for project developers. Use -Wno-dev to suppress it. CMake Warning (dev) in CMakeLists.txt: No cmake_minimum_required command is present. A line of code such as cmake_minimum_required(VERSION 3.0) should be added at the top of the file. The version specified may be lower if you wish to support older CMake versions for this project. For more information run "cmake --help-policy CMP0000". This warning is for project developers. Use -Wno-dev to suppress it. -- Configuring done -- Generating done -- Build files have been written to: /home/vagrant/swimmer_riscv/cmake_tests $ make Scanning dependencies of target library [ 50%] Building C object vendor/CMakeFiles/library.dir/library.o Linking C static library liblibrary.a [ 50%] Built target library Scanning dependencies of target main [100%] Building C object CMakeFiles/main.dir/main.o Linking C executable main [100%] Built target main $ ./main call_add(100, 200) = 300
これで、自動的にvendorディレクトリもビルドしてくれるMakefileが生成された。これを使って、どうにかしてISSのプロジェクトも、全て一発でビルドが完成するように改良してみよう。