資源簡(jiǎn)介
簡(jiǎn)單到復(fù)雜的cmake編寫(xiě)教程,適合剛?cè)雮兊男率?。cmake 已經(jīng)開(kāi)發(fā)了 5,6 年的時(shí)間,如果沒(méi)有 KDE4,也許不會(huì)有人或者 Linux 發(fā)行版 本重視 cmake,因?yàn)槌?Kitware 似乎沒(méi)有人使用它。通過(guò) KDE4
初識(shí) cmake Cmake不再使你在構(gòu)建項(xiàng)目時(shí)郁悶地想自殺了 一位KDE開(kāi)發(fā)者 1,背景知識(shí): cmake是 kitware公司以及一些開(kāi)源開(kāi)發(fā)者在開(kāi)發(fā)幾個(gè)工具套件(VTK)的過(guò)程中衍 生品,最終形成體系,成為一個(gè)獨(dú)立的開(kāi)放源代碼項(xiàng)目。項(xiàng)目的誕生時(shí)間是2601年。其官 方網(wǎng)站是ww. cmake.org,可以通過(guò)訪問(wèn)官方網(wǎng)站獲得更多關(guān)于 cmake的信息。 cmake 的流行其實(shí)要?dú)w功于KDE4的開(kāi)發(fā)(似乎跟當(dāng)年的Svn一樣,KDE將代碼倉(cāng)庫(kù)從CVS遷移到 SVN,同時(shí)證明了SWN管理大型項(xiàng)目的可用性),在KDE開(kāi)發(fā)者使用了近10年 autotools 之后,他們終于決定為KDE4選擇一個(gè)新的工程構(gòu)建工具,其根本原因用KDE開(kāi)發(fā)者的話來(lái) 說(shuō)就是:只有少數(shù)幾個(gè)“編譯專(zhuān)家”能夠掌握KDE現(xiàn)在的構(gòu)建體系 ( admin/ Makefile. common),在經(jīng)歷了 unsermake, scons以及 cmake的選型和嘗 試之后,KDE4決定使用 cmake作為自己的構(gòu)建系統(tǒng)。在遷移過(guò)程中,進(jìn)展異常的順利,并 獲得了 cmake開(kāi)發(fā)者的支持。所以,目前的KDE4開(kāi)發(fā)版本已經(jīng)完全使用 cmake來(lái)進(jìn)行構(gòu) 建。像 kdesvn, rosegarden等項(xiàng)目也開(kāi)始使用 cmake,這也注定了 cmake必然會(huì)成為 個(gè)主流的構(gòu)建體系。 2,特點(diǎn): cmake的特點(diǎn)主要有: ,開(kāi)放源代碼,使用類(lèi)BSD許可發(fā)布http://cmake.org/html/copyrigHt.html 2,跨平臺(tái),并可生成 native編譯配置文件,在 Linux/Uni×平臺(tái),生成 makefile,在 蘋(píng)果平臺(tái),可以生成 xcode,在 Window5平臺(tái),可以生成MsVC的工程文件。 3,能夠管理大型項(xiàng)目,KDE4就是最好的證明。 4,簡(jiǎn)化編譯構(gòu)建過(guò)程和編譯過(guò)程。 Cmake的工具鏈非常簡(jiǎn)單: cmake+make。 5,高效慮,按照KDE官方說(shuō)法, CMake構(gòu)建KDE4的 kdelib5要比使用 autotools來(lái) 構(gòu)建KDE3.5.6的 delis快40%,主要是因?yàn)?Cmake在工具鏈中沒(méi)有 libtool。 6,可擴(kuò)展,可以為 cmake編寫(xiě)特定功能的模塊,擴(kuò)充 cmake功能。 3,問(wèn)題,難道就沒(méi)有問(wèn)題? 1, cmake很簡(jiǎn)單,但絕對(duì)沒(méi)有聽(tīng)起來(lái)或者想象中那么簡(jiǎn)單。 2, cmake編寫(xiě)的過(guò)程實(shí)際上是編程的過(guò)程,跟以前使用 autotools一樣,不過(guò)你需要編 寫(xiě)的是 CMakelists5.txt(每個(gè)目錄一個(gè)),使用的是" cmake語(yǔ)言和語(yǔ)法。 3, cmake跟已有體系的配合并不是特別理想,比如 pkgconfig,您在實(shí)際使用中會(huì)有所 體會(huì),雖然有一些擴(kuò)展可以使用,但并不理想。 4,個(gè)人的建議: 如果你沒(méi)有實(shí)際的項(xiàng)目需求,那么看到這里就可以停下來(lái)了,因?yàn)?cmake的學(xué)習(xí)過(guò)程就 是實(shí)踐過(guò)程,沒(méi)有實(shí)踐,讀的再多幾天后也會(huì)忘記 2,如果你的工程只有幾個(gè)文件,直接編寫(xiě) Makefile是最好的選擇。 3,如果使用的是C/C++/Java之外的語(yǔ)言,請(qǐng)不要使用 cmake(至少目前是這樣) 4,如果你使用的語(yǔ)言有非常完備的構(gòu)建體系,比如java的ant,也不需要學(xué)習(xí) cmake, 雖然有成功的例子,比如QT4.3的 csharp綁定 yoto。 5,如果項(xiàng)目已經(jīng)采用了非常完備的工程管理工具,并且不存在維護(hù)問(wèn)題,沒(méi)有必要遷移到 cmake 4,如果僅僅使用qt編程,沒(méi)有必要使用 cmake,因?yàn)?qmake管理Qt工程的專(zhuān)業(yè)性和自 動(dòng)化程度比 cmake要高很多。 二,安裝 cmake 還需要安裝嗎? cmake目前已經(jīng)成為各大 Linux發(fā)行版提供的組件,比如 Everest直接在系統(tǒng)中包含 Fedora在 extra倉(cāng)庫(kù)中提供,所以,需要自己動(dòng)手安裝的可能性很小。如果你使用的操 作系統(tǒng)(比如 Windows或者某些 Linux版本)沒(méi)有提供 cmake或者包含的版本較舊,建議 你直接從 cmake官方網(wǎng)站下載安裝。 http://www.cmake.org/html/downloAd.html 在這個(gè)頁(yè)面,提供了源代碼的下載以及針對(duì)各種不同操作系統(tǒng)的二進(jìn)制下載,可以選擇適合 自己操作系統(tǒng)的版本下載安裝。因?yàn)楦鱾€(gè)系統(tǒng)的安裝方式和包管理格式有所不同,在此就不 再贅述了,相信一定能夠順利安裝 cmake。 ,初試 cmake- cmake的 helloworld Hello world,世界你好 本節(jié)選擇了一個(gè)最簡(jiǎn)單的例子 Helloworld來(lái)演練一下 cmake的完整構(gòu)建過(guò)程,本節(jié)并不 會(huì)深入的探討 cmake,僅僅展示一個(gè)簡(jiǎn)單的例子,并加以粗略的解釋。我們選擇了 Everest linux作為基本開(kāi)發(fā)平臺(tái),因?yàn)檫@個(gè)只有一張CD的發(fā)行版本,包含了gcc 4.2/gtk/qt3/qt4等完整的開(kāi)發(fā)環(huán)境,同時(shí),系統(tǒng)默認(rèn)集成了 cmake最新版本2.4.6。 ,準(zhǔn)備工作: 首先,在/ backup目錄建立一個(gè) cmake目錄,用來(lái)放置我們學(xué)習(xí)過(guò)程中的所有練習(xí)。 mkdir -p/backup/cmake 以后我們所有的 cmake練習(xí)都會(huì)放在/ backup/ cma ke的子目錄下(你也可以自行安排目錄, 這個(gè)并不是限制,僅僅是為了敘述的方便) 然后在 cmake建立第一個(gè)練習(xí)目錄t1 cd /backup/cmake mkdir tl d t1 在t1目錄建立main.C和 CMakelists.txt(注意文件名大小寫(xiě)): main.C文件內(nèi)容: //main. c #include <stdio. h> int main () printf ("hello world from tl Main! \n") return o Cmakelists.txt文件內(nèi)容: PROJECT (HELLO) SET(SRC LIST main. c) MESSAGE(STATUS This is binarY dir $HELLO BINARY DIRj MESSAGE(STATUS This is source dir SHELLO SOURCE DIRF) ADd EXECUTABLE(helLo SRC LIST) 2,開(kāi)始構(gòu)建 所有的文件創(chuàng)建完成后,t1目錄中應(yīng)該存在main.C和 CMakelists.txt兩個(gè)文件 接下來(lái)我們來(lái)構(gòu)建這個(gè)工程,在這個(gè)目錄運(yùn)行: cmake.(注意命令后面的點(diǎn)號(hào),代表本目錄)。 輸出大概是這個(gè)樣子: Check for working c compiler: /usr/bin/gcc Check for working c compiler: /usr/bin/gcc -. works Check size of void Check size of void- done Check for working CXX compiler: /usr/bin/c++ Check for working CXX compiler: /usr/bin/c++-- works This is binary dir /backup/cmake/t1 This is source dir /backup/ cmake/t1 Configuring done Generating done Build files have been written to: /backup/cmake/t1 再讓我們看一下目錄中的內(nèi)容: 你會(huì)發(fā)現(xiàn),系統(tǒng)自動(dòng)生成了: CMakefiles, CMakeCache.txt, cmake install. cmake等文件,并且生成了 Makefile 現(xiàn)在不需要理會(huì)這些文件的作用,以后你也可以不去理會(huì)。最關(guān)鍵的是,它自動(dòng)生成了 Makefile 然后進(jìn)行工程的實(shí)際構(gòu)建,在這個(gè)目錄輸入make命令,大概會(huì)得到如下的彩色輸出: Scanning dependencies of target hello [100] Building c object CMakeFiles/hello. dir/main.o Linking c executable hello [100% Built target hello 如果你需要看到make構(gòu)建的詳細(xì)過(guò)程,可以使用 make verbi0SE=1或者 VERBOSE=1 make命令來(lái)進(jìn)行構(gòu)建。 這時(shí)候,我們需要的目標(biāo)文件 hello已經(jīng)構(gòu)建完成,位于當(dāng)前目錄,嘗試運(yùn)行一下: Thello 得到輸出: Hello world from Main 恭喜您,到這里為止您已經(jīng)完全掌握了 cmake的使用方法。 3,簡(jiǎn)單的解釋 我們來(lái)重新看一下 CMakelists.txt,這個(gè)文件是 cmake的構(gòu)建定義文件,文件名 是大小寫(xiě)相關(guān)的,如果工程存在多個(gè)目錄,需要確保每個(gè)要管理的目錄都存在一個(gè) CMakelists.txt。(關(guān)于多目錄構(gòu)建,后面我們會(huì)提到,這里不作過(guò)多解釋)。 上面例子中的 CMakelists.txt文件內(nèi)容如下: PROJECT (HELLO) SET(SRC LIST main. c) MESSAGE (STATUS This is binary dir $HELLO BINARY DIRl) MESSAGE(STATUS This is source dir $HELLO SOURCE DIR]) ADD EXECUTABLE(hello ISRC LISTI) PR0JECT指令的語(yǔ)法是: PROJECT(projectname [CXX] [c] [Javal) 你可以用這個(gè)指令定義工程名稱(chēng),并可指定工程支持的語(yǔ)言,支持的語(yǔ)言列表是可以忽略的, 默認(rèn)情況表示支持所有語(yǔ)言。這個(gè)指令隱式的定義了兩個(gè) cmake變量: < projectname> BINARY DIR以及< projectname>S0URCE_DIR,這里就是 HELL0 BINARY DIR和HELL0S0 URCE DIR(所以 CMakelists.txt中兩個(gè) MESSAGE 指令可以直接使用了這兩個(gè)變量),因?yàn)椴捎玫氖莾?nèi)部編譯,兩個(gè)變量目前指的都是工程所 在路徑/ backup/ cmake/t1,后面我們會(huì)講到外部編譯,兩者所指代的內(nèi)容會(huì)有所不同 同時(shí) cmake系統(tǒng)也幫助我們預(yù)定義了PRO] ECT BINARY DIR和 PROJECT SOURCE DIR 變量,他們的值分別跟HELL0 BINARY DIR與HELL0 SOURCE DIR一致。 為了統(tǒng)一起見(jiàn),建議以后直接使用PR0 JECT BINARY DIR,PR0 JECT S0 URCE DIR,即 使修改了工程名稱(chēng),也不會(huì)影響這兩個(gè)變量。如果使用了 < projectname>s0URCE_D工R,修改工程名稱(chēng)后,需要同時(shí)修改這些變量。 SET指令的語(yǔ)法是: SET(VAR [VALUE [CACHE TYPE DOCSTRING [FORCE]l) 現(xiàn)階段,你只需要了解SET指令可以用來(lái)顯式的定義變量即可。 比如我們用到的是SET( SRC LIST main.C),如果有多個(gè)源文件,也可以定義成 SET(SRC LIST main. c tlc t2.c)o MESSAGE指令的語(yǔ)法是: MESSAGE([SEND ERROR STATUS FATAL ERROR] message to display 這個(gè)指令用于向終端輸出用戶定義的信息,包含了三種類(lèi)型: SEND ERROR,產(chǎn)生錯(cuò)誤,生成過(guò)程被跳過(guò)。 SATUS,輸出前綴為-的信息。 FATAL ERR0R,立即終止所有 cmake過(guò)程 我們?cè)谶@里使用的是 STATUS信息輸出,演示了由PR0]ECT指令定義的兩個(gè)隱式變量 HELL0 BINARY DIR和HELL0S0 URCE DIR。 ADd EXECUTABLE(helLo $ISRC listy) 定義了這個(gè)工程會(huì)生成一個(gè)文件名為 hello的可執(zhí)行文件,相關(guān)的源文件是 SRC LIST中 定義的源文件列表,本例中你也可以直接寫(xiě)成 ADD EXECUTABLE( hello main,C 在本例我們使用了${}來(lái)引用變量,這是 cmake的變量應(yīng)用方式,但是,有一些例外,比 如在工F控制語(yǔ)句,變量是直接使用變量名引用,而不需要${}。如果使用了$}去應(yīng)用變 量,其實(shí)IF會(huì)去判斷名為${}所代表的值的變量,那當(dāng)然是不存在的了。 將本例改寫(xiě)成一個(gè)最簡(jiǎn)化的 CMakelists.txt PROJECT(HELLO) ADd EXECUTABLE(hello main. c) 4,基本語(yǔ)法規(guī)則 前面提到過(guò), cmake其實(shí)仍然要使用" cmake語(yǔ)言和語(yǔ)法"去構(gòu)建,上面的內(nèi)容就是所謂的 " cmake語(yǔ)言和語(yǔ)法〃,最簡(jiǎn)單的語(yǔ)法規(guī)則是 1,變量使用$仍}方式取值,但是在IF控制語(yǔ)句中是直接使用變量名 2,指令(參數(shù)1參數(shù)2...) 參數(shù)使用括弧括起,參數(shù)之間使用空格或分號(hào)分開(kāi) 以上面的 ADD EXECUTABLE指令為例,如果存在另外一個(gè)func.C源文件,就要寫(xiě)成 ADD EXECUTABLE( hello main. c func,c)或者 ADD EXECUTABLE(hello main. c; func. c) 3,指令是大小寫(xiě)無(wú)關(guān)的,參數(shù)和變量是大小寫(xiě)相關(guān)的。但,推薦你全部使用大寫(xiě)指令 上面的 MESSAGE指令我們已經(jīng)用到了這條規(guī)則 MESSAGE(STATUS This is binary dir/ $HELLo BINARY DIR]) 也可以寫(xiě)成: MESSAGE(STATUS "This is binary dir $HELLO BINARY DIR") 這里需要特別解釋的是作為工程名的HELL0和生成的可執(zhí)行文件 hello是沒(méi)有任何關(guān)系的。 heLo定義了可執(zhí)行文件的文件名,你完全可以寫(xiě)成: ADD EXECUTABLE(tl main. c) 編譯后會(huì)生成一個(gè)t1可執(zhí)行文件。 5,關(guān)于語(yǔ)法的疑惑 cmake的語(yǔ)法還是比較靈活而且考慮到各種情況,比如 SET( SRC LIST main.C)也可以寫(xiě)成SET( SRC LIST“main.C") 是沒(méi)有區(qū)別的,但是假設(shè)一個(gè)源文件的文件名是func.C(文件名中間包含了空格)。 這時(shí)候就必須使用雙引號(hào),如果寫(xiě)成了SET( SRC List fu nd.c),就會(huì)出現(xiàn)錯(cuò)誤,提示 你找不到fu文件和nc.C文件。這種情況,就必須寫(xiě)成 SET( SRC LIST“func.C 此外,你可以可以忽略掉 source列表中的源文件后綴,比如可以寫(xiě)成 ADD EXECUTABLE(t1main), cmake會(huì)自動(dòng)的在本目錄查找main.C或者main.Cpp 等,當(dāng)然,最好不要偷這個(gè)懶,以免這個(gè)目錄確實(shí)存在一個(gè)main.C一個(gè)main 同時(shí)參數(shù)也可以使用分號(hào)來(lái)進(jìn)行分割。 下面的例子也是合法的: ADD EXECUTABLE(t1main.Ct1.c)可以寫(xiě)成 ADD EXECUTABLE(t1 main. c; tl.c) 我們只需要在編寫(xiě) CMakelists.txt時(shí)注意形成統(tǒng)一的風(fēng)格即可 6,清理工程: 跟經(jīng)典的 autotools系列工具一樣,運(yùn)行: make clean 即可對(duì)構(gòu)建結(jié)果進(jìn)行清理。 7,問(wèn)題?問(wèn)題 我嘗試運(yùn)行了 make distclean,這個(gè)指令一般用來(lái)清理構(gòu)建過(guò)程中產(chǎn)生的中間文件的 如果要發(fā)布代碼,必然要清理掉所有的中間文件,但是為什么在 cmake工程中這個(gè)命令是 無(wú)效的? 是的, cmake并不支持 make distclean,關(guān)于這一點(diǎn),官方是有明確解釋的: 因?yàn)?CMakelists.txt可以執(zhí)行腳本并通過(guò)腳本生成一些臨時(shí)文件,但是卻沒(méi)有辦法來(lái)跟 蹤這些臨時(shí)文件到底是哪些。因此,沒(méi)有辦法提供一個(gè)可靠的 make distclean方案。 Some build trees created with gnu autotools have a make distclean" target that cleans the build and also removes Makefiles and other parts of the generated build system make does not generate a"make distclean"target because CMakeLists. txt files can run scripts and arbitrary commands CMake has no way of tracking exactly which files are generated as part of running
代碼片段和文件信息
評(píng)論
共有 條評(píng)論