序章
前のセクションでは、make/Makefile
以前に紹介した c++ プロジェクトのコンパイルを紹介しました。このプロジェクトを例として使用して説明します。
C++ コンパイル (1)-g++ 単一/複数ファイル/ライブラリ コンパイル
C++ コンパイル (2)-make および makefile コンパイル プロセス
次のように、前のセクションの実際の戦闘のディレクトリ構造を見てみましょう。
- mutilFilesDemo
- include // 头文件目录
- HelloTools.h
- Prints.h
- libs // 库子项目目录
- ToolLibs.h
- ToolLibs.cpp
- Makefile // 子项目Makefile
- src // 源码目录
- module // 源码模块
- Prints.cpp // Prints类
- HelloTools.cpp // HelloTools类
- main.cpp // main类
- Makefile // 主项目Makefile
make と Makefile,cmake と CMakeLists.txt
make
c++ プロジェクトをコンパイルするために使用され、make
コマンドはMakefile
コマンドで構成されたコンパイル リンク関係に基づいており、Makefile
ファイルの生成は大きなプロジェクトであるため、表示されcmake工具
、それcmake
に従ってCMakeLists.txt
cmake コマンドが実行されます。
CMake を使用してクロスプラットフォーム プロジェクトを作成するプロセスは次のとおりです。
(1) ソースファイルの書き込み
(2) CMakeLists.txt を書く
(3) CMake は、CMakeLists.txt に従って、対応する makefile を生成します。
(4) make を使用し、makefile に従って gcc を呼び出して、対応する実行ファイルを生成します。
CMake は、すべてのプラットフォームのコンパイル プロセスを簡単な文章で記述できるクロスプラットフォーム コンパイル ツールです。彼は、さまざまなメイクファイルまたはプロジェクト ファイルを出力できます。make や makefile と同様に、CMake を使用する際のルールを提供するファイルも必要です。
CMakeLists.txt
CMakeLists.txt を記述する最も一般的な機能は、他の .h ヘッダー ファイルと .so/.a ライブラリ ファイルを呼び出し、.cpp/.c/.cc ファイルを実行可能ファイルまたは新しいライブラリ ファイルにコンパイルすることです。
# 指定cmake最小版本
cmake_minimum_required(VERSION 3.4.1)
# 本CMakeLists.txt的project名称
# 会自动创建两个变量,PROJECT_SOURCE_DIR和PROJECT_NAME
# ${PROJECT_SOURCE_DIR}:本CMakeLists.txt所在的文件夹路径
# ${PROJECT_NAME}:本CMakeLists.txt的project名称
# CMAKE_BINART_DIR, PROJECT_BINARY_DIR, <projectName>_BINARY_DIR:这三个变量的含义一样。
project(xxx)
# 获取路径下所有的.cpp/.c/.cc文件,并赋值给变量中
aux_source_directory(路径 变量)
# 给文件名/路径名或其他字符串起别名,用${变量}获取变量内容
set(变量 文件名/路径/...)
# 添加编译选项
add_definitions(编译选项)
# 打印消息
message(消息)
# 编译子文件夹的CMakeLists.txt
add_subdirectory(./subProject)
# 将.cpp/.c/.cc文件生成可执行文件
add_executable(main main.cpp)
# 将.cpp/.c/.cc文件生成.a静态库 // add_library(库文件名称 STATIC 文件)
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
# 生成静态库(默认)
add_library(util STATIC util.cpp)
# 生成动态库
add_library(util SHARED util.cpp)
# 规定.h头文件路径
include_directories(路径)
# 规定.so/.a库文件路径
link_directories(路径)
# 对add_library或add_executable生成的文件进行链接操作
# 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
target_link_libraries(可执行文件名称 链接的库文件名称)
# 如果是链接的动态库,则运行的时候需要把它拷贝到可执行文件名称同目录下
DGBデバッグモードの設定方法はこちらをご覧ください
CMakeListsの書き込み処理の方法
1. cmake の最小バージョンを指定する
cmake_minimum_required(VERSION 3.4.1)
2. プロジェクト名を設定する
project(myProject)
2 つの変数 myProject_BINARY_DIR と myProject_SOURCE_DIR が導入され、同時に、cmake は 2 つの同等の変数 PROJECT_BINARY_DIR と PROJECT_SOURCE_DIR を自動的に定義します。
3. コンパイル タイプを設定する
// 将.cpp/.c/.cc文件生成可执行文件
add_executable(main main.cpp)
// 生成静态库(默认)
add_library(util STATIC util.cpp tools.cpp)
// 生成动态库
add_library(util SHARED util.cpp tools.cpp)
を追加しない場合STATIC|SHARED
、デフォルトでは静的ライブラリが生成されます。さらに、生成されたライブラリにはデフォルトで接頭辞lib
と接尾辞が付けられます*.a|*.so
4. すべての cpp ファイルを検索する
aux_source_directory(. SRC_LIST)
add_library(demo ${
SRC_LIST})
ディレクトリ内のすべてのソース コード ファイルを検索し、そのリストを変数に格納します (ディレクトリを再帰的に走査しません)。
5. 検索ルールをカスタマイズする
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_library(demo ${
SRC_LIST})
#或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${
SRC_LIST} ${
SRC_PROTOCOL_LIST})
#或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_library(demo ${
SRC_LIST) ${
SRC_PROTOCOL_LIST)
6. 検索するライブラリ ファイルを指定する
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
指定されたプリコンパイル済みライブラリを見つけて、そのパスを変数に格納します。デフォルトの検索パスは、cmake に含まれるシステム ライブラリです。
同様のコマンドには、find_file()、find_path()、find_program()、find_package() があります。
7. 含まれるディレクトリを設定する
include_directories(
${
CMAKE_CURRENT_SOURCE_DIR}
${
CMAKE_CURRENT_BINARY_DIR}
${
CMAKE_CURRENT_SOURCE_DIR}/include
)
Linux では、次のようにインクルード ディレクトリを設定することもできます。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")
8. リンク ライブラリの検索ディレクトリを設定する
link_directories(
${
CMAKE_CURRENT_SOURCE_DIR}/libs
)
Linux では、次のようにインクルード ディレクトリを設定することもできます。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs")
9. ターゲットがリンクする必要があるライブラリを設定します
target_link_libraries( # 目标库
demo
# 目标库需要链接的库
# log-lib 是上面 find_library 指定的变量名
${
log-lib} )
target_link_libraries(demo libface.a) # 链接libface.a
target_link_libraries(demo libface.so) # 链接libface.so
ライブラリ ファイルの名前は通常 libxxx.so であることに注意してください。ここに xxx と記述してください。明確に指定する必要がある場合は、プレフィックスとサフィックスを追加できます。
10. 変数の使用
# set 直接设置变量的值
set(SRC_LIST main.cpp test.cpp)
add_executable(demo ${
SRC_LIST})
# set 追加设置变量的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${
SRC_LIST} test.cpp)
add_executable(demo ${
SRC_LIST})
# list 追加或者删除变量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${
SRC_LIST})
11. コンパイル オプションを追加する
機能 1
add_definitions
関数はC/C++ と#define
同じです。
# 添加一个宏定义,设置后,代码中即可使用 `TEST_DEBUG`这个宏,等同在代码中增加 #define TEST_DEBUG
add_definitions(-DTEST_DEBUG)
したがって、cpp コードでは、TEST_DEBUG
このマクロを使用できます。
#ifdef TEST_DEBUG
...
#else
...
#endif
問題は、誰がこのマクロの定義を推進するかということです。optionsコマンドを組み合わせることで実現できます
# 设置一个宏选项默认值ON,
# option选项 不会影响到cpp代码(不会添加#define宏)
option(TEST_DEBUG "test" ON)
if(TEST_DEBUG )
message("itis" ${TEST_IT_CMAKE})
add_definitions(-DTEST_DEBUG )
endif()
最後に、cmake を実行するときに、このオプションを設定して値を渡すことができます。
cmake .. -DTEST_DEBUG=1
次のように、cmake-gui を介してオプションを構成することも非常に便利です。
機能 2
add_definitions("-Wall -g")
#没加之前
gcc -c main.c -o test
#添加之后,相当于
gcc -g -Wall -c main.c -o tes
12. 複雑なプロジェクト、サブプロジェクト
# 添加subProjectDir子目录
add_subdirectory(subProjectDir)
subProjectDir ディレクトリの CMakeLists.txt は、次のように記述できます。
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library(subFuns ${
DIR_LIB_SRCS})
13. その他
- 一般的に使用される定義済み変数
変数 | 例証する |
---|---|
PROJECT_SOURCE_DIR | プロジェクトのルート ディレクトリ |
PROJECT_BINARY_DIR | cmake コマンドが実行されるディレクトリ。通常は ${PROJECT_SOURCE_DIR}/build |
PROJECT_NAME | project コマンドで定義されたプロジェクト名を返します |
CMAKE_CURRENT_SOURCE_DIR | 現在処理中の CMakeLists.txt が配置されているパス |
CMAKE_CURRENT_BINARY_DIR | ターゲット コンパイル ディレクトリ |
CMAKE_CURRENT_LIST_DIR | CMakeLists.txt へのフル パス |
CMAKE_CURRENT_LIST_LINE | 現在の行 |
CMAKE_MODULE_PATH | cmake モジュールが配置されているパスを定義します。SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) の場合、INCLUDE コマンドを使用して独自のモジュールを呼び出すことができます |
EXECUTABLE_OUTPUT_PATH | ターゲットのバイナリ実行可能ファイルの保存場所を再定義する |
ライブラリ_出力_パス | ターゲット リンク ライブラリの格納場所を再定義します |
-
環境変数
- 環境変数を使用する
$ENV{name}
- 環境変数を書く
set(ENV{name} value)
- 環境変数を使用する
-
cmake
コマンドの共通パラメーター
Cmake命令行使用:
-G 指明生成的Makefile格式
-D 添加参数
-S 指明源码位置
-B 指明输出路径
例如:
cmake -G “MinGW Makefiles” -S “源码路径” -B “输出路径”
或者
cmake -G “MinGW Makefiles” -D CMAKE_TOOLCHAIN_FILE=“编译工具链路径” -S “源码路径” -B “输出路径”
注意:Cmake是不支持中文的,无论是GUI还是命令行,都严禁出现中文字符.
- 規則ルール
不好的 CMake 的用法
不要使用全局函数,例如 link_directories,include_libraries,add_definitions 等,请你忘记它们
不要滥用 PUBLIC,除非有依赖传递,否则请你使用 PRIVATE 替换 PUBLIC
不要使用 GLOB 来添加文件
不要直接链接文件,而是链接目标
链接时千万不要跳过 PUBLIC/PRIVATE,这会导致未来的链接都没有关键字
良好的 CMake 用法
把 CMake 视作代码,保持它的整洁和可读性
围绕 target 构建你的 CMake。将需要的信息打包在 target 里,然后链接那个目标
导出你的接口
写 Config.cmake 文件,这是一个库作者应该做的,可以方便别人使用你的库
使用 ALAS 目标,以保持使用一致性
将常用的功能提取成函数或者宏,通常函数更好
使用小写的函数名,全大写是变量
使用 cmake_policy 或者 range of versions
CMakeLists.txt を使用してコンパイル プロセスを完了する方法
前節のプロジェクトを例に、コンパイルを実現するために CMakeLists.txt に変換してみましょう。以下に示すように、最初に 2 つのMakefile
ファイルを削除し、2 つの CMakeLists.txt を作成します。これは、複数フォルダーおよび複数プロジェクトの複数レベルのコンパイルの場合でもあります (他のファイルは変更する必要はありません)。
- mutilFilesDemo
- include // 头文件目录
- HelloTools.h
- Prints.h
- libs // 库子项目目录
- ToolLibs.h
- ToolLibs.cpp
- CMakeLists.txt // 子项目CMakeLists.txt
- src // 源码目录
- module // 源码模块
- Prints.cpp // Prints类
- HelloTools.cpp // HelloTools类
- main.cpp // main类
- CMakeLists.txt // 主项目CMakeLists
前のチュートリアルをまだ読んでいない場合は、ここをクリックして前のセクションを読んで
1.最初にサブプロジェクトのソースコードを提供libs
しCMakeLists.txt
ます
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(subLibPro)
aux_source_directory(. SRC_LIST)
add_library(ToolLibs STATIC ${
SRC_LIST})
libs ディレクトリに入り、最初にbuild
一時的なコンパイル ディレクトリを作成してから、cmake を実行します。
$ cd mutilFilesDemo/libs
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mutilFilesDemo/libs/build
実行が成功するとbuild
ディレクトリに自動で作成されるのでMakefile
、このファイルを使って直接実行make
・コンパイルできる
# 先看看cmake后,创建了写啥东西
$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
# 在执行一下make
$ make
Scanning dependencies of target ToolLibs
[ 50%] Building CXX object CMakeFiles/ToolLibs.dir/ToolLibs.cpp.o
[100%] Linking CXX static library libToolLibs.a
[100%] Built target ToolLibs
# 编译成功后,最后再查看一下目录是否生成我们需要的静态库
$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libToolLibs.a Makefile
必要なものが正常に生成されたことがわかりますlibToolLibs.a
2. 次に、メイン プロジェクトの作成方法を見てみましょうCMakeLists.txt
最初にコードを直接投稿してください
cmake_minimum_required(VERSION 3.4.1)
# 项目名称
project(mainPro)
# 设置子项目目录变量-libs
set(SUB_PROJ_LIBS_DIR libs)
# 设置主项目依赖的库名变量-libToolLibs.a
set(MAIN_LIBS ToolLibs)
# 添加子项目
add_subdirectory(${
SUB_PROJ_LIBS_DIR})
# 搜索主项目源码
file(GLOB SRC_LIST "*.cpp" "src/*.cpp" "src/modules/*.cpp")
# 生成可执行目标
add_executable(${
PROJECT_NAME} ${
SRC_LIST})
# 添加库目录
link_directories(${
PROJECT_NAME} ${
SUB_PROJ_LIBS_DIR})
# 添加链接库
target_link_libraries(${
PROJECT_NAME} ${
MAIN_LIBS})
mutilFilesDemo ディレクトリの下にビルド ディレクトリを作成して、コンパイル済みファイルを生成します。同時に、前のサブプロジェクトのコンパイル プロセスで作成されたビルド ディレクトリを削除します。
$ cd mutilFilesDemo
$ mkdir build
$ cd mutilFilesDemo/libs
$ rm -rf ./build
$ cd mutilFilesDemo/build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mutilFilesDemo/build
が正常に作成されましたMakefile
。実行を続けますmake
$ make
Scanning dependencies of target ToolLibs
[ 16%] Building CXX object libs/CMakeFiles/ToolLibs.dir/ToolLibs.cpp.o
[ 33%] Linking CXX static library libToolLibs.a
[ 33%] Built target ToolLibs
Scanning dependencies of target mainPro
[ 50%] Building CXX object CMakeFiles/mainPro.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/mainPro.dir/src/HelloTools.cpp.o
[ 83%] Building CXX object CMakeFiles/mainPro.dir/src/modules/Prints.cpp.o
[100%] Linking CXX executable mainPro
[100%] Built target mainPro
完璧で、ずさんではありません; サブライブラリ プロジェクトはCMakeLists.txt
自動的に実行され、前のセクションで直接書いたように、すべてのプロジェクト コンパイル プロセス ファイルを最も外側のビルド ディレクトリに配置するのに自動的に役立ちます;スタティックMakefile
ライブラリは自動的にリンクされるため、スタティック ライブラリのおおよそのディレクトリを指定するだけで済みます (指定しなくても、cmake はlink_directories
コンパイル済みの作業ディレクトリ全体でbuild
必要なライブラリを自動的に検索します)。
実装してみましょうmainPro
$ ./mainPro
Hello world!
MAX_NUM+n:110
=================================
使用静态库-add(a,b)
结果为:a+b=500
前のセクションと同じ結果
参考文献
C++ コンパイル (1)-g++ 単一/複数ファイル/ライブラリ コンパイル
C++ コンパイル (2)-make および makefile コンパイル プロセス
CMakeLists の基本的な使用方法
https://zhuanlan.zhihu.com/p/473573789