現代 CMake 簡明教程 CMake 基礎

2021-10-25 15:26:40 字數 4032 閱讀 9055

用 cmake 來構建 c/c++ 專案是業內的主流做法。最近,我們的專案**做了一些拆分和合併:引入其他倉庫**,並且將公共部分拆分以供多個倉庫同時使用。為此,就得修改專案中的 cmake 以滿足需求。

在做這件事情時,過程是相當痛苦的,修改的難度超過了我的預期。這份痛苦的回憶,讓我陷入了沉思:這 cmake 咋這麼不好使,是我的使用姿勢不對嗎?cmake 的最佳實踐是啥?

在經過一番搜尋和學習,我開始了解 modern cmake 的一些用法與理念,它主張放棄傳統的基於變數的方法,而採用基於 target 的結構化模式,使其成為乙個更可維護、更直觀、更易整合、更具意義的方案。

在這裡對自己的學習做乙個總結,主要內容包括:

介紹 modern cmake 的基礎語法與工具,讓你對 cmake 能做些啥有更清楚的認識

介紹 modern cmake 理念與最佳實踐,並給出具體例項

這部分內容是 an introduction to modern cmake 的總結,並不會講的非常詳細,希望通過幾句話來高度總結各個用法,旨在了解 cmake 有哪能力,如果對某些部分感興趣請大家自行查閱具體內容。

為什麼一定是 cmake?其他工具不行嗎?

為什麼要用現代 cmake?

macos

linux

設定cccxx環境變數來選擇 c/c++ 編譯器

~/package/build $ cc=clang cxx=clang++ cmake ..

選擇不同的工具進行構建

通過-d來設定選項,例如cmake -s . -b build -dcmake_install_prefix=dist

--trace列印 cmake configure 階段的輸出,例如cmake -s . -b build --trace

良好的 cmake 用法

project

project(myproject version 1.0

description "very nice project"

languages cxx)

生成可執行檔案

add_executable(one two.cpp three.h)

生成庫

add_library(one static two.cpp three.h)

給 target 新增屬性

# public 表示外部也需要這個 include 目錄

target_include_directories(one public include)

add_library(another static another.cpp another.h)

# 由於具有傳遞性,another 可以連線 one 的 include 目錄

target_link_libraries(another public one)

快取變數

關於區域性變數與緩衝變數的示例,請參考 cmake-變數和全域性變數快取

屬性

if(variable)

# if variable is `on`, `yes`, `true`, `y`, or non zero number

else()

# if variable is `0`, `off`, `no`, `false`, `n`, `ignore`, `notfound`, `""`, or ends in `- notfound`

endif()

# if variable does not expand to one of the above, cmake will expand it then try again

if(not target liba or exists "test.xml")

# if liba or test.xml exist

endif()

生成器表示式, generator-expressions

target_include_directories(mytarget 

public

$$)

巨集與函式

引數。可以通過cmake_parse_arguments來解析函式引數

- project

- .gitignore

- readme.md

- licence.md

- cmakelists.txt

- cmake

- findsomelib.cmake

- something_else.cmake

- include

- project

- lib.hpp

- src

- cmakelists.txt

- lib.cpp

- cmakelists.txt

- tests

- cmakelists.txt

- testlib.cpp

- docs

- cmakelists.txt

- extern

- googletest

- scripts

- helper.py

find_package(git quiet)

if(git_found and exists "$/.git")

execute_process(command $ submodule update --init --recursive

working_directory $

result_variable git_submod_result)

if(not git_submod_result equal "0")

message(fatal_error "git submodule update --init failed with $, please checkout submodules")

endif()

endif()

在 build 階段執行命令

find_package(pythoninterp required)

add_custom_command(output "$/include/generated.hpp"

command "$" "$/scripts/generateheader.py" --argument

depends some_target)

add_custom_target(generate_header all

depends "$/include/generated.hpp")

install(files $/include/generated.hpp destination include)

cmake -e執行內建的一些命令,例如解壓、複製等,具體參看 run a command-line tool

cmake 3.1+: 全域性和屬性設定

全域性變數設定

set(cmake_cxx_standard 11)

set(cmake_cxx_standard_required on)

set(cmake_cxx_extensions off)

小型庫interprocedural optimization,執行時優化(link time optimization),即-flto

在 cmake 中可以配合其他工具

cmake modules 非常有用,簡單介紹一些常用的

除錯 cmake **

介紹了引入 cuda、openmp、boost、mpi、root、minuit2 等庫的標準姿勢

Visual Unit 簡明教程

visual unit,簡稱vu,是新一代單元測試工具,功能強大,使用簡單,完全視覺化,不需編寫測試 vu的測試結果使程式行為一目了然,有助於整理程式設計思路,提高程式設計效率和正確性,並能快速排錯 vu還增強偵錯程式功能 如自由後退 用例切換 提高除錯的效率 vu能達到空前的測試完整性,輕鬆完成語...

MYSQL簡明教程

dos進入mysql命令 c mysql h 127.0.0.1 u root p enter password mysql 進入完成 建立資料庫 create database databasename 使用指定資料庫進行操作 方法1 use database databasename 方法2 m...

Struts Hibernate簡明教程

jboss 資助的開源專案,當前比較流行的持久層框架,是一種先進的 jdbc 封裝框架。優點 提高了資料訪問層的開發效率,使我們不必直接呼叫 jdbc 來訪問關係型資料庫。hibernate 建立在物件導向的基礎之上,開發人員只需針對物件進行操作,不必再關心資料庫的連線關閉,sql的執行,以及 re...