add_executable
add_library
-I
target_include_directories
cmake の簡単な使い方をまとめます。
静的ライブラリ | 動的ライブラリ | 実行ファイル | |
---|---|---|---|
Linux | .a |
.so |
無し |
Windows | .lib |
.dll |
.exe |
ビルド方法 | add_library(mylib STATIC mylib.cpp) |
add_library(mylib SHARED mylib.cpp) |
add_executable(main main.cpp) |
add_executable
main.cpp
#include <iostream>
int main() {
std::cout << "hi" << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_executable(main main.cpp)
ビルド例
mkdir build
cd build/
cmake ..
make
./main
hi
add_library
mylib.cpp
#include <iostream>
void MyFunc() {
std::cout << "hi" << std::endl;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
add_library(mylib2 STATIC mylib.cpp)
ビルド例
mkdir build
cd build/
cmake ..
make
成果物
libmylib.so
libmylib2.a
mylib.cpp
#include <iostream>
void MyFunc() {
std::cout << "hi" << std::endl;
}
include/mylib.hpp
#pragma once
はインクルードガードの方法の一つです。
#pragma once
void MyFunc();
main.cpp
#include <mylib.hpp>
int main() {
MyFunc();
return 0;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_library(mylib STATIC mylib.cpp)
add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)
ビルド例
mkdir build
cd build/
cmake ..
make
./main
hi
成果物
libmylib.a
main
静的ライブラリと実行ファイルのビルドにおける CMakeLists.txt
を以下のように変更します。
cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)
成果物
libmylib.so
main
/usr/lib/libfoo.so
→ -lfoo
動的ライブラリのリンク方法には、絶対パスを指定する方法とリンカに検索させる方法の二つがあります。
後者について、-L
で指定したディレクトリ等に存在する libxxx.so/a
という静的または動的ライブラリを g++ などで指定するときは "lib" を除外して -lxxx
とします。
既定では実行ファイルは動的ライブラリを絶対パスで参照します。実行時に検索するように変更するためには以下のようにします。
cmake_minimum_required (VERSION 3.10)
set(CMAKE_SKIP_BUILD_RPATH true)
add_library(mylib SHARED mylib.cpp)
add_executable(main main.cpp)
target_link_libraries(main mylib)
target_include_directories(main PRIVATE include)
ldd main
の結果が
libmylib.so => /path/to/build/libmylib.so (0x00007f4676f50000)
から以下のように変更されます。
libmylib.so => not found
カレントディレクトリがライブラリの検索対象ではないため LD_LIBRARY_PATH
等で対応します。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./main
hi
プロジェクト名を指定します。
project( gtest_main )
PROJECT_NAME
で参照できます。
add_executable(${PROJECT_NAME} main.cpp)
CMakeLists.txt
の一番最初に記載します。project()
コマンドよりも前である必要があります。最低限必要な cmake のバージョンを指定します。
cmake_minimum_required(VERSION 2.8)
変数をコンソールに出力できます。CMakeLists.txt
のデバッグ時に便利です。
message("hi")
find_library(gtest NAMES libgtest.a PATHS googletest-master/googletest)
message(${gtest})
出力情報を増やして cmake デバッグしやすくします。
set(CMAKE_VERBOSE_MAKEFILE TRUE)
set(EXECUTABLE_OUTPUT_PATH /tmp)
set(LIBRARY_OUTPUT_PATH /tmp)
add_executable(main main.cpp)
target_compile_options(main PRIVATE "-Wall")
-I
target_include_directories
add_executable(main main.cpp)
target_include_directories(main PRIVATE path/to/include)
ライブラリの指定方法は複数あります。
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
find_library(mylib NAMES libcurl.so.4)
find_library(mylib2 NAMES EGL)
message("hi")
message(${mylib})
message(${mylib2})
実行例
mkdir build
cd build/
cmake ..
hi
/usr/lib/x86_64-linux-gnu/libcurl.so.4
/usr/lib/x86_64-linux-gnu/libEGL.so
cmake_minimum_required (VERSION 3.10)
find_program(path NAMES python)
message(${path})
cmake に登録されているモジュールの一覧は以下のコマンドで確認できます。
cmake --help-module-list
例えば FindPython を利用すると以下のようにパス検索できます。
cmake_minimum_required (VERSION 3.10)
find_package(Python REQUIRED)
message(${Python_FOUND})
message(${Python_EXECUTABLE})
実行例
$ cmake .
TRUE
/usr/bin/python3.7
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/somewhere
include ファイル分割
cmake_minimum_required (VERSION 3.10)
include("a/1.cmake")
include("a/2.cmake")
ソースコードと CMakeLists.txt が存在するディレクトリを読み込む場合 add_subdirectory
add_subdirectory("b")
cmake_minimum_required (VERSION 3.10)
string(REGEX REPLACE [[([0-9]+)]] [[!\1!]] replaced "abc123")
message(${replaced})
実行例
abc!123!
install によって make install
時のインストール先を設定できます。
mylib.hpp
#pragma once
void MyFunc();
mylib.cpp
#include <iostream>
void MyFunc() {
std::cout << "hi" << std::endl;
}
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
install(TARGETS mylib DESTINATION /tmp/lib)
install(FILES mylib.hpp DESTINATION /tmp/include)
実行例
mkdir build
cd build/
cmake ..
make
make install
[100%] Built target mylib
Install the project...
-- Install configuration: ""
-- Installing: /tmp/lib/libmylib.so
-- Installing: /tmp/include/mylib.hpp
cmake_minimum_required (VERSION 3.10)
execute_process(
COMMAND mkdir -p hello
WORKING_DIRECTORY /tmp
)
main の CMakeLists.txt
で target_include_directories
していないのがポイントです。ライブラリの利用側で都度設定する必要がなくなるため、特に依存関係が多段になった場合に有用です。
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_subdirectory("a")
add_executable(main main.cpp)
target_link_libraries(main mylib)
main.cpp
#include <mylib.hpp>
int main() {
MyFunc();
return 0;
}
a/CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED mylib.cpp)
target_include_directories(mylib INTERFACE include)
install(TARGETS mylib DESTINATION /tmp/a/lib)
install(DIRECTORY include DESTINATION /tmp/a)
a/mylib.cpp
#include <iostream>
void MyFunc() {
std::cout << "hi" << std::endl;
}
a/include/mylib.hpp
#pragma once
void MyFunc();
ビルド例
mkdir build
cd build/
cmake ..
make
./main
hi
make install
cmake で target_include_directories
する際には PUBLIC、PRIVATE、INTERFACE を選択します。
PUBLIC
→ 上記例で a
および main
の両方のビルドで必要という設定になります。PRIVATE
→ 上記例で a
のビルドについてのみ必要という設定になります。INTERFACE
→ 上記例で main
のビルドについてのみ必要という設定になります。自身 a
のビルドについては不要で、a
を利用する main
において必要となるため target_include_directories(mylib INTERFACE include)
としています。参考: INTERFACE 設定は、ヘッダーのみからなるライブラリを作る際にも利用できます。
IMPORTED ライブラリとして外部ライブラリを add_library
しています。依存関係が多段になった場合に有用です。find_library
で main に対して直接 target_link_libraries
しても動作します。
CMakeLists.txt
cmake_minimum_required (VERSION 3.10)
add_library(mylib SHARED IMPORTED)
set_target_properties(mylib PROPERTIES IMPORTED_LOCATION /tmp/a/lib/libmylib.so)
set_target_properties(mylib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES /tmp/a/include)
add_executable(main main.cpp)
target_link_libraries(main mylib)
main.cpp
#include <mylib.hpp>
int main() {
MyFunc();
return 0;
}
ビルド例
mkdir build
cd build/
cmake ..
make
./main
hi