CMAKE入門實戰

2021-02-19 光城
0.導語

最近做的項目使用CLION構建,而這個採用CMakeLists.txt管理,因此為了更好的學習,故找到了一篇大牛級別的入門文章,有文章有代碼,本文是花了一點時間把這篇文章學習後的重要點記錄吧,原作者github地址:https://github.com/wzpan/cmake-demo。

1.單個源文件

CMakeLists.txt 的語法比較簡單,由命令、注釋和空格組成,其中命令是不區分大小寫的。符號 # 後面的內容被認為是注釋。命令由命令名稱、小括號和參數組成,參數之間使用空格進行間隔。

首先創建一個main.cpp

#include <iostream>

int main() {
   std::cout << "Hello, World!" << std::endl;
   return 0;
}

編寫第一個CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(cmakeLearn)
add_executable(main main.cpp)

cmake_minimum_required:指定運行此配置文件所需的 CMake 的最低版本;

project:參數值是 cmakeLearn,該命令表示項目的名稱是 cmakeLearn 。

add_executable:將名為main.cpp的源文件編譯成一個名稱為 cmakeLearn 的可執行文件。

現在查看一下路徑:

light@city:~/CLionProjects/cmakeLearn$ ls
CMakeLists.txt  main.cpp

輸入下列命令進行cmake

cmake .

cmake過程

light@city:~/CLionProjects/cmakeLearn$ cmake .
-- The C compiler identification is GNU 5.5.0
-- The CXX compiler identification is GNU 5.5.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/light/CLionProjects/cmakeLearn

cmake 後 生成了Makefile

light@city:~/CLionProjects/cmakeLearn$ ls
CMakeCache.txt cmake_install.cmake main.cpp
CMakeFiles     CMakeLists.txt       Makefile

然後執行make

light@city:~/CLionProjects/cmakeLearn$ make
Scanning dependencies of target main
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main

執行

light@city:~/CLionProjects/cmakeLearn$ ./main
Hello, World!

2.多個源文件2.1 同一目錄,多個源文件

在1中的cmake添加下面這行:

# 查找當前目錄下的所有源文件
# 並將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)

當本地源文件很多,如果將源文件都加到裡面就很煩,所以這裡採用aux_source_directory。CMake 會將當前目錄所有源文件的文件名賦值給變量 DIR_SRCS ,再指示變量 DIR_SRCS 中的源文件需要編譯成一個名稱為 Demo 的可執行文件。

這樣就避免出現下面這種情況:

# 指定生成目標
add_executable(Demo main.cc MathFunctions.cc xx.cc ....cc)

小結:

查找當前目錄下的所有源文件,並將名稱保存到 DIR_SRCS 變量。

2.2 多個目錄,多個源文件

此時目錄架構:

./Demo3
  |
  +--- main.cc
  |
  +--- math/
        |
        +--- MathFunctions.cc
        |
        +--- MathFunctions.h

對於這種情況,需要分別在項目根目錄 Demo3 和 math 目錄裡各編寫一個 CMakeLists.txt 文件。

為了方便,我們可以先將 math 目錄裡的文件編譯成靜態庫再由 main 函數調用

這裡與上述2.1CMakeLists不同之處是在上面基礎上加上了:

# 添加 math 子目錄
add_subdirectory(math)
# 添加連結庫
target_link_libraries(Demo MathFunctions)

以此完成:

最後,在子目錄下指定連結庫名字:

子目錄中的 CMakeLists.txt:

# 查找當前目錄下的所有源文件
# 並將名稱保存到 DIR_LIB_SRCS 變量
aux_source_directory(. DIR_LIB_SRCS)
# 生成連結庫
add_library (MathFunctions ${DIR_LIB_SRCS})

小結:

將 src 目錄中的源文件編譯為靜態連結庫。

3.自定義編譯選項

CMake 允許為項目增加編譯選項,從而可以根據用戶的環境和需求選擇最合適的編譯方案。

例如,可以將 MathFunctions 庫設為一個可選的庫,如果該選項為 ON ,就使用該庫定義的數學函數來進行運算。否則就調用標準庫中的數學函數庫。

本節CMake與2不同如下三塊:

(1)加入一個配置頭文件,用於處理 CMake 對源碼的設置

# 加入一個配置頭文件,用於處理 CMake 對源碼的設置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)

configure_file 命令用於加入一個配置頭文件 config.h ,這個文件由 CMake 從 config.h.in生成,通過這樣的機制,將可以通過預定義一些參數和變量來控制代碼的生成。

例如:修改main.cc:

#include "config.h"
...
...
...
#ifdef USE_MYMATH
#include "math/MathFunctions.h"
#else
#include
#endif

根據 USE_MYMATH 的預定義值來決定是否調用標準庫還是 MathFunctions 庫。

上修改main.cc中引用了一個 config.h 文件,這個文件預定義了 USE_MYMATH 的值。但我們並不直接編寫這個文件,為了方便從 CMakeLists.txt 中導入配置,我們編寫一個 config.h.in 文件:

#cmakedefine USE_MYMATH

這樣 CMake 會自動根據 CMakeLists 配置文件中的設置自動生成 config.h 文件。

這裡使用了ccmake進行可視化編譯選擇,Ubuntu上安裝:

sudo apt-get install cmake-curses-gui

運行ccmake .後:


hjkl控制方向移動,enter 鍵可以修改該選項。修改完成後可以按下 c 選項完成配置,之後再按 g 鍵確認生成 Makefile 。ccmake 的其他操作可以參考窗口下方給出的指令提示。

下面來看一下config.h文件內容:

USE_MYMATH 為 ON
#define USE_MYMATH

USE_MYMATH 為 OFF
/* #undef USE_MYMATH */

(2)是否加入 MathFunctions 庫

# 是否加入 MathFunctions 庫
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)  
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)

option 命令添加了一個 USE_MYMATH 選項,並且默認值為 ON 。

(3)是否使用自己的 MathFunctions 庫

# 是否使用自己的 MathFunctions 庫
option (USE_MYMATH
      "Use provided math implementation" ON)

根據 USE_MYMATH 變量的值來決定是否使用我們自己編寫的 MathFunctions 庫。

4.安裝和測試4.1 安裝

之前在編譯一些原始碼程序的時候,先make後make install,這樣會把一些頭文件與靜態/動態庫安裝到指定的目錄下。

那在CMAKE中同樣可以這麼做,如下:

首先先在 math/CMakeLists.txt 文件裡添加下面兩行:

 指定 MathFunctions 庫的安裝路徑
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

指明 MathFunctions 庫的安裝路徑。之後同樣修改根目錄的 CMakeLists 文件,在末尾添加下面幾行:

# 指定安裝路徑
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
        DESTINATION include)

通過上面定製,後安裝如下:

light@city:~/cmake-demo/Demo5$ sudo make install
[ 50%] Built target MathFunctions
[100%] Built target Demo
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/Demo
-- Installing: /usr/local/include/config.h
-- Installing: /usr/local/lib/libMathFunctions.a
-- Installing: /usr/local/include/MathFunctions.h

據此完成了安裝工作。

4.2 測試

CMake 提供了一個稱為 CTest 的測試工具。我們要做的只是在項目根目錄的 CMakeLists 文件中調用一系列的 add_test 命令。

啟動測試:

# 啟用測試
enable_testing()

(1)無幫助信息測試

# 測試程序是否成功運行
add_test (test_run Demo 5 2)

(2)有幫助信息測試

# 測試 2 的 10 次方
add_test (test_2_10 Demo 2 10)
set_tests_properties (test_2_10)
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")

其中 PASS_REGULAR_EXPRESSION 用來測試輸出是否包含後面跟著的字符串。

5.支持gdb

讓 CMake 支持 gdb 的設置也很容易,只需要指定 Debug 模式下開啟 -g 選項:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

6.添加版本號

在編寫項目中給項目添加版本號:

set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)

分別指定當前的項目的主版本號和副版本號。

如果想在代碼中獲取信息,可以修改config.h.in文件,添加兩個預定義變量:

// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@

主程序調用,列印:

printf("%s Version %d.%d\n",
       argv[0],
       Demo_VERSION_MAJOR,
       Demo_VERSION_MINOR);

7.生成安裝包

如何配置生成各種平臺上的安裝包,包括二進位安裝包和源碼安裝包。為了完成這個任務,我們需要用到 CPack ,它同樣也是由 CMake 提供的一個工具,專門用於打包。

我們做如下三個工作:

導入 InstallRequiredSystemLibraries 模塊,以便之後導入 CPack 模塊;

設置一些 CPack 相關變量,包括版權資訊和版本信息,其中版本信息用了上一節定義的版本號;

導入 CPack 模塊。

對應CMakeLists.txt如下:

# 構建一個 CPack 安裝包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)

下面就是如何使用:

輸入cpack .,也可以指定二進位與源碼安裝包:

cpack -C CPackConfig.cmake

cpack -C CPackSourceConfig.cmake

cpack安裝:

light@city:~/cmake-demo/Demo8$ cpack -CPackConfig.cmake
CPack: Create package using STGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.sh generated.
CPack: Create package using TGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.tar.gz generated.
CPack: Create package using TZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.tar.Z generated.

此時會在本地目錄下創建3個不同格式的二進位包文件:

light@city:~/cmake-demo/Demo8$ ls Demo8*
Demo8-1.0.1-Linux.sh Demo8-1.0.1-Linux.tar.gz Demo8-1.0.1-Linux.tar.Z

隨便選擇一個安裝,例如sh:

sh Demo8-1.0.1-Linux.sh

使用:

light@city:~/cmake-demo/Demo8$ ./Demo8-1.0.1-Linux/bin/Demo 5 2
Now we use our own Math library.
5 ^ 2 is 25

相關焦點

  • CMake實戰教程(三)
    前言CMake實戰教程(一)CMake實戰教程(二)從本小節開始,後面所有的構建我們都將採用 out-of-source build 外部構建的方式去編寫構建工程代碼,構建目錄是工程目錄下的 build 目錄。
  • CMake入門
    mkdir build && cd buildcmake ..makemake install在這個例子中,我們建了一個 build 文件夾用於執行 cmake 指令,這種做法叫做外部編譯(out-of-source-build)。注意 cmake .. 這後邊有個 .. 這是用於告訴 CMAKE CMakeLists.txt 在哪個文件夾下。
  • CMake實戰教程(二)
    外部構建第一個問題,在運行cmake .後會產生很多垃圾文件,那麼我們可以讓它在一個build目錄下去編譯,生成的垃圾文件放在這個目錄下就好了,不需要的時候直接清除即可。cmake PATH那麼很顯然,它可以是相對路徑而不是絕對路徑,畢竟點『.』  表示當前路徑, 點點『..』 表示上一級路徑,那麼我們可以新建一個build目錄,然後在build目錄下去運行:cmake ..
  • Cmake 入門簡介
    二、 CMake下載安裝下載地址 https://cmake.org/download/window版直接點擊「下一步」安裝完成效果三 CMake基本使用和語法1、 commandcommand (args …)command 是命令名,大小寫無關(注意:變量是大小寫相關的)args 是參數,參數如果有空格,
  • Ubuntu 18.04下安裝最新CMake及CMake簡單使用
    cmake所做的事其實就是告訴編譯器如何去編譯連結原始碼。你也許想問不是有makefile嗎,為什麼還要它?這裡就牽涉到跨平臺問題。在Windows平臺下是通過project文件去管理這些的,如果不用cmake,那我們為Windows和Linux系統就要寫對應的project文件和makefile文件,這無疑是一件繁瑣的事,而我們只要編寫一次cmake,就可以用在各個平臺,而且其語法也簡單。
  • CMake使用入門
    例子cmake_minimum_required(VERSION 3.13)project(HelloWorld)add_library(hello_world STATIC
  • 跨平臺開發編譯必備——CMake入門指南
    << std::endl; return 0;}CMakeLists.txt123456789cmake_minimum_required(VERSION 3.8) project(CmakeHelloWorld)
  • 分享一篇很不錯的CMake入門文章,值得收藏細讀!
    執行命令 cmake PATH 或者 ccmake PATH 生成 Makefile(ccmake 和 cmake 的區別在於前者提供了一個交互式的界面)。其中, PATH 是 CMakeLists.txt 所在的目錄。本文將從實例入手,一步步講解 CMake 的常見用法,文中所有的實例代碼可以在這裡找到。
  • 跨平臺編譯工具-CMake的語法特性與常用變量
    Linux下C++命令行調試實戰1. 概述在不同的作業系統上,我們可以使用不同的編譯工具,比如 windows 中使用 Visual Studio 的開發套件, mac 中使用 xcode 開發套件,Linux 中使用 Makefile 結合 g++ 編譯,那如果我們使用 cmake 就可以解決了跨平臺的問題。
  • cmake簡介
    通過這種方式,cmake實現了跨平臺。關於cmake支持生成的目標構建文件可以參考官方網站3.1 cmake操作介紹cmake有很多種使用方法,比如說命令行,交互式命令行等等。cmake同時也附帶一個用qt寫的圖形界面工具,在windows和linux下都可以使用,本節將著重介紹圖形工具的使用。
  • 基於VSCode和CMake進行C/C++開發「第六講」CMake
    6.2 語法特性介紹6.3 重要指令和CMake常用變量6.3.1 重要指令cmake_minimum_required - 指定CMake的最小版本要求1# CMake最小版本要求為2.8.32cmake_minimum_required(VERSION 2.8.3)
  • CMake環境搭建
    (VERSION 2.8)project(cmake_test)add_executable(${PROJECT_NAME} "main.cpp")1.CMake官網下載https://cmake.org/download/2. linux中安裝CMake環境編譯好的二進位文件安裝直接下載二進位文件直接執行sh解壓     tar -xvf xxxx.tar.gz.
  • 【CMake教程】(五)CMake 配置install打包
    本片教程我們將講述如何在cmake中配置install的打包路徑。下面我們將以mathlib庫和頭文件為例子進行配置。(2)CMake 的使用環境和安裝本教程的使用環境為:ubutu18.04 ltsgcc version 7.5.0g++ version 7.5.0cmake version 3.10.2安裝cmake:sudo apt install cmake(3)設置設置我們的程序輸出為lib文件
  • 安卓ndk開發實戰(1)Android Studio 中配置 ndk 和 cmake 工具
    二、配置 ndk 和 cmake 編譯工具2.1 android studio 安裝配置 ndk 和 cmake 工具打開 Android Studio,依次按照如下圖示操作。圖 3:2.1 查看安裝的 ndk 和 cmake
  • cmake終極奧義
    一、初識cmakecmake集中開源,跨平臺,能夠管理大型項目,簡化編譯構建過程和編譯過程,高效率,可擴展於一體,簡單而強大的項目構建工具二,安裝cmake一般不需要安裝,cmake目前已經成為各大Linux發行版提供的組件,所以,需要自己動手安裝的可能性很小。
  • 黑客入門實戰指南
    文末附黑客工具及學習資料領取說到黑客大家可能覺得很神秘,其實我們說的的黑客是白帽子黑客,就是去尋找網站、系統、軟體等漏洞並幫助廠商修復的人,剛入門的黑客大部分從事滲透工作如果你想入門黑客,但是不知道從何學起,沒有前輩帶路,實時解疑答惑,請往下看我們邀請了挖洞經驗豐富的大佬,打造了一門——《0基礎入門黑客必修實戰課》課程。重要的事情說在前面。本次課程共計7個課時,附帶7個實戰訓練、本公眾號粉絲,限時僅需1元,超級乾貨!千萬不要錯過啦!
  • CMake的安裝及簡單使用
    因此,對於大多數項目,應當考慮使用更自動化一些的 cmake或者autotools來生成makefile,而不是上來就動手編寫。總之,項目構建工具能夠幫我們在不同平臺上更好地組織和管理我們的代碼及其編譯過程,這是我們使用它的主要原因。cmake的主要特點cmake和autotools是不同的項目管理工具,有各自的特點和用戶群。
  • 實用 | 使用Cmake快速生成visual studio工程
    三、CMake安裝 首先需要下載、安裝Windows版本的CMake工具:官網下載連結:https://cmake.org/download/安裝完成之後按Win+r進入運行窗口,輸入cmd後按回車來到命令行,輸入cmake -version命令核實是否安裝成功,出現如下界面說明已經安裝成功:
  • 【CMake教程】(三)CMake 配置指定C++11編譯的標準
    (2)CMake 的使用環境和安裝本教程的使用環境為:ubutu18.04 ltsgcc version 7.5.0g++ version 7.5.0cmake version 3.10.2安裝cmake:sudo apt install cmake(3)CMake指定C++標準  指定C+
  • AndroidNDK——Cmake詳解
    以CMake編寫的源文件以CmakeLists.txt命名或以.cmake為擴展名。可以通過add_subdirectory()命令把子目錄的CMake源文件添加進來。CMake源文件中所有有效的語句都是命令,可以是內置命令或自定義的函數/宏命令。