那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CMake的實(shí)戰(zhàn)教程-3

汽車電子技術(shù) ? 來源:物聯(lián)網(wǎng)IoT開發(fā) ? 作者:杰杰mcu ? 2023-02-14 10:45 ? 次閱讀

前言

CMake實(shí)戰(zhàn)教程(一)

CMake實(shí)戰(zhàn)教程(二)

從本小節(jié)開始,后面所有的構(gòu)建我們都將采用 out-of-source build 外部構(gòu)建的方式去編寫構(gòu)建工程代碼,構(gòu)建目錄是工程目錄下的 build 目錄。

從上一篇文章我們就知道,通過aux_source_directory命令可以掃描某個(gè)目錄下的所有源碼,但是更深一層的目錄源碼就找不到了,因此不滿足我們真正工程項(xiàng)目的需要,畢竟真的工程會(huì)有很多個(gè)目錄的,這些目錄在的地方還不一樣,現(xiàn)在就來解決這個(gè)問題…

定個(gè)小目標(biāo)

  • CMake自動(dòng)構(gòu)建多個(gè)源碼目錄下的工程

實(shí)現(xiàn)

首先,起碼工程中得有多個(gè)目錄對(duì)吧,按照編程習(xí)慣,我喜歡把源碼放到 src 目錄下,把頭文件放到 inc 目錄下,那么把上一篇文章的代碼分離放開,具體如下:

jie@pc:~/github/cmake/section4$ tree
.
├── build.sh
├── CMakeLists.txt
├── inc
│   └── power.h
├── main.c
└── power
    ├── CMakeLists.txt
    └── power.c

2 directories, 6 files

很顯然,從上面的目錄結(jié)構(gòu)中可以看出,有兩個(gè)CMakeLists.txt文件,一個(gè)是在根目錄下,一個(gè)是在src目錄下:

./CMakeLists.txt
./src/CMakeLists.txt

其實(shí)無論在何處,CMakeLists.txt文件都可以被 CMake 命令識(shí)別并且自動(dòng)構(gòu)建,但是,我們自動(dòng)構(gòu)建的時(shí)候,都會(huì)有一個(gè)頂層目錄CMakeLists.txt文件,它就是cmake的入口文件,而在頂層目錄下,如果某些子目錄中存在CMakeLists.txt文件,那么 CMake 可以將頂層的環(huán)境變量傳遞到子目錄下,就好比,你在某個(gè)文件中定義了個(gè)全局變量,你在那個(gè)文件中的子函數(shù)都可以使用這個(gè)全局變量,有點(diǎn)類似的道理,說白了就是作用域。。。

添加子目錄

那么為了能讓 CMake 去識(shí)別到src目錄下的./src/CMakeLists.txt文件,我們可以在頂層./CMakeLists.txt文件添加一個(gè)子目錄,用以下這個(gè)命令:

add_subdirectory(source_dir [binary_dir]
                [EXCLUDE_FROM_ALL])

add_subdirectory 這條命令的作用是為構(gòu)建添加一個(gè)子路徑。

  • source_dir 選項(xiàng)指定了 CMakeLists.txt 源文件和代碼文件的位置。如果 source_dir 是一個(gè)相對(duì)路徑,那么 source_dir 選項(xiàng)會(huì)被解釋為相對(duì)于當(dāng)前的目錄,不過它也可以是一個(gè)絕對(duì)路徑。在 source_dir 指定路徑下的 CMakeLists.txt 將會(huì)在當(dāng)前輸入文件的處理過程執(zhí)行到該命令之前,立即被 CMake 處理。
  • binary_dir 選項(xiàng)指定了輸出文件的路徑,同樣的, binary_dir 可以相對(duì)路徑,也可以是一個(gè)絕對(duì)路徑。不過杰杰目前暫未使用到binary_dir,感興趣的兄弟姐妹可以自己去了解它。
  • 如果指定了 EXCLUDE_FROM_ALL 選項(xiàng),在子路徑下的目標(biāo)默認(rèn)不會(huì)被包含到父路徑的 ALL 目標(biāo)里,并且也會(huì)被排除在工程文件之外,用戶必須顯式構(gòu)建在子路徑下的目標(biāo)。

添加路徑

include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)

同理可以使用include_directories命令將給定的路徑添加到編譯器搜索包含文件(.h 文件)的路徑列表中,這是為了讓編譯器找到合適的頭文件。如果指定了 SYSTEM 選項(xiàng),編譯器將會(huì)認(rèn)為該路徑是某種平臺(tái)上的系統(tǒng)包含路徑。

遍歷

在cmake中,很多變量都是以列表的形式存在,比如上面的兩個(gè)命令,添加頭文件與添加子目錄,我們可以用列表的形式添加進(jìn)去,比如include_directories(dir1 dir2 dir3),那么這些dir,那么cmake也提供了遍歷這些列表的方法,這與C語言中的for循環(huán)都差不多,可以使用以下命令去遍歷它:

foreach(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endforeach(loop_var)

注意,這個(gè)命令需要配合 endforeach 命令使用,endforeach 表示結(jié)束遍歷

所有的 foreach 和與之匹配的 endforeach 命令之間的命令,會(huì)根據(jù)list的每個(gè)變量都執(zhí)行一遍,在每次迭代中,循環(huán)變量${loop_var}將會(huì)被設(shè)置為 list 中的當(dāng)前變量值。

為了演示,我就將foreach命令去變量指定的INCDIRS(雖然只有一個(gè)變量,不過不影響演示),把INCDIRS列表的內(nèi)容一個(gè)個(gè)添加到路徑中:

### 頭文件
set(INCDIRS "inc")

# 添加頭文件目錄
foreach(incdir ${INCDIRS})
    include_directories(${incdir})
endforeach()

當(dāng)然,我在這提到遍歷并不是因?yàn)楸仨氁褂眠@個(gè)命令,而是為后續(xù)的文章做鋪墊。

構(gòu)建庫

如果一個(gè)工程中有非常多的源碼,那么總不能將所有的源碼都使用add_executable命令去生成可執(zhí)行文件是不是,我們可以讓這個(gè)可執(zhí)行文件去依賴庫,靜態(tài)庫,動(dòng)態(tài)庫都可以,那么在這里就簡單說說add_executable命令依賴靜態(tài)庫生成可執(zhí)行文件,那么問題來了,靜態(tài)庫從哪來?

很顯然,靜態(tài)庫是我們的一些源碼文件生成的,在生成靜態(tài)庫后,再通過靜態(tài)庫去構(gòu)建可執(zhí)行文件,那么就用到了CMake中的add_library命令:

add_library( [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 source2 ... sourceN)

它的作用就是使用指定的源文件向工程中添加一個(gè)庫。添加一個(gè)名為的庫文件,在一個(gè)工程的全局域內(nèi)必須是唯一的,這個(gè)庫文件將會(huì)根據(jù)命令里列出的源文件(source1 source2 ... sourceN)來創(chuàng)建。待構(gòu)建的庫文件的實(shí)際文件名根據(jù)對(duì)應(yīng)平臺(tái)的命名約定來構(gòu)造(比如 可以是lib.a 或者.lib)。通過指定STATICSHARED,或者 MODULE 參數(shù)用來指定要?jiǎng)?chuàng)建的庫的類型。

  • STATIC 庫是目標(biāo)文件的歸檔文件,在鏈接其它目標(biāo)的時(shí)候使用。
  • SHARED 庫會(huì)被動(dòng)態(tài)鏈接,在運(yùn)行時(shí)被加載。
  • MODULE 庫是不會(huì)被鏈接到其它目標(biāo)中的插件,但是可能會(huì)在運(yùn)行時(shí)使用 dlopen-系列的函數(shù)動(dòng)態(tài)鏈接。如果沒有類型被顯式指定,這個(gè)選項(xiàng)將會(huì)根據(jù)變量 BUILD_SHARED_LIBS 的當(dāng)前值是否為真決定是 STATIC 還是 SHARED
# 查找當(dāng)前目錄下的所有源文件
# 并將名稱保存到 DIR_LIB_SRCS 變量
file(GLOB_RECURSE DIR_LIB_SRCS *.c)
file(GLOB_RECURSE DIR_LIB_HDRS *.h)

### 生成鏈接庫
add_library(${LIB_NAME} ${DIR_LIB_SRCS} ${DIR_LIB_HDRS})

當(dāng)然,為了我們的CMakeLists.txt文件有更好的兼容性,也不必每次都去寫對(duì)應(yīng)的庫文件名字,杰杰自己會(huì)使用正則表達(dá)式去解析當(dāng)前目錄的名字,并以這個(gè)目錄名字去作為庫的命名,正則表達(dá)式如下:

# 正則表達(dá)式得到當(dāng)前目錄名字作為提供給上一層的庫名字
string(REGEX REPLACE ".*/(.*)" "\\\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR})

工程demo

頂層./CMakeLists.txt文件內(nèi)容:

# CMake 最低版本號(hào)要求
cmake_minimum_required(VERSION 2.8)

# 項(xiàng)目信息
project(targets)

# 設(shè)置可執(zhí)行文件目標(biāo)
set(TARGETS "targets")

# 子目錄
set(SUBDIRS "power")

# 頭文件
set(INCDIRS "inc")

# 指定編譯器
set(CMAKE_C_COMPILER "gcc")

#判斷編譯器類型,如果是gcc編譯器,則在編譯選項(xiàng)中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
endif(CMAKE_COMPILER_IS_GNUCXX)

#指定編譯類型
SET(CMAKE_BUILE_TYPE "RELEASE")

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

# 指定生成目標(biāo)
add_executable(${TARGETS} ${DIR_SRCS})

# 添加頭文件目錄
foreach(incdir ${INCDIRS})
    include_directories(${incdir})
endforeach()


# 添加子目錄
foreach(subdir ${SUBDIRS})
    add_subdirectory(${subdir})
endforeach()

# 添加鏈接庫
target_link_libraries(${TARGETS} ${SUBDIRS})

src目錄下的./src/CMakeLists.txt文件內(nèi)容:

# 查找當(dāng)前目錄下的所有源文件
# 并將名稱保存到 DIR_LIB_SRCS 變量
file(GLOB_RECURSE DIR_LIB_SRCS *.c)
file(GLOB_RECURSE DIR_LIB_HDRS *.h)

# 正則表達(dá)式得到當(dāng)前目錄名字作為提供給上一層的庫名字
string(REGEX REPLACE ".*/(.*)" "\\\\1" LIB_NAME ${CMAKE_CURRENT_SOURCE_DIR}) 

# 生成鏈接庫
add_library(${LIB_NAME} ${DIR_LIB_SRCS} ${DIR_LIB_HDRS})

最后直接運(yùn)行./build去構(gòu)建工程與編譯工程即可

代碼下載

https://github.com/jiejieTop/cmake

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    652

    瀏覽量

    29454
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4827

    瀏覽量

    69054
  • Build
    +關(guān)注

    關(guān)注

    0

    文章

    26

    瀏覽量

    12086
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    cmake是什么?cmake的特性和編譯原理(cmake原理和cmake編譯過程)

    CMake是一個(gè)開源、跨平臺(tái)的工具系列,是用來構(gòu)建、測試和打包軟件。
    的頭像 發(fā)表于 07-18 10:53 ?4842次閱讀
    <b class='flag-5'>cmake</b>是什么?<b class='flag-5'>cmake</b>的特性和編譯原理(<b class='flag-5'>cmake</b>原理和<b class='flag-5'>cmake</b>編譯過程)

    3. CMake 中 set 的使用 - 上___CMake 保姆級(jí)教程【C_C++】

    CMake
    jf_97106930
    發(fā)布于 :2023年05月18日 15:39:48

    CMake 入門實(shí)戰(zhàn)

    CMake 入門實(shí)戰(zhàn),,
    發(fā)表于 09-28 12:38

    交叉平臺(tái)開源編譯系統(tǒng)_cmake入門

    交叉平臺(tái)開源編譯系統(tǒng)_cmake入門
    發(fā)表于 01-22 13:59 ?9次下載

    Cmake學(xué)習(xí)的總結(jié)(二)

    大家好,上次給大家分享了第一篇 cmake 文章:cmake學(xué)習(xí)總結(jié)(一),今天繼續(xù)給大家分享cmake。那么廢話就不多說,開始內(nèi)容分享。
    的頭像 發(fā)表于 12-24 17:54 ?676次閱讀

    cmake管理配置ROOT項(xiàng)目的方法

    Qtcreator打開cmake項(xiàng)目時(shí)生成的用戶緩存文件,可忽略 3 CMakeLists.txt.user.4825354 ? 某個(gè)緩存文件的版本,可忽略 4 helloworld.h 頭文件 5 helloworld.
    的頭像 發(fā)表于 01-18 17:45 ?4699次閱讀
    <b class='flag-5'>cmake</b>管理配置ROOT項(xiàng)目的方法

    如何使用CMake工具套件構(gòu)建CUDA應(yīng)用程序

    我希望這篇文章向您展示了 CMake 如何自然地支持構(gòu)建 CUDA 應(yīng)用程序。如果您是 CMake 的現(xiàn)有用戶,請(qǐng)?jiān)囉?CMake 3 . 9 并利用改進(jìn)的 CUDA 支持。如果您不是
    的頭像 發(fā)表于 04-01 17:42 ?4644次閱讀
    如何使用<b class='flag-5'>CMake</b>工具套件構(gòu)建CUDA應(yīng)用程序

    RT-Thread V4.1.0新特性CMake介紹與構(gòu)建CMake工程

    ? ? CMake 支持 在 RT-Thread 4.1.0 正式發(fā)布版中,添加了對(duì) CMake 的支持。開發(fā)者可以使用 SCons 工具來生成 CMakeLists.txt 文件。 為何要支持
    的頭像 發(fā)表于 05-24 19:20 ?3087次閱讀

    RT-Thread 4.1.0的CMake構(gòu)建教程

    CMake 支持 在 RT-Thread 4.1.0 正式發(fā)布版中,添加了對(duì) CMake 的支持。開發(fā)者可以使用 SCons 工具來生成 CMakeLists.txt 文件。 為何要支持 CMake
    的頭像 發(fā)表于 05-25 11:06 ?3440次閱讀

    CMake用法詳解

    CMake用法詳解
    發(fā)表于 10-25 16:28 ?2次下載

    CMake實(shí)戰(zhàn)教程-1

    CMake 是一個(gè)跨平臺(tái)的構(gòu)建系統(tǒng)生成工具。它使用平臺(tái)無關(guān)的 CMake 清單文件CMakeLists.txt,指定工程的構(gòu)建過程;源碼樹的每個(gè)路徑下都有這個(gè)文件。CMake 產(chǎn)生一個(gè)適用于具體平臺(tái)的構(gòu)建系統(tǒng),用戶使用這個(gè)系統(tǒng)構(gòu)
    的頭像 發(fā)表于 02-14 10:42 ?746次閱讀
    <b class='flag-5'>CMake</b>的<b class='flag-5'>實(shí)戰(zhàn)</b>教程-1

    CMake實(shí)戰(zhàn)教程-2

    第一個(gè)問題,在運(yùn)行`cmake .`后會(huì)產(chǎn)生很多垃圾文件,那么我們可以讓它在一個(gè)build目錄下去編譯,生成的垃圾文件放在這個(gè)目錄下就好了,不需要的時(shí)候直接清除即可。
    的頭像 發(fā)表于 02-14 10:43 ?720次閱讀

    CMake實(shí)戰(zhàn)教程-2

    第一個(gè)問題,在運(yùn)行`cmake .`后會(huì)產(chǎn)生很多垃圾文件,那么我們可以讓它在一個(gè)build目錄下去編譯,生成的垃圾文件放在這個(gè)目錄下就好了,不需要的時(shí)候直接清除即可。
    的頭像 發(fā)表于 02-28 16:18 ?804次閱讀

    在Linux下如何使用CMake編譯程序

    CMake是開源、跨平臺(tái)的構(gòu)建工具,可以讓我們通過編寫簡單的配置文件去生成本地的Makefile,這個(gè)配置文件是獨(dú)立于運(yùn)行平臺(tái)和編譯器的,這樣就不用親自去編寫Makefile了,而且配置文件可以直接
    的頭像 發(fā)表于 11-08 16:15 ?6666次閱讀
    在Linux下如何使用<b class='flag-5'>CMake</b>編譯程序

    CMake構(gòu)建后的項(xiàng)目結(jié)構(gòu)解析

    一、 CMake構(gòu)建后的項(xiàng)目結(jié)構(gòu)解析(Analysis of the Project Structure After CMake Build) 1.1 CMake構(gòu)建后的目錄結(jié)構(gòu)(Directory
    的頭像 發(fā)表于 11-10 10:27 ?2237次閱讀
    <b class='flag-5'>CMake</b>構(gòu)建后的項(xiàng)目結(jié)構(gòu)解析
    百家乐官网赢钱打| 大发888设置| 百家乐官网投注平台信誉排行| 威尼斯人娱乐最新地址| 路单百家乐官网的玩法技巧和规则 | 南通棋牌游戏中心下载| 百家乐官网真人游戏| 澳门赌场老板| 缅甸百家乐娱乐| 百家乐官网游戏机说明书| 大发888游戏平台下载| 风水学中的24向是什么| 环球百家乐官网现金网| 同乐城百家乐娱乐城| 利博百家乐官网的玩法技巧和规则| 伽师县| 网上百家乐试玩网址| 百家乐九| 属蛇做生意坐向| 百家乐官网庄闲点数| 大发888怎么下载| 百家乐公式计算| 百家乐官网翻天qvod| 手机棋牌游戏| 玩百家乐五湖四海娱乐城| 百家乐官网桌码合| KK娱乐城| 百家乐官网的出牌技巧| 博士娱乐| 威尼斯人娱乐官方| 澳门百家乐单注下限| 百家乐官网gamble| 喜达国际| 悍马百家乐的玩法技巧和规则| 鑫鑫百家乐官网的玩法技巧和规则 | 专业的百家乐玩家| 属鼠做生意办公桌摆貔貅好不好 | 亿酷棋牌世界下载| 百家乐透明牌靴| 红宝石百家乐官网的玩法技巧和规则 | bet365娱乐城注册|