CMake編程實踐(一) 基礎CMake工程入門

CMake簡介

CMake 是什麼?

CMake是一個開源的跨平臺工具系列,旨在構建,測試和打包軟件。CMake用於使用簡單的平臺和獨立於編譯器的配置文件來控制軟件編譯過程,並生成可在您選擇的編譯器環境中使用的本機makefile和工作空間。CMake工具套件由Kitware創建,以滿足對ITK和VTK等開源項目的強大跨平臺構建環境的需求。
CMake類似於automake的跨平臺輔助項目編譯的工具,但語法更加簡單易用,你也可以認爲cmake是一套編程語言或者說腳本,稱爲CMake語言,支持變量定義、流程控制、函數、預製函數等。

CMake的工作流程

CMake處理頂級目錄的CMakeLists.txt(CMake的配置文件,配置了子目錄,編譯目標,編譯依賴等等),最後根據配置生成相應的MakeFile。
使用make命令就可以進行編譯。
在這裏插入圖片描述

環境要求

默認已配置好以下環境:
CMake
gcc
Linxu環境(ubuntu)

分析一個簡單的CMake工程

先來看一個標準的CMake工程cmake-template,掰開揉碎了給大家詳細分析下
1,子目錄src,用來存儲源代碼;
2,子目錄doc,用來存儲這個工程的相關文檔
3,子目錄build,用來存放這個工程編譯產生的臨時文件以及編譯好的應用程序等
4,README.md 用於描述該項目或者簡介;

目錄樹:

➜ cmake-template tree
.
├── CMakeLists.txt
├── doc
│ └── Introduction.txt
├── README.md
└── src
    ├── CMakeLists.txt
    └── main.cpp

2 directories, 5 files

主要文件:

CMakeLists.txt
src/CMakeLists.txt
src/main.cpp

CMakeLists.txt

# 聲明編譯要求cmake最低版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

# 聲明一個cmake工程
PROJECT(Hello)

# 添加子目錄, 並指定指定中間二進制和目標二進制存放的位置
ADD_SUBDIRECTORY(src bin)

# 安裝Hello腳本到bin目錄下,默認755權限
INSTALL(PROGRAMS ${PROJECT_BINARY_DIR}/bin/Hello DESTINATION bin)

# 安裝README文件到doc目錄下
INSTALL(FILES README.md DESTINATION doc)

# 安裝當前工程中doc/目錄下的所有內容到doc目錄下
INSTALL(DIRECTORY doc/ DESTINATION doc)

src/CMakeLists.txt

# 聲明編譯要求cmake最低版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

# 打印一些變量,沒什麼作用,僅爲了展示MESSAGE命令如何使用,以及如何引用變量${}
MESSAGE(STATUS "This is BINARY dir" ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir ${PROJECT_SOURCE_DIR}")
MESSAGE(STATUS "This is BINARY dir" ${Hello_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${Hello_SOURCE_DIR})

# 添加源文件
SET(SOURCE 
    main.cpp
    )

# 添加一個可執行程序,名稱和工程名稱保持一致
ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCE})

# 設置最終編譯生成的可執行程序或庫存放的位置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

src/main.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
 cout << "argc:"<< argc<< endl;
 for(int i=0; i<argc; i++)
 {
  cout << "argv["<< i <<"]:" << argv[i] << endl;
 }

 cout << "hello world by main.cpp" << endl;

 return 0;
}

基本語法規則:

1,變量使用${}方式取值,但是在 IF 控制語句中是直接使用變量名
2,指令(參數 1 參數 2…)
參數使用括弧括起,參數之間使用空格或分號分開。
以上面的 ADD_EXECUTABLE 指令爲例,如果存在另外一個 func.c 源文件,就要寫成:
ADD_EXECUTABLE(hello main.c func.c)或者
ADD_EXECUTABLE(hello main.c;func.c)
3,指令是大小寫無關的,參數和變量是大小寫相關的。但推薦你全部使用大寫指令。

MESSAGE 指令我們已經用到了這條規則:
MESSAGE(STATUS “This is BINARY dir” ${PROJECT_BINARY_DIR})
也可以寫成:
MESSAGE(STATUS “This is BINARY dir ${PROJECT_BINARY_DIR}”)

cmake 的語法還是比較靈活而且考慮到各種情況,比如
SET(SOURCE main.c)也可以寫成 SET(SOURCE “main.cpp”)
是沒有區別的,但是假設一個源文件的文件名是 ut ils.cpp(文件名中間包含了空格)。
這時候就必須使用雙引號,如果寫成了 SET(SOURCE ut ils.cpp),就會出現錯誤,提示
你找不到 ut 文件和 ils.cpp 文件。這種情況,就必須寫成:
SET(SOURCE “ut ils.cpp”)
此外,你可以可以忽略掉 source 列表中的源文件後綴,比如可以寫成
ADD_EXECUTABLE(SOURCE main),cmake會自動的在本目錄查找 main.c 或者 main.cpp
等,當然,最好不要偷這個懶,以免這個目錄確實存在一個 main.c 一個 main.cpp

編譯安裝

編譯生成的應用在哪裏?

在src/CMakeLists.txt中已經指定輸出到build/bin/目錄下
爲啥是build/bin目錄下呢?因爲我們在build目錄下執行的cmake指令,即編譯發生的當前目錄。這就要涉及到外部構建(out-of-source build)的內容了,後面會提到

安裝到哪裏?安裝那些內容?

通過CMAKE_INSTALL_PREFIX指定安裝位置,具體安裝的內容在項目根目錄的CMakeLists.txt中已經指定了

  • 將Hello二進制安裝到安裝目錄的/bin目錄
  • 將doc目錄中的所有文件以及README.md安裝到安裝目錄的/doc
cd cmake-template
mkdir build && cd build

# 指定安裝的目錄爲項目根目錄下的release
cmake -DCMAKE_INSTALL_PREFIX=../release ..
make
make install

# 查看安裝好的應用
tree ../release 
../release
├── bin
│ └── Hello
└── doc
    ├── Introduction.txt
    └── README.md

OK, 到這裏你已經熟悉並編譯安裝了第一個CMake工程,其中用到了幾個簡單的指令以及變量調用的方法,同時提及了兩個隱式變量_SOURCE_DIR 及_BINARY_DIR,演示了變量調用的方法,從這個過程來看,有些開發者可能會想,這比我直接寫 Makefile 要複雜多了,甚至我都可以不編寫 Makefile,直接使用 g++ main.cpp 即可生成需要的目標文件。是的,正如第一節提到的,如果工程只有幾個文件,還是直接編寫Makefile最簡單。但如果有成千上萬個源文件,那麼該如何組織編譯?

cmake-demo源碼已上傳到github,歡迎Star

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章