日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【Tools】cmake 常用变量和常用环境变量查表手册---整理

發(fā)布時(shí)間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Tools】cmake 常用变量和常用环境变量查表手册---整理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文鏈接:https://blog.csdn.net/gubenpeiyuan/article/details/8667279

一.cmake 變量引用的方式:

前面我們已經(jīng)提到了,使用${}進(jìn)行變量的引用。在IF等語(yǔ)句中,是直接使用變量名而不通過(guò)${}取值.


二.cmake 自定義變量的方式:

主要有隱式定義和顯式定義兩種,前面舉了一個(gè)隱式定義的例子,就是 PROJECT 指令,他會(huì)隱式的定義<projectname>_BINARY_DIR 和<projectname>_SOURCE_DIR 兩個(gè)變量。
顯式定義的例子我們前面也提到了,使用 SET 指令,就可以構(gòu)建一個(gè)自定義變量了。
比如:
SET(HELLO_SRC main.SOURCE_PATHc),就 PROJECT_BINARY_DIR 可以通過(guò)${HELLO_SRC}來(lái)引用這個(gè)自定義變量了.


三.cmake 常用變量:

  • 1.工程頂層目錄、工程編譯發(fā)生的目錄
    CMAKE_BINARY_DIR
    PROJECT_BINARY_DIR
    <projectname>_BINARY_DIR
    這三個(gè)變量指代的內(nèi)容是一致的,如果是 in source 編譯,指得就是工程頂層目錄,如果是 out-of-source 編譯,指的是工程編譯發(fā)生的目錄。PROJECT_BINARY_DIR 跟其他指令稍有區(qū)別,現(xiàn)在,你可以理解為他們是一致的。

  • 2.工程頂層目錄
    CMAKE_SOURCE_DIR
    PROJECT_SOURCE_DIR
    <projectname>_SOURCE_DIR
    這三個(gè)變量指代的內(nèi)容是一致的,不論采用何種編譯方式,都是工程頂層目錄。
    也就是在 in source 編譯時(shí),他跟 CMAKE_BINARY_DIR 等變量一致。
    PROJECT_SOURCE_DIR 跟其他指令稍有區(qū)別,現(xiàn)在,你可以理解為他們是一致的。

  • 3.CMAKE_CURRENT_SOURCE_DIR
    指的是當(dāng)前處理的 CMakeLists.txt 所在的路徑,比如上面我們提到的 src 子目錄。

  • 4.CMAKE_CURRRENT_BINARY_DIR
    如果是 in-source 編譯,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 編譯,他指的是 target 編譯目錄。
    使用我們上面提到的 ADD_SUBDIRECTORY(src bin)可以更改這個(gè)變量的值。
    使用 SET(EXECUTABLE_OUTPUT_PATH <新路徑>)并不會(huì)對(duì)這個(gè)變量造成影響,它僅僅修改了最終目標(biāo)文件存放的路徑。

  • 5.CMAKE_CURRENT_LIST_FILE
    輸出調(diào)用這個(gè)變量的 CMakeLists.txt 的完整路徑

  • 6.CMAKE_CURRENT_LIST_LINE
    輸出這個(gè)變量所在的行

  • 7.CMAKE_MODULE_PATH
    這個(gè)變量用來(lái)定義自己的 cmake 模塊所在的路徑。如果你的工程比較復(fù)雜,有可能會(huì)自己編寫(xiě)一些 cmake 模塊,這些 cmake 模塊是隨你的工程發(fā)布的,為了讓 cmake 在處理CMakeLists.txt 時(shí)找到這些模塊,你需要通過(guò) SET 指令,將自己的cmake模塊路徑設(shè)置一下。
    比如
    SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
    這時(shí)候你就可以通過(guò) INCLUDE 指令來(lái)調(diào)用自己的模塊了。

  • 8.EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH
    分別用來(lái)重新定義最終結(jié)果的存放目錄,前面我們已經(jīng)提到了這兩個(gè)變量。

  • 9.PROJECT_NAME
    返回通過(guò) PROJECT 指令定義的項(xiàng)目名稱(chēng)。


四.cmake 調(diào)用環(huán)境變量的方式

使用$ENV{NAME}指令就可以調(diào)用系統(tǒng)的環(huán)境變量了。
比如
MESSAGE(STATUS “HOME dir: $ENV{HOME}”)
設(shè)置環(huán)境變量的方式是:
SET(ENV{變量名} 值)

  • 1.CMAKE_INCLUDE_CURRENT_DIR
    自動(dòng)添加 CMAKE_CURRENT_BINARY_DIR和 CMAKE_CURRENT_SOURCE_DIR 到當(dāng)前處理
    的 CMakeLists.txt。相當(dāng)于在每個(gè)CMakeLists.txt加入:
    INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

  • 2.CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
    將工程提供的頭文件目錄始終至于系統(tǒng)頭文件目錄的前面,當(dāng)你定義的頭文件確實(shí)跟系統(tǒng)發(fā)生沖突時(shí)可以提供一些幫助。

  • 3.CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH我們?cè)谏弦还?jié)已經(jīng)提及。


五.系統(tǒng)信息

  • CMAKE_MAJOR_VERSION,CMAKE 主版本號(hào),比如 2.4.6 中的 2
  • 2.CMAKE_MINOR_VERSION,CMAKE 次版本號(hào),比如 2.4.6 中的 4
  • 3.CMAKE_PATCH_VERSION,CMAKE 補(bǔ)丁等級(jí),比如 2.4.6 中的 6
  • 4.CMAKE_SYSTEM,系統(tǒng)名稱(chēng),比如 Linux-2.6.22
  • 5.CMAKE_SYSTEM_NAME,不包含版本的系統(tǒng)名,比如 Linux
  • 6.CMAKE_SYSTEM_VERSION,系統(tǒng)版本,比如 2.6.22
  • 7.CMAKE_SYSTEM_PROCESSOR,處理器名稱(chēng),比如 i686.
  • 8.UNIX,在所有的類(lèi) UNIX 平臺(tái)為 TRUE,包括 OS X 和 cygwin
  • 9.WIN32,在所有的 win32 平臺(tái)為 TRUE,包括 cygwin

六.主要的開(kāi)關(guān)選項(xiàng):

  • 1.CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS,用來(lái)控制 IF ELSE 語(yǔ)句的書(shū)寫(xiě)方式,在
    下一節(jié)語(yǔ)法部分會(huì)講到。
  • 2.BUILD_SHARED_LIBS
    這個(gè)開(kāi)關(guān)用來(lái)控制默認(rèn)的庫(kù)編譯方式,如果不進(jìn)行設(shè)置,使用 ADD_LIBRARY并沒(méi)有指定庫(kù)
    類(lèi)型的情況下,默認(rèn)編譯生成的庫(kù)都是靜態(tài)庫(kù)。
    如果 SET(BUILD_SHARED_LIBS ON)后,默認(rèn)生成的為動(dòng)態(tài)庫(kù)。
  • 3.CMAKE_C_FLAGS
    設(shè)置C編譯選項(xiàng),也可以通過(guò)指令 ADD_DEFINITIONS()添加。
  • 4.CMAKE_CXX_FLAGS
    設(shè)置C++編譯選項(xiàng),也可以通過(guò)指令A(yù)DD_DEFINITIONS()添加。
    小結(jié):
    本章介紹了一些較常用的 cmake 變量,這些變量?jī)H僅是所有 cmake 變量的很少一部分,目
    前 cmake 的英文文檔也是比較缺乏的,如果需要了解更多的 cmake 變量,更好的方式是閱
    讀一些成功項(xiàng)目的 cmake 工程文件,比如 KDE4 的代碼。

八.cmake 常用指令

前面我們講到了 cmake 常用的變量,相信“cmake 即編程”的感覺(jué)會(huì)越來(lái)越明顯,無(wú)論如何,我們?nèi)匀豢梢钥吹?cmake 比 autotools 要簡(jiǎn)單很多。接下來(lái)我們就要集中的看一看cmake 所提供的常用指令。在前面的章節(jié)我們已經(jīng)討論了很多指令的用法,如
PROJECT,ADD_EXECUTABLE,INSTALL,ADD_SUBDIRECTORY,SUBDIRS,
INCLUDE_DIRECTORIES,LINK_DIRECTORIES,TARGET_LINK_LIBRARIES,SET 等。
本節(jié)會(huì)引入更多的 cmake 指令,為了編寫(xiě)的方便,我們將按照 cmake man page的順序來(lái)介紹各種指令,不再推薦使用的指令將不再介紹,INSTALL 系列指令在安裝部分已經(jīng)做了非常詳細(xì)的說(shuō)明,本節(jié)也不在提及。(你可以將本章理解成選擇性翻譯,但是會(huì)加入更多的個(gè)人理解)

8.1.基本指令
  • 1.ADD_DEFINITIONS
    向 C/C++編譯器添加-D 定義,比如:
    ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),參數(shù)之間用空格分割。
    如果你的代碼中定義了#ifdef ENABLE_DEBUG #endif,這個(gè)代碼塊就會(huì)生效。
    如果要添加其他的編譯器開(kāi)關(guān),可以通過(guò) CMAKE_C_FLAGS 變量和 CMAKE_CXX_FLAGS 變量設(shè)置。

  • 2.ADD_DEPENDENCIES
    定義 target 依賴(lài)的其他 target,確保在編譯本 target 之前,其他的 target 已經(jīng)被構(gòu)建。
    ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)

  • 3.ADD_EXECUTABLE、ADD_LIBRARY、ADD_SUBDIRECTORY 前面已經(jīng)介紹過(guò)了,這里不再羅唆。

  • 4.ADD_TEST 與 ENABLE_TESTING 指令。
    ENABLE_TESTING 指令用來(lái)控制 Makefile 是否構(gòu)建 test 目標(biāo),涉及工程所有目錄。語(yǔ)法很簡(jiǎn)單,沒(méi)有任何參數(shù),ENABLE_TESTING(),一般情況這個(gè)指令放在工程的主CMakeLists.txt 中.

ADD_TEST 指令的語(yǔ)法是:
ADD_TEST(testname Exename arg1 arg2 ...)
testname 是自定義的 test 名稱(chēng),Exename 可以是構(gòu)建的目標(biāo)文件也可以是外部腳本等等。后面連接傳遞給可執(zhí)行文件的參數(shù)。如果沒(méi)有在同一個(gè) CMakeLists.txt 中打開(kāi)ENABLE_TESTING()指令,任何 ADD_TEST都是無(wú)效的。
比如我們前面的 Helloworld 例子,可以在工程主 CMakeLists.txt 中添加
ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING()
生成 Makefile 后,就可以運(yùn)行 make test來(lái)執(zhí)行測(cè)試了。

  • 5.AUX_SOURCE_DIRECTORY
    基本語(yǔ)法是:
    AUX_SOURCE_DIRECTORY(dir VARIABLE)
    作用是發(fā)現(xiàn)一個(gè)目錄下所有的源代碼文件并將列表存儲(chǔ)在一個(gè)變量中,這個(gè)指令臨時(shí)被用來(lái)自動(dòng)構(gòu)建源文件列表。因?yàn)槟壳?cmake 還不能自動(dòng)發(fā)現(xiàn)新添加的源文件。
    比如
    AUX_SOURCE_DIRECTORY(. SRC_LIST)
    ADD_EXECUTABLE(main ${SRC_LIST})
    你也可以通過(guò)后面提到的 FOREACH 指令來(lái)處理這個(gè) LIST

  • 6.CMAKE_MINIMUM_REQUIRED
    其語(yǔ)法為 CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])
    比如 CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)
    如果 cmake 版本小與 2.5,則出現(xiàn)嚴(yán)重錯(cuò)誤,整個(gè)過(guò)程中止。

  • 7.EXEC_PROGRAM
    在 CMakeLists.txt 處理過(guò)程中執(zhí)行命令,并不會(huì)在生成的 Makefile 中執(zhí)行。

具體語(yǔ)法為:

EXEC_PROGRAM(Executable [directory in which to run][ARGS <arguments to executable>][OUTPUT_VARIABLE <var>][RETURN_VALUE <var>])

用于在指定的目錄運(yùn)行某個(gè)程序,通過(guò) ARGS 添加參數(shù),如果要獲取輸出和返回值,可通過(guò)OUTPUT_VARIABLE 和 RETURN_VALUE 分別定義兩個(gè)變量.

這個(gè)指令可以幫助你在 CMakeLists.txt 處理過(guò)程中支持任何命令,比如根據(jù)系統(tǒng)情況去修改代碼文件等等。
舉個(gè)簡(jiǎn)單的例子,我們要在 src 目錄執(zhí)行 ls 命令,并把結(jié)果和返回值存下來(lái)。
可以直接在 src/CMakeLists.txt 中添加:

EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE) IF(not LS_RVALUE) MESSAGE(STATUS "ls result: " ${LS_OUTPUT}) ENDIF(not LS_RVALUE)

在 cmake 生成 Makefile 的過(guò)程中,就會(huì)執(zhí)行 ls 命令,如果返回 0,則說(shuō)明成功執(zhí)行,那么就輸出ls *.c的結(jié)果。關(guān)于IF 語(yǔ)句,后面的控制指令會(huì)提到。

  • 8.FILE 指令
    文件操作指令,基本語(yǔ)法為:
FILE(WRITE filename "message to write"... ) FILE(APPEND filename "message to write"... ) FILE(READ filename variable) FILE(GLOB variable [RELATIVE path] [globbing expression_r_rs]...) FILE(GLOB_RECURSE variable [RELATIVE path] [globbing expression_r_rs]...) FILE(REMOVE [directory]...) FILE(REMOVE_RECURSE [directory]...) FILE(MAKE_DIRECTORY [directory]...) FILE(RELATIVE_PATH variable directory file) FILE(TO_CMAKE_PATH path result) FILE(TO_NATIVE_PATH path result)

這里的語(yǔ)法都比較簡(jiǎn)單,不再展開(kāi)介紹了,可參考這篇博客https://blog.csdn.net/gubenpeiyuan/article/details/51098116。

  • 9.INCLUDE 指令,用來(lái)載入 CMakeLists.txt 文件,也用于載入預(yù)定義的 cmake 模塊.
    INCLUDE(file1 [OPTIONAL])
    INCLUDE(module [OPTIONAL])
    [OPTIONAL] 參數(shù)的作用是文件不存在也不會(huì)產(chǎn)生錯(cuò)誤。
    你可以指定載入一個(gè)文件,如果定義的是一個(gè)模塊,那么將在CMAKE_MODULE_PATH中搜索這個(gè)模塊并載入。
    載入的內(nèi)容將在處理到 INCLUDE語(yǔ)句是直接執(zhí)行。

8.2.INSTALL指令

INSTALL 系列指令已經(jīng)在前面的章節(jié)有非常詳細(xì)的說(shuō)明,這里不在贅述,可參考前面的安裝部分。


8.3.FIND_xxx指令

FIND_系列指令主要包含一下指令:
FIND_FILE(<VAR> name1 path1 path2 ...)
VAR 變量代表找到的文件全路徑,包含文件名
FIND_LIBRARY(<VAR> name1 path1 path2 ...)
VAR 變量表示找到的庫(kù)全路徑,包含庫(kù)文件名
FIND_PATH(<VAR> name1 path1 path2 ...)
VAR 變量代表包含這個(gè)文件的路徑。
FIND_PROGRAM(<VAR> name1 path1 path2 ...)
VAR 變量代表包含這個(gè)程序的全路徑。
FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])
用來(lái)調(diào)用預(yù)定義在 CMAKE_MODULE_PATH下的Find<name>.cmake 模塊,你也可以自己定義Find<name>模塊,通過(guò) SET(CMAKE_MODULE_PATH dir)將其放入工程的某個(gè)目錄中供工程使用,我們?cè)诤竺娴恼鹿?jié)會(huì)詳細(xì)介紹 FIND_PACKAGE 的使用方法和Find 模塊的編寫(xiě)。

FIND_LIBRARY 示例:

FIND_LIBRARY(libX X11 /usr/lib) IF(NOT libX) MESSAGE(FATAL_ERROR “l(fā)ibX not found”) ENDIF(NOT libX)
8.4.控制指令:
  • 1.IF 指令,基本語(yǔ)法為:
IF(expression_r_r)# THEN section.COMMAND1(ARGS ...)COMMAND2(ARGS ...)... ELSE(expression_r_r)# ELSE section.COMMAND1(ARGS ...)COMMAND2(ARGS ...)... ENDIF(expression_r_r)

另外一個(gè)指令是 ELSEIF,總體把握一個(gè)原則,凡是出現(xiàn)IF的地方一定要有對(duì)應(yīng)的ENDIF.出現(xiàn) ELSEIF 的地方,ENDIF是可選的。
表達(dá)式的使用方法如下:
IF(var),如果變量不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或_NOTFOUND 時(shí),表達(dá)式為真。
IF(NOT var ),與上述條件相反。
IF(var1 AND var2),當(dāng)兩個(gè)變量都為真是為真。
IF(var1 OR var2),當(dāng)兩個(gè)變量其中一個(gè)為真時(shí)為真。
IF(COMMAND cmd),當(dāng)給定的 cmd 確實(shí)是命令并可以調(diào)用是為真。
IF(EXISTS dir)或者IF(EXISTS file),當(dāng)目錄名或者文件名存在時(shí)為真。
IF(file1 IS_NEWER_THAN file2),當(dāng) file1 比 file2 新,或者 file1/file2 其中有一個(gè)不存在時(shí)為真,文件名請(qǐng)使用完整路徑。
IF(IS_DIRECTORY dirname),當(dāng) dirname 是目錄時(shí),為真。
IF(variable MATCHES regex)
IF(string MATCHES regex)
當(dāng)給定的變量或者字符串能夠匹配正則表達(dá)式 regex 時(shí)為真。比如:

IF("hello" MATCHES "ell") MESSAGE("true") ENDIF("hello" MATCHES "ell") IF(variable LESS number) IF(string LESS number) IF(variable GREATER number) IF(string GREATER number) IF(variable EQUAL number) IF(string EQUAL number)

數(shù)字比較表達(dá)式:

IF(variable STRLESS string) IF(string STRLESS string) IF(variable STRGREATER string) IF(string STRGREATER string) IF(variable STREQUAL string) IF(string STREQUAL string)

按照字母序的排列進(jìn)行比較.
IF(DEFINED variable),如果變量被定義,為真。
一個(gè)小例子,用來(lái)判斷平臺(tái)差異:

IF(WIN32)MESSAGE(STATUS “This is windows.”)#作一些 Windows 相關(guān)的操作 ELSE(WIN32)MESSAGE(STATUS “This is not windows”)#作一些非 Windows 相關(guān)的操作 ENDIF(WIN32)

上述代碼用來(lái)控制在不同的平臺(tái)進(jìn)行不同的控制,但是,閱讀起來(lái)卻并不是那么舒服,
ELSE(WIN32)之類(lèi)的語(yǔ)句很容易引起歧義。
這就用到了我們?cè)凇俺S米兞俊币还?jié)提到的 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS開(kāi)關(guān)。
可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
這時(shí)候就可以寫(xiě)成:

IF(WIN32) ELSE() ENDIF()

如果配合 ELSEIF 使用,可能的寫(xiě)法是這樣:

IF(WIN32) #do something related to WIN32 ELSEIF(UNIX) #do something related to UNIX ELSEIF(APPLE) #do something related to APPLE ENDIF(WIN32)
  • 2.WHILE
    WHILE 指令的語(yǔ)法是:
WHILE(condition)COMMAND1(ARGS ...)COMMAND2(ARGS ...)... ENDWHILE(condition)

其真假判斷條件可以參考 IF 指令。

  • 3.FOREACH
    FOREACH 指令的使用方法有三種形式:
    (1)列表
FOREACH(loop_var arg1 arg2 ...)COMMAND1(ARGS ...)COMMAND2(ARGS ...)... ENDFOREACH(loop_var)

像我們前面使用的 AUX_SOURCE_DIRECTORY的例子

AUX_SOURCE_DIRECTORY(. SRC_LIST) FOREACH(F ${SRC_LIST})MESSAGE(${F}) ENDFOREACH(F)

(2)范圍

FOREACH(loop_var RANGE total) ENDFOREACH(loop_var)

從 0 到 total 以1為步進(jìn)
舉例如下:

FOREACH(VAR RANGE 10) MESSAGE(${VAR}) ENDFOREACH(VAR)

最終得到的輸出是:

0 1 2 3 4 5 6 7 8 9 10

(3)范圍和步進(jìn)

FOREACH(loop_var RANGE start stop [step]) ENDFOREACH(loop_var)

從 start 開(kāi)始到 stop 結(jié)束,以 step 為步進(jìn),
舉例如下

FOREACH(A RANGE 5 15 3) MESSAGE(${A}) ENDFOREACH(A)

最終得到的結(jié)果是:

5 8 11 14

這個(gè)指令需要注意的是,知道遇到 ENDFOREACH 指令,整個(gè)語(yǔ)句塊才會(huì)得到真正的執(zhí)行。
小結(jié):
本小節(jié)基本涵蓋了常用的 cmake 指令,包括基本指令、查找指令、安裝指令以及控制語(yǔ)句等,特別需要注意的是,在控制語(yǔ)句條件中使用變量,不能用${}引用,而是直接應(yīng)用變量名。
掌握了以上的各種控制指令,你應(yīng)該完全可以通過(guò) cmake 管理復(fù)雜的程序了,下一節(jié),我
們將介紹一個(gè)比較復(fù)雜的例子,通過(guò)他來(lái)演示本章的一些指令,并介紹模塊的概念。


九,復(fù)雜的例子:模塊的使用和自定義模塊

你現(xiàn)在還會(huì)覺(jué)得 cmake 簡(jiǎn)單嗎?

本章我們將著重介紹系統(tǒng)預(yù)定義的 Find模塊的使用以及自己編寫(xiě) Find 模塊,系統(tǒng)中提供了其他各種模塊,一般情況需要使用 INCLUDE指令顯式的調(diào)用,FIND_PACKAGE指令是一個(gè)特例,可以直接調(diào)用預(yù)定義的模塊.

其實(shí)使用純粹依靠 cmake 本身提供的基本指令來(lái)管理工程是一件非常復(fù)雜的事情,所以,cmake 設(shè)計(jì)成了可擴(kuò)展的架構(gòu),可以通過(guò)編寫(xiě)一些通用的模塊來(lái)擴(kuò)展 cmake.

在本章,我們準(zhǔn)備首先介紹一下 cmake 提供的FindCURL 模塊的使用。然后,基于我們前面的 libhello共享庫(kù),編寫(xiě)一個(gè)FindHello.cmake模塊.

9.1使用 FindCURL模塊

在/backup/cmake 目錄建立 t5 目錄,用于存放我們的 CURL 的例子。
建立 src 目錄,并建立 src/main.c,內(nèi)容如下:

#include <curl/curl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> FILE *fp; int write_data(void *ptr, size_t size, size_t nmemb, void *stream) { int written = fwrite(ptr, size, nmemb, (FILE *)fp); return written; } int main() { const char * path =/tmp/curl-test”; const char * mode = “w”; fp = fopen(path,mode); curl_global_init(CURL_GLOBAL_ALL); CURLcode res; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, “http://www.linux-ren.org”); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); res = curl_easy_perform(curl); curl_easy_cleanup(curl); }

這段代碼的作用是通過(guò) curl取回 www.linux-ren.org 的首頁(yè)并寫(xiě)入/tmp/curl-test文件中。
建立主工程文件 CMakeLists.txt

PROJECT(CURLTEST) ADD_SUBDIRECTORY(src)

建立 src/CMakeLists.txt
ADD_EXECUTABLE(curltest main.c)
現(xiàn)在自然是沒(méi)辦法編譯的,我們需要添加 curl 的頭文件路徑和庫(kù)文件。
方法 1:
直接通過(guò) INCLUDE_DIRECTORIES和 TARGET_LINK_LIBRARIES 指令添加:
我們可以直接在 src/CMakeLists.txt 中添加:

INCLUDE_DIRECTORIES(/usr/include) TARGET_LINK_LIBRARIES(curltest curl)

然后建立 build 目錄進(jìn)行外部構(gòu)建即可。
現(xiàn)在我們要探討的是使用 cmake 提供的 FindCURL 模塊。
方法 2,使用 FindCURL 模塊。
向src/CMakeLists.txt 中添加:

FIND_PACKAGE(CURL) IF(CURL_FOUND)INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})TARGET_LINK_LIBRARIES(curltest ${CURL_LIBRARY}) ELSE(CURL_FOUND)MESSAGE(FATAL_ERROR ”CURL library not found”) ENDIF(CURL_FOUND)

對(duì)于系統(tǒng)預(yù)定義的 Find<name>.cmake 模塊,使用方法一般如上例所示:
每一個(gè)模塊都會(huì)定義以下幾個(gè)變量

<name>_FOUND <name>_INCLUDE_DIR or <name>_INCLUDES <name>_LIBRARY or <name>_LIBRARIES

你可以通過(guò)<name>_FOUND來(lái)判斷模塊是否被找到,如果沒(méi)有找到,按照工程的需要關(guān)閉某些特性、給出提醒或者中止編譯,上面的例子就是報(bào)出致命錯(cuò)誤并終止構(gòu)建。

如果<name>_FOUND 為真,則將<name>_INCLUDE_DIR 加入 INCLUDE_DIRECTORIES,將<name>_LIBRARY加入 TARGET_LINK_LIBRARIES中。
我們?cè)賮?lái)看一個(gè)復(fù)雜的例子,通過(guò)<name>_FOUND來(lái)控制工程特性:

SET(mySources viewer.c) SET(optionalSources) SET(optionalLibs) FIND_PACKAGE(JPEG) IF(JPEG_FOUND)SET(optionalSources ${optionalSources} jpegview.c)INCLUDE_DIRECTORIES( ${JPEG_INCLUDE_DIR} )SET(optionalLibs ${optionalLibs} ${JPEG_LIBRARIES} )ADD_DEFINITIONS(-DENABLE_JPEG_SUPPORT) ENDIF(JPEG_FOUND) IF(PNG_FOUND)SET(optionalSources ${optionalSources} pngview.c)INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )SET(optionalLibs ${optionalLibs} ${PNG_LIBRARIES} )ADD_DEFINITIONS(-DENABLE_PNG_SUPPORT) ENDIF(PNG_FOUND) ADD_EXECUTABLE(viewer ${mySources} ${optionalSources} ) TARGET_LINK_LIBRARIES(viewer ${optionalLibs})

通過(guò)判斷系統(tǒng)是否提供了 JPEG 庫(kù)來(lái)決定程序是否支持 JPEG 功能。


9.2,編寫(xiě)屬于自己的FindHello模塊。

我們?cè)诖饲暗?t3 實(shí)例中,演示了構(gòu)建動(dòng)態(tài)庫(kù)、靜態(tài)庫(kù)的過(guò)程并進(jìn)行了安裝。
接下來(lái),我們?cè)?t6 示例中演示如何自定義FindHELLO模塊并使用這個(gè)模塊構(gòu)建工程:
請(qǐng)?jiān)诮?backup/cmake/中建立 t6 目錄,并在其中建立 cmake 目錄用于存放我們自己定義的FindHELLO.cmake 模塊,同時(shí)建立 src 目錄,用于存放我們的源文件。

1,定義cmake/FindHELLO.cmake 模塊

FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello) FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib /usr/local/lib) IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)SET(HELLO_FOUND TRUE) ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY) IF (HELLO_FOUND)IF (NOT HELLO_FIND_QUIETLY)MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")ENDIF (NOT HELLO_FIND_QUIETLY) ELSE (HELLO_FOUND)IF (HELLO_FIND_REQUIRED)MESSAGE(FATAL_ERROR "Could not find hello library")ENDIF (HELLO_FIND_REQUIRED) ENDIF (HELLO_FOUND)

針對(duì)上面的模塊讓我們?cè)賮?lái)回顧一下 FIND_PACKAGE 指令:
FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])
前面的 CURL 例子中我們使用了最簡(jiǎn)單的FIND_PACKAGE 指令,其實(shí)他可以使用多種參數(shù),
QUIET 參數(shù),對(duì)應(yīng)與我們編寫(xiě)的FindHELLO 中的 HELLO_FIND_QUIETLY,如果不指定這個(gè)參數(shù),就會(huì)執(zhí)行:
MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")

REQUIRED 參數(shù),其含義是指這個(gè)共享庫(kù)是否是工程必須的,如果使用了這個(gè)參數(shù),說(shuō)明這個(gè)鏈接庫(kù)是必備庫(kù),如果找不到這個(gè)鏈接庫(kù),則工程不能編譯。對(duì)應(yīng)于
FindHELLO.cmake 模塊中的 HELLO_FIND_REQUIRED變量。
同樣,我們?cè)谏厦娴哪K中定義了 HELLO_FOUND,HELLO_INCLUDE_DIR,HELLO_LIBRARY 變量供開(kāi)發(fā)者在 FIND_PACKAGE 指令中使用。
OK,下面建立 src/main.c,內(nèi)容為:

#include <hello.h> int main() {HelloFunc();return 0; }

建立 src/CMakeLists.txt 文件,內(nèi)容如下:

FIND_PACKAGE(HELLO) IF(HELLO_FOUND)ADD_EXECUTABLE(hello main.c)INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR})TARGET_LINK_LIBRARIES(hello ${HELLO_LIBRARY}) ENDIF(HELLO_FOUND)

為了能夠讓工程找到 FindHELLO.cmake 模塊(存放在工程中的 cmake 目錄)我們?cè)谥鞴こ涛募?CMakeLists.txt 中加入:
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)


9.3,使用自定義的FindHELLO模塊構(gòu)建工程

仍然采用外部編譯的方式,建立 build 目錄,進(jìn)入目錄運(yùn)行:
cmake ..
我們可以從輸出中看到:
Found Hello: /usr/lib/libhello.so
如果我們把上面的 FIND_PACKAGE(HELLO)修改為FIND_PACKAGE(HELLO QUIET),則不會(huì)看到上面的輸出。
接下來(lái)就可以使用make命令構(gòu)建工程,運(yùn)行:
./src/hello 可以得到輸出Hello World。
說(shuō)明工程成功構(gòu)建。
四,如果沒(méi)有找到hello library 呢?
我們可以嘗試將/usr/lib/libhello.x移動(dòng)到/tmp目錄,這樣,按照 FindHELLO模塊的定義,就找不到hello library了,我們?cè)賮?lái)看一下構(gòu)建結(jié)果:
cmake ..
仍然可以成功進(jìn)行構(gòu)建,但是這時(shí)候是沒(méi)有辦法編譯的。
修改 FIND_PACKAGE(HELLO)為FIND_PACKAGE(HELLO REQUIRED),將 hello library定義為工程必須的共享庫(kù)。

這時(shí)候再次運(yùn)行 cmake ..
我們得到如下輸出:

CMake Error: Could not find hello library.

因?yàn)檎也坏?libhello.x,所以,整個(gè)Makefile 生成過(guò)程被出錯(cuò)中止。

小結(jié):

在本節(jié)中,我們學(xué)習(xí)了如何使用系統(tǒng)提供的 Find<NAME>模塊并學(xué)習(xí)了自己編寫(xiě)
Find<NAME>模塊以及如何在工程中使用這些模塊。
后面的章節(jié),我們會(huì)逐漸學(xué)習(xí)更多的 cmake 模塊使用方法以及用 cmake 來(lái)管理 GTK 和 QT4工程。

總結(jié)

以上是生活随笔為你收集整理的【Tools】cmake 常用变量和常用环境变量查表手册---整理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。