目錄
- 語法
- 一些重要指令
- CMake常用變量
- CMake編譯工程
- 編譯流程
- 兩種構建方式
- 實例展示
參考:
基于VSCode和CMake實現C/C++開發 | Linux篇
語法
基本語法格式:指令(arg1 arg2 …)
- 參數使用括弧括起來
- 參數之間使用空格或者分號分開
指令是大小寫無關的,參數和變量是大小寫相關的
set(HELLO hello.cpp) # 將hello.cpp 作為一個名為 HELLO 的變量
add_executable(hello main.cpp hello.cpp)
ADD_EXECUTABLE(hello main.cpp ${HELLO})
變量使用方式取值,但是在IF控制語句里面直接使用變量名,例如:‘IF(HELLO)‘而不是‘IF({}方式取值,但是在IF控制語句里面直接使用變量名,例如:`IF(HELLO)`而不是`IF(方式取值,但是在IF控制語句里面直接使用變量名,例如:‘IF(HELLO)‘而不是‘IF({HELLO})`
一些重要指令
- cmake_minimum_required : 用來指定CMake的最小版本要求
# CMake最小版本要求為2.8.3
cmake_minimum_required(VERSION 2.8.3)
- project :用來定義工程名稱,并可指定工程支持的語言
project(HELLOWORLD C)
- set :顯示的定義變量
# 定義SRC變量,其值為sayhello.cpp hello.cpp
set(SRC sayhello.cpp hello.cpp)
- include_directories :向工程添加多個特定的頭文件搜索路徑->相當于指定g++編譯器的-I參數
# 將usr/include/myincludefolder 和 ./include 添加到頭文件搜索路徑
include_directories(usr/include/myincludefolder ./include)
- link_directories:向工程添加多個特定的庫文件搜索路徑->相當于指定g++編譯器的-L參數
# 將usr/lib/mylibfolder 和 ./lib 添加到庫文件搜索路徑
link_directories(usr/lib/mylibfolder ./lib)
- add_library :生成庫文件
# 通過變量 SRC 生成 libhello.so 共享庫
add_library(hello SHARED ${SRC})
- add_compile_options :添加編譯參數
# 添加編譯參數 -Wall -std=c++11 -O2
add_compile_options(-Wall -std=c++11 -O2)
- add_executable:生成可執行文件
# 編譯main.cpp生成可執行文件main
add_executable(main main.cpp)
- target_link_libraries:為target添加需要鏈接的共享庫->相當于指定g++編譯器的-l 參數
# 將hello動態庫鏈接到可執行文件main上
target_link_libraries(main hello)
- add_subdirectory:向當前工程添加存放源文件的子目錄,并可以指定中間二進制和目標二進制存放的位置
# 添加src子目錄,src中需要有一個CMakeLists.txt
add_subdirectory(src)
- aux_source_directory :發現一個目錄下所有的源代碼文件并將列表存儲在一個變量中,這個指令被用來臨時自動構建源文件列表
# 定義SRC變量,其值為當前目錄下所有的源代碼文件
aux_source_directory(. SRC)
# 編譯SRC變量所代表的源代碼文件,生成main可執行文件
add_executable(main ${SRC})
CMake常用變量
- CMAKE_C_FLAGS :gcc編譯選項
- CMAKE_CXX_FLAGS:g++編譯選項
# 在編譯選項后追加-std=c++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
- CMAKE_BUILD_TYPE:編譯類型(Debug,Release)
# 設定編譯類型為debug,調試時需要選擇debug
set(CMAKE_BUILD_TYPE Debug)
# 設定編譯類型為release,發布時需要選擇release
set(CMAKE_BUILD_TYPE Release)
- CMAKE_BINARY_DIR、PROJECT_BINARY_DIR 、_BINARY_DIR
這三個變量指代的內容是一致的
如果是 in source build,指的是工程頂層目錄
如果是out-of-source編譯,指的是工程編譯發生的目錄
- CMAKE_SOURCE_DIR、PROJECT_SOURCE_DIR、_SOURCE_DIR
這三個變量指代內容一致,不管采用何種編譯方式,都是工程頂層目錄
在in source build時,與CMAKE_BINARY_DIR等變量一致
- CMAKE_C_COMPILER:指定C編譯器
- CMAKE_CXX_COMPILER:指定C++編譯器
- EXECUTABLE_OUTPUT_PATH:可執行文件輸出的存放路徑
- LIBRARY_OUTPUT_PATH:庫文件輸出的存放路徑
CMake編譯工程
CMake目錄結構:項目主目錄存在一個CMakeLists.txt文件
一般有兩種方式設置編譯規則:
1、包含源文件的子文件夾包含CMakeLists.txt文件,主目錄的CMakeList.txt通過add_subdirectory添加子目錄即可
2、包含源文件的子文件夾未包含CMakeLists.txt文件,子目錄編譯規則體現在主目錄的CMakeLists.txt中
編譯流程
在linux下使用CMake構建C/C++工程的流程如下:
- 手寫CMakeLists.txt文件
- 執行命令
cmake PATH
生成Makefile(PATH是頂層CMakeLists.txt所在的目錄) - 執行命令
make
進行編譯
兩種構建方式
1、內部構建(in-source build):這種方式不推薦使用
內部構建會在同級目錄下產生一大堆中間文件,和工程源文件放在一起會顯得雜亂無章
# 內部構建
# 在當前目錄下,編譯本目錄的CMakeLists.txt,生成Makefile文件和其他文件
cmake .
# 執行make命令,生成target
make
2、外部構建(out-of-source build) :這種方式推薦使用
該方式將編譯輸出文件和源文件放在不同目錄中
# 外部構建
# 1、在當前目錄下,創建build文件夾
mkdir build
# 2、進入build文件夾
cd build
# 3、編譯上級目錄的CMakeList.txt ,生成Makefile和其他文件
cmake ..
# 4、執行make,生成目標文件
make
實例展示
實例一
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/hello$ tree
.
├── hello
└── hello.cpp
hello.cpp內容為:
#include<iostream>
using namespace std;
int main()
{cout << "hello world!" << endl;return 0;
}
我們進入目錄,然后輸入:
code .
這樣就能打開vscode了
我們要給這個最簡單的cpp程序寫一個CMakeLists.txt
CMakeLists.txt一般處于項目的頂層目錄,此處就在文件夾下了
一般來說,在vscode中寫cmakelists的話會有只能提示的,如果你裝了插件的話
# 指定最低版本要求
cmake_minimum_required(VERSION 3.0)
# 指定項目名稱
project(HELLO)
# 指定生成的可執行文件的名字 源文件
add_executable(hello_cmake hello.cpp)
## 此時等價于 g++ hello.cpp -o hello_cmake
接下來我們在vscode的終端里面進行外部構建并編譯
我們在終端下使用tree命令看看文件結構:
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/hello$ tree
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 3.16.3
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── a.out
│ │ │ │ ├── CMakeCCompilerId.c
│ │ │ │ └── tmp
│ │ │ └── CompilerIdCXX
│ │ │ ├── a.out
│ │ │ ├── CMakeCXXCompilerId.cpp
│ │ │ └── tmp
│ │ ├── cmake.check_cache
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── hello_cmake.dir
│ │ │ ├── build.make
│ │ │ ├── cmake_clean.cmake
│ │ │ ├── CXX.includecache
│ │ │ ├── DependInfo.cmake
│ │ │ ├── depend.internal
│ │ │ ├── depend.make
│ │ │ ├── flags.make
│ │ │ ├── hello.cpp.o
│ │ │ ├── link.txt
│ │ │ └── progress.make
│ │ ├── Makefile2
│ │ ├── Makefile.cmake
│ │ ├── progress.marks
│ │ └── TargetDirectories.txt
│ ├── cmake_install.cmake
│ ├── hello_cmake
│ └── Makefile
├── CMakeLists.txt
├── hello
└── hello.cpp
此時發現可執行文件是在build文件夾下的
實例二
此處用到的實例請參考:
gcc 編譯器使用指南
此時工程結構如下:
.
├── include
│ └── swap.h
├── main.cpp
├── sharemain
├── src
│ ├── libswap.a
│ ├── libswap.so
│ ├── swap.cpp
│ └── swap.o
└── staticmain
然后寫cmakelists.txt
cmake_minimum_required(VERSION 3.0)project(SWAP)
# 與 -Iinclude 命令對應
include_directories(include)# 此命令相當于 g++ main.cpp src/swap.cpp -Iinclude -o main_cmake
add_executable(main_cmake main.cpp src/swap.cpp)
然后執行cmake、make:
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST$ mkdir build
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST$ cd build/
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ cmake ..
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.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/dyy/Desktop/GCCTEST/build
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ make
Scanning dependencies of target main_cmake
[ 33%] Building CXX object CMakeFiles/main_cmake.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/main_cmake.dir/src/swap.cpp.o
[100%] Linking CXX executable main_cmake
[100%] Built target main_cmake
dyy@dyy-Lenovo-ThinkBook-14-IIL:~/Desktop/GCCTEST/build$ ./main_cmake
before
10 20
after
20 10