標籤:

cmake 常用變數和常用環境變數查表手冊

http://www.cnblogs.com/xianghang123/p/3556425.html2014一,cmake 變數引用的方式:前面我們已經提到了,使用${}進行變數的引用。在 IF 等語句中,是直接使用變數名而不通過${}取值二,cmake 自定義變數的方式:主要有隱式定義和顯式定義兩種,前面舉了一個隱式定義的例子,就是 PROJECT 指令,他會隱式的定義<projectname>_BINARY_DIR 和<projectname>_SOURCE_DIR 兩個變數。顯式定義的例子我們前面也提到了,使用 SET 指令,就可以構建一個自定義變數了。比如:SET(HELLO_SRC main.SOURCE_PATHc),就 PROJECT_BINARY_DIR 可以通過${HELLO_SRC}來引用這個自定義變數了.三,cmake 常用變數:1,CMAKE_BINARY_DIR PROJECT_BINARY_DIR<projectname>_BINARY_DIR這三個變數指代的內容是一致的,如果是 in source 編譯,指得就是工程頂層目錄,如果是 out-of-source 編譯,指的是工程編譯發生的目錄。PROJECT_BINARY_DIR 跟其他指令稍有區別,現在,你可以理解為他們是一致的。2,CMAKE_SOURCE_DIR PROJECT_SOURCE_DIR <projectname>_SOURCE_DIR這三個變數指代的內容是一致的,不論採用何種編譯方式,都是工程頂層目錄。也就是在 in source 編譯時,他跟 CMAKE_BINARY_DIR 等變數一致。PROJECT_SOURCE_DIR 跟其他指令稍有區別,現在,你可以理解為他們是一致的。3,CMAKE_CURRENT_SOURCE_DIR指的是當前處理的 CMakeLists.txt 所在的路徑,比如上面我們提到的 src 子目錄。4,CMAKE_CURRRENT_BINARY_DIR如果是 in-source 編譯,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 編譯,他指的是 target 編譯目錄。使用我們上面提到的 ADD_SUBDIRECTORY(src bin)可以更改這個變數的值。使用 SET(EXECUTABLE_OUTPUT_PATH <新路徑>)並不會對這個變數造成影響,它僅僅修改了最終目標文件存放的路徑。5,CMAKE_CURRENT_LIST_FILE

輸出調用這個變數的 CMakeLists.txt 的完整路徑

6,CMAKE_CURRENT_LIST_LINE

輸出這個變數所在的行

7,CMAKE_MODULE_PATH這個變數用來定義自己的 cmake 模塊所在的路徑。如果你的工程比較複雜,有可能會自己編寫一些 cmake 模塊,這些 cmake 模塊是隨你的工程發布的,為了讓 cmake 在處理CMakeLists.txt 時找到這些模塊,你需要通過 SET 指令,將自己的 cmake 模塊路徑設置一下。比如SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)這時候你就可以通過 INCLUDE 指令來調用自己的模塊了。8,EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH分別用來重新定義最終結果的存放目錄,前面我們已經提到了這兩個變數。9,PROJECT_NAME返回通過 PROJECT 指令定義的項目名稱。四,cmake 調用環境變數的方式使用$ENV{NAME}指令就可以調用系統的環境變數了。比如MESSAGE(STATUS 「HOME dir: $ENV{HOME}」)設置環境變數的方式是:SET(ENV{變數名} 值)1,CMAKE_INCLUDE_CURRENT_DIR自動添加 CMAKE_CURRENT_BINARY_DIR 和 CMAKE_CURRENT_SOURCE_DIR 到當前處理的 CMakeLists.txt。相當於在每個 CMakeLists.txt 加入:INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}${CMAKE_CURRENT_SOURCE_DIR})2,CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE將工程提供的頭文件目錄始終至於系統頭文件目錄的前面,當你定義的頭文件確實跟系統發生衝突時可以提供一些幫助。3,CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH 我們在上一節已經提及。五,系統信息1,CMAKE_MAJOR_VERSION,CMAKE 主版本號,比如 2.4.6 中的 22,CMAKE_MINOR_VERSION,CMAKE 次版本號,比如 2.4.6 中的 43,CMAKE_PATCH_VERSION,CMAKE 補丁等級,比如 2.4.6 中的 64,CMAKE_SYSTEM,系統名稱,比如 Linux-2.6.225,CMAKE_SYSTEM_NAME,不包含版本的系統名,比如 Linux6,CMAKE_SYSTEM_VERSION,系統版本,比如 2.6.227,CMAKE_SYSTEM_PROCESSOR,處理器名稱,比如 i686.8,UNIX,在所有的類 UNIX 平台為 TRUE,包括 OS X 和 cygwin9,WIN32,在所有的 win32 平台為 TRUE,包括 cygwin六,主要的開關選項:1,CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS,用來控制 IF ELSE 語句的書寫方式,在下一節語法部分會講到。2,BUILD_SHARED_LIBS這個開關用來控制默認的庫編譯方式,如果不進行設置,使用 ADD_LIBRARY 並沒有指定庫類型的情況下,默認編譯生成的庫都是靜態庫。如果 SET(BUILD_SHARED_LIBS ON)後,默認生成的為動態庫。3,CMAKE_C_FLAGS設置 C 編譯選項,也可以通過指令 ADD_DEFINITIONS()添加。4,CMAKE_CXX_FLAGS設置 C++編譯選項,也可以通過指令 ADD_DEFINITIONS()添加。小結:本章介紹了一些較常用的 cmake 變數,這些變數僅僅是所有 cmake 變數的很少一部分,目前 cmake 的英文文檔也是比較缺乏的,如果需要了解更多的 cmake 變數,更好的方式是閱讀一些成功項目的 cmake 工程文件,比如 KDE4 的代碼。八,cmake 常用指令前面我們講到了 cmake 常用的變數,相信「cmake 即編程」的感覺會越來越明顯,無論如何,我們仍然可以看到 cmake 比 autotools 要簡單很多。接下來我們就要集中的看一看cmake 所提供的常用指令。在前面的章節我們已經討論了很多指令的用法,如PROJECT,ADD_EXECUTABLE,INSTALL,ADD_SUBDIRECTORY,SUBDIRS,INCLUDE_DIRECTORIES,LINK_DIRECTORIES,TARGET_LINK_LIBRARIES,SET 等。本節會引入更多的 cmake 指令,為了編寫的方便,我們將按照 cmake man page 的順序來介紹各種指令,不再推薦使用的指令將不再介紹,INSTALL 系列指令在安裝部分已經做了非常詳細的說明,本節也不在提及。(你可以將本章理解成選擇性翻譯,但是會加入更多的個人理解)一,基本指令1,ADD_DEFINITIONS向 C/C++編譯器添加-D 定義,比如:ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),參數之間用空格分割。

如果你的代碼中定義了#ifdef ENABLE_DEBUG #endif,這個代碼塊就會生效。如果要添加其他的編譯器開關,可以通過 CMAKE_C_FLAGS 變數和 CMAKE_CXX_FLAGS 變數設置。

2,ADD_DEPENDENCIES定義 target 依賴的其他 target,確保在編譯本 target 之前,其他的 target 已經被構建。ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)

3,ADD_EXECUTABLE、ADD_LIBRARY、ADD_SUBDIRECTORY 前面已經介紹過了,這裡不再羅唆。

4,ADD_TEST 與 ENABLE_TESTING 指令。ENABLE_TESTING 指令用來控制 Makefile 是否構建 test 目標,涉及工程所有目錄。語法很簡單,沒有任何參數,ENABLE_TESTING(),一般情況這個指令放在工程的主CMakeLists.txt 中.

ADD_TEST 指令的語法是:ADD_TEST(testname Exename arg1 arg2 ...)testname 是自定義的 test 名稱,Exename 可以是構建的目標文件也可以是外部腳本等等。後面連接傳遞給可執行文件的參數。如果沒有在同一個 CMakeLists.txt 中打開ENABLE_TESTING()指令,任何 ADD_TEST 都是無效的。比如我們前面的 Helloworld 例子,可以在工程主 CMakeLists.txt 中添加ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)ENABLE_TESTING()生成 Makefile 後,就可以運行 make test 來執行測試了。

5,AUX_SOURCE_DIRECTORY基本語法是:AUX_SOURCE_DIRECTORY(dir VARIABLE)作用是發現一個目錄下所有的源代碼文件並將列表存儲在一個變數中,這個指令臨時被用來自動構建源文件列表。因為目前 cmake 還不能自動發現新添加的源文件。比如AUX_SOURCE_DIRECTORY(. SRC_LIST)ADD_EXECUTABLE(main ${SRC_LIST})你也可以通過後面提到的 FOREACH 指令來處理這個 LIST

6,CMAKE_MINIMUM_REQUIRED其語法為 CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])比如 CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)如果 cmake 版本小與 2.5,則出現嚴重錯誤,整個過程中止。

7,EXEC_PROGRAM在 CMakeLists.txt 處理過程中執行命令,並不會在生成的 Makefile 中執行。

具體語法為:EXEC_PROGRAM(Executable [directory in which to run] [ARGS <arguments to executable>] [OUTPUT_VARIABLE <var>] [RETURN_VALUE <var>])用於在指定的目錄運行某個程序,通過 ARGS 添加參數,如果要獲取輸出和返回值,可通過OUTPUT_VARIABLE 和 RETURN_VALUE 分別定義兩個變數.

這個指令可以幫助你在 CMakeLists.txt 處理過程中支持任何命令,比如根據系統情況去修改代碼文件等等。舉個簡單的例子,我們要在 src 目錄執行 ls 命令,並把結果和返回值存下來。可以直接在 src/CMakeLists.txt 中添加:EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUELS_RVALUE)IF(not LS_RVALUE)MESSAGE(STATUS "ls result: " ${LS_OUTPUT})ENDIF(not LS_RVALUE)

在 cmake 生成 Makefile 的過程中,就會執行 ls 命令,如果返回 0,則說明成功執行,那麼就輸出 ls *.c 的結果。關於 IF 語句,後面的控制指令會提到。

8,FILE 指令文件操作指令,基本語法為: 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)這裡的語法都比較簡單,不在展開介紹了。

9,INCLUDE 指令,用來載入 CMakeLists.txt 文件,也用於載入預定義的 cmake 模塊. INCLUDE(file1 [OPTIONAL]) INCLUDE(module [OPTIONAL])OPTIONAL 參數的作用是文件不存在也不會產生錯誤。你可以指定載入一個文件,如果定義的是一個模塊,那麼將在 CMAKE_MODULE_PATH 中搜索這個模塊並載入。載入的內容將在處理到 INCLUDE 語句是直接執行。二,INSTALL 指令INSTALL 系列指令已經在前面的章節有非常詳細的說明,這裡不在贅述,可參考前面的安裝部分。三,FIND_指令FIND_系列指令主要包含一下指令:FIND_FILE(<VAR> name1 path1 path2 ...)VAR 變數代表找到的文件全路徑,包含文件名FIND_LIBRARY(<VAR> name1 path1 path2 ...)VAR 變數表示找到的庫全路徑,包含庫文件名FIND_PATH(<VAR> name1 path1 path2 ...)VAR 變數代表包含這個文件的路徑。FIND_PROGRAM(<VAR> name1 path1 path2 ...)VAR 變數代表包含這個程序的全路徑。FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])用來調用預定義在 CMAKE_MODULE_PATH 下的 Find<name>.cmake 模塊,你也可以自己定義 Find<name>模塊,通過 SET(CMAKE_MODULE_PATH dir)將其放入工程的某個目錄中供工程使用,我們在後面的章節會詳細介紹 FIND_PACKAGE 的使用方法和 Find 模塊的編寫。

FIND_LIBRARY 示例:FIND_LIBRARY(libX X11 /usr/lib)IF(NOT libX)MESSAGE(FATAL_ERROR 「libX not found」)ENDIF(NOT libX)

四,控制指令:1,IF 指令,基本語法為: IF(expression_r_r) # THEN section. COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ELSE(expression_r_r) # ELSE section. COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDIF(expression_r_r)另外一個指令是 ELSEIF,總體把握一個原則,凡是出現 IF 的地方一定要有對應的ENDIF.出現 ELSEIF 的地方,ENDIF 是可選的。表達式的使用方法如下:IF(var),如果變數不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或<var>_NOTFOUND 時,表達式為真。IF(NOT var ),與上述條件相反。IF(var1 AND var2),當兩個變數都為真是為真。IF(var1 OR var2),當兩個變數其中一個為真時為真。IF(COMMAND cmd),當給定的 cmd 確實是命令並可以調用是為真。IF(EXISTS dir)或者 IF(EXISTS file),當目錄名或者文件名存在時為真。IF(file1 IS_NEWER_THAN file2),當 file1 比 file2 新,或者 file1/file2 其中有一個不存在時為真,文件名請使用完整路徑。IF(IS_DIRECTORY dirname),當 dirname 是目錄時,為真。IF(variable MATCHES regex)IF(string MATCHES regex)當給定的變數或者字元串能夠匹配正則表達式 regex 時為真。比如: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)數字比較表達式IF(variable STRLESS string)IF(string STRLESS string)IF(variable STRGREATER string)IF(string STRGREATER string)IF(variable STREQUAL string)IF(string STREQUAL string)按照字母序的排列進行比較.IF(DEFINED variable),如果變數被定義,為真。一個小例子,用來判斷平台差異:IF(WIN32) MESSAGE(STATUS 「This is windows.」) #作一些 Windows 相關的操作ELSE(WIN32) MESSAGE(STATUS 「This is not windows」) #作一些非 Windows 相關的操作ENDIF(WIN32)上述代碼用來控制在不同的平台進行不同的控制,但是,閱讀起來卻並不是那麼舒服,ELSE(WIN32)之類的語句很容易引起歧義。這就用到了我們在「常用變數」一節提到的 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 開關。可以 SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)這時候就可以寫成:IF(WIN32)ELSE()ENDIF()如果配合 ELSEIF 使用,可能的寫法是這樣:IF(WIN32)#do something related to WIN32ELSEIF(UNIX)#do something related to UNIXELSEIF(APPLE)#do something related to APPLEENDIF(WIN32)2,WHILEWHILE 指令的語法是: WHILE(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDWHILE(condition)其真假判斷條件可以參考 IF 指令。3,FOREACHFOREACH 指令的使用方法有三種形式: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為步進舉例如下:FOREACH(VAR RANGE 10)MESSAGE(${VAR})ENDFOREACH(VAR)最終得到的輸出是:0123456789103,範圍和步進FOREACH(loop_var RANGE start stop [step])ENDFOREACH(loop_var)從 start 開始到 stop 結束,以 step 為步進,舉例如下FOREACH(A RANGE 5 15 3)MESSAGE(${A})ENDFOREACH(A)最終得到的結果是:581114這個指令需要注意的是,知道遇到 ENDFOREACH 指令,整個語句塊才會得到真正的執行。小結:本小節基本涵蓋了常用的 cmake 指令,包括基本指令、查找指令、安裝指令以及控制語句等,特別需要注意的是,在控制語句條件中使用變數,不能用${}引用,而是直接應用變數名。

掌握了以上的各種控制指令,你應該完全可以通過 cmake 管理複雜的程序了,下一節,我們將介紹一個比較複雜的例子,通過他來演示本章的一些指令,並介紹模塊的概念。

九,複雜的例子:模塊的使用和自定義模塊你現在還會覺得 cmake 簡單嗎?

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

其實使用純粹依靠 cmake 本身提供的基本指令來管理工程是一件非常複雜的事情,所以,cmake 設計成了可擴展的架構,可以通過編寫一些通用的模塊來擴展 cmake.

在本章,我們準備首先介紹一下 cmake 提供的 FindCURL 模塊的使用。然後,基於我們前面的 libhello 共享庫,編寫一個 FindHello.cmake 模塊.

一,使用 FindCURL 模塊在/backup/cmake 目錄建立 t5 目錄,用於存放我們的 CURL 的例子。建立 src 目錄,並建立 src/main.c,內容如下:#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);}這段代碼的作用是通過 curl 取回 www.linux-ren.org 的首頁並寫入/tmp/curl-test文件中。建立主工程文件 CMakeLists.txtPROJECT(CURLTEST)ADD_SUBDIRECTORY(src)建立 src/CMakeLists.txtADD_EXECUTABLE(curltest main.c)現在自然是沒辦法編譯的,我們需要添加 curl 的頭文件路徑和庫文件。方法 1:直接通過 INCLUDE_DIRECTORIES 和 TARGET_LINK_LIBRARIES 指令添加:我們可以直接在 src/CMakeLists.txt 中添加:INCLUDE_DIRECTORIES(/usr/include)TARGET_LINK_LIBRARIES(curltest curl)然後建立 build 目錄進行外部構建即可。現在我們要探討的是使用 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)對於系統預定義的 Find<name>.cmake 模塊,使用方法一般如上例所示:每一個模塊都會定義以下幾個變數 <name>_FOUND · <name>_INCLUDE_DIR or <name>_INCLUDES · <name>_LIBRARY or <name>_LIBRARIES ·你可以通過<name>_FOUND 來判斷模塊是否被找到,如果沒有找到,按照工程的需要關閉某些特性、給出提醒或者中止編譯,上面的例子就是報出致命錯誤並終止構建。

如果<name>_FOUND 為真,則將<name>_INCLUDE_DIR 加入 INCLUDE_DIRECTORIES,將<name>_LIBRARY 加入 TARGET_LINK_LIBRARIES 中。我們再來看一個複雜的例子,通過<name>_FOUND 來控制工程特性: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}通過判斷系統是否提供了 JPEG 庫來決定程序是否支持 JPEG 功能。

二,編寫屬於自己的 FindHello 模塊。我們在此前的 t3 實例中,演示了構建動態庫、靜態庫的過程並進行了安裝。接下來,我們在 t6 示例中演示如何自定義 FindHELLO 模塊並使用這個模塊構建工程:請在建立/backup/cmake/中建立 t6 目錄,並在其中建立 cmake 目錄用於存放我們自己定義的 FindHELLO.cmake 模塊,同時建立 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)針對上面的模塊讓我們再來回顧一下 FIND_PACKAGE 指令: FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])前面的 CURL 例子中我們使用了最簡單的 FIND_PACKAGE 指令,其實他可以使用多種參數,QUIET 參數,對應與我們編寫的 FindHELLO 中的 HELLO_FIND_QUIETLY,如果不指定這個參數,就會執行:MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")

REQUIRED 參數,其含義是指這個共享庫是否是工程必須的,如果使用了這個參數,說明這個鏈接庫是必備庫,如果找不到這個鏈接庫,則工程不能編譯。對應於FindHELLO.cmake 模塊中的 HELLO_FIND_REQUIRED 變數。同樣,我們在上面的模塊中定義了 HELLO_FOUND,HELLO_INCLUDE_DIR,HELLO_LIBRARY 變數供開發者在 FIND_PACKAGE 指令中使用。OK,下面建立 src/main.c,內容為:#include <hello.h>int main(){ HelloFunc(); return 0;}建立 src/CMakeLists.txt 文件,內容如下: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 目錄)我們在主工程文件 CMakeLists.txt 中加入:SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

三,使用自定義的 FindHELLO 模塊構建工程仍然採用外部編譯的方式,建立 build 目錄,進入目錄運行:cmake ..我們可以從輸出中看到:Found Hello: /usr/lib/libhello.so如果我們把上面的 FIND_PACKAGE(HELLO)修改為 FIND_PACKAGE(HELLO QUIET),則不會看到上面的輸出。接下來就可以使用 make 命令構建工程,運行:./src/hello 可以得到輸出Hello World。說明工程成功構建。四,如果沒有找到 hello library 呢?我們可以嘗試將/usr/lib/libhello.x 移動到/tmp 目錄,這樣,按照 FindHELLO 模塊的定義,就找不到 hello library 了,我們再來看一下構建結果:cmake ..仍然可以成功進行構建,但是這時候是沒有辦法編譯的。修改 FIND_PACKAGE(HELLO)為 FIND_PACKAGE(HELLO REQUIRED),將 hello library 定義為工程必須的共享庫。

這時候再次運行 cmake ..我們得到如下輸出:CMake Error: Could not find hello library.因為找不到 libhello.x,所以,整個 Makefile 生成過程被出錯中止。小結:在本節中,我們學習了如何使用系統提供的 Find<NAME>模塊並學習了自己編寫Find<NAME>模塊以及如何在工程中使用這些模塊。後面的章節,我們會逐漸學習更多的 cmake 模塊使用方法以及用 cmake 來管理 GTK 和 QT4工程。


推薦閱讀:

無需手寫任何代碼,直接快速編譯源代碼
Chinese university bans students from celebrating Christmas because its kitsch and makes them wat
为什么make up for ever 翻译成浮生若梦?
I can make my own money!

TAG:環境 | make |