天天看點

【整理】CMake 介紹和 CMake 實踐

【cmake 優點】:

開放源代碼,使用 bsd 許可證釋出。

跨平台,可以生成 native 編譯配置檔案。在 linux/unix 平台可以生成 makefile,在 mac 平台可以生成 xcode,在 windows 平台可以生成 msvc 工程的配置檔案。

能夠管理大型項目。

簡化編譯建構過程和編譯過程,隻需要 cmake + make 就可以。

高效率。

可擴充,可以為 cmake 編寫特定功能的子產品,擴充 cmake 功能。

【如何安裝 cmake】:

1. cmake 的安裝可以使用 autotools 進行安裝,點選cmake-2.8.6.tar.gz連結,可以對軟體進行下

2. 執行 ./configure; make; make install

【cmake的原理】 

準備main.cpp檔案

<a href="http://my.oschina.net/moooofly/blog/89722#">?</a>

1

2

3

4

5

6

7

8

9

<code>//main.cpp</code>

<code>#include&lt;cstdio&gt;</code>

<code>int</code> <code>main()</code>

<code>{</code>

<code>    </code><code>printf</code><code>(</code><code>"hello world from main\n"</code><code>);</code>

<code>    </code><code>return</code> <code>0;</code>

<code>}</code>

a.建立 cmakelists.txt(注意:此檔案名大小寫必須如此命名),向該檔案中加入以下幾行(内容中指令的大小寫無所謂):

<code>project (hello)</code>

<code>set(src_list main.cpp)</code>

<code>message(status</code><code>"this is binary dir "</code> <code>${hello_binary_dir})</code>

<code>message(status</code><code>"this is source dir "</code><code>${hello_source_dir})</code>

<code>add_executable(hello ${src_list})</code>

b.運作以下指令(linux下):

<code>$ cmake .                (别忘記加上這個點,表示目前目錄)</code>

【整理】CMake 介紹和 CMake 實踐

執行完該指令後執行ls可以看到:

【整理】CMake 介紹和 CMake 實踐

生成了cmakefiles(目錄)、cmakecache.txt、cmake_install.cmake以及makefile檔案。

c.執行make。

【整理】CMake 介紹和 CMake 實踐

這時目前目錄下就會生成可執行檔案:

【整理】CMake 介紹和 CMake 實踐

【例子解釋】:

上面cmakelists.txt的内容重新列出如下: 

project指令的文法:

project(projectname [cxx] [c] [java]) 

該指令用來定義工程名稱和工程支援的語言。這個指令也同時隐式定義了兩個cmake變量:&lt;projectname&gt;_binary_dir以及&lt;projectname&gt;_source_dir。

在該例子中就是hello_binary_dir和hello_source_dir,兩個變量指的都是目前工程的路徑。 

set指令的文法:

set(var[value] [cache type docstring [force]]) 

set指令是用來顯式的定義變量的,我們之前用到的是set(src_list main.cpp),如果有多個源檔案,也可以定義成set(src_list main.cpp t1.cpp t2.cpp)。 

message指令的文法是:

message([send_error | status | fatal_error] "message to display" ...) 

這個指令用于向終端輸出使用者資訊,包含三種類型:

send_error,産生錯誤,生成過程被跳過。

satus,輸出字首為-的資訊。

fatal_error,立即終止所有cmake過程。 

上例使用的是status類型進行資訊輸出,用于顯示由project指令隐式定義的兩個變量hello_binary_dir和hello_source_dir的值。 

add_executable(hello ${src_list})

定義了這個,工程會生成一個檔案名為hello的可執行檔案,相關的源檔案是src_list中定義的源檔案清單,本例中你可以直接寫成add_executable(hello main.c)。

本例cmakelists.txt的最簡化形式:

<code>project(hello)</code>

<code>add_executable(hello main.c)</code>

=== 我是分割線 ===

下面我們介紹一個比較實用的例子,既包含生成靜态庫又包含引入外部頭檔案和連結庫的cmake demo。

先按照工程規範建立工程目錄并編寫代碼,以下面的工程目錄為例進行解釋這個例子,工程的目錄結構為:

【整理】CMake 介紹和 CMake 實踐

編譯工程要實作的目标:

添加子目錄doc,用以放置這個工程的文檔hello.txt。

生成hello的靜态庫,并在main可執行程式連結hello靜态庫。

在這個工程中添加copyright和readme檔案。

在工程目錄中添加一個run.sh的腳本,用以調用生成的二進制可執行檔案。

将生成的二進制檔案生成到bin子目錄中。

編寫安裝程式。 

1. 編寫cmakelists.txt

      由于一個工程目錄中包含多個項目,其中在此項目中包含util項目和main項目,其中util項目是用以生成main程式需要的靜态庫,main是用以生成可執行檔案。

      在整個工程項目的根目錄下的cmakelists.txt是用來定義工程需要的cmake設定以及子目錄src,用以遞歸調用src中的makelists.txt。該cmakelists.txt的内容定義如下: 

<code>add_subdirectory(src)</code>

      目錄src中的cmakelists.txt用以定義src目錄下包含的兩個工程(main和util)的依賴關系。

      目錄util裡面的cmakelists.txt是用以定義生成util靜态庫的規則,其中内容如下:

<code>set(library_output_path ${hello_source_dir}</code><code>/lib</code><code>)</code>

<code>set(cmake_c_compiler g++)</code>

<code>set(src_list hello.c)</code>

<code>include_directories(${hello_source_dir}</code><code>/include</code><code>)</code>

<code>add_library(util static ${src_list})</code>

set(library_output_path ${hello_source_dir}/lib) -- 定義了庫生成的路徑,内部變量library_output_path用于存放庫的生成路徑。 

set(cmake_c_compiler g++) -- 定義c的編譯器為g++,防止出現c和c++代碼在不指定c編譯器的情況下預設使用gcc,導緻系統編譯混亂。 

set(src_list hello.c) -- 定義庫檔案需要的源檔案。

include_directories(${hello_source_dir}/include) -- 定義非标準庫頭檔案要搜尋的路徑。 

其中include_directories指令的格式為:

include_directories([after|before] [system] dir1 dir2 ...)

add_library(util static ${src_list}) -- 定義生成庫的名字、類型和庫所需要的源檔案,

其中add_library指令格式為:

add_library(libname [shared|static|module] [exclude_from_all]

source1 source2 ... sourcen)

      目錄main裡面的cmakelists.txt是用來定義可執行程式編譯和連結時所需要的一些指令或環境。内容如下: 

<code>set(executable_output_path ${hello_source_dir}</code><code>/bin</code><code>)</code>

<code>link_directories(${hello_source_dir}</code><code>/lib</code><code>)</code>

<code>target_link_libraries(hello util)</code>

include_directories(${hello_source_dir}/include) -- 定義工程引用的include檔案夾位置,其中存放使用到的庫的頭檔案。

link_directories(${hello_source_dir}/lib) -- 定義工程引用的庫檔案位置,其中存放着庫檔案。

add_executable(hello ${src_list}) -- 定義生成的可執行檔案。

target_link_libraries(hello util) -- 用以定義連結時需要的庫檔案。 

2.在工程目錄下建立build目錄,并采用out-of-source方式編譯項目。執行指令

<code>$ cmake ..</code>

執行結果如下

【整理】CMake 介紹和 CMake 實踐

執行tree指令,這時在build目錄下生成了中間編譯檔案:

<code>$ tree .</code>

【整理】CMake 介紹和 CMake 實踐

執行make指令,結果如下:

【整理】CMake 介紹和 CMake 實踐

可以看到工程建立和編譯成功了。 

3. 安裝

      在工程目錄下添加copyright、readme和run.sh,重新編輯工程目錄下的cmakelists.txt。在cmakelists.txt中添加如下指令: 

<code>install(files copyright readme destination share</code><code>/doc/cmake_demo</code><code>)</code>

<code>install(programs run.sh destination bin)</code>

<code>install(programs bin</code><code>/hello</code> <code>destination bin)</code>

<code>install(directory doc/ destination share</code><code>/doc/cmake_demo</code><code>)</code>

      這些指令表示在執行make install指令時,安裝程式會拷貝相應的檔案、目錄或程式到指定的字首開始的目錄中,cmake執行指令如下: 

<code>cmake -dcmake_install_prefix=~</code><code>/data/cmake_demo</code> <code>..</code>

      這時将工程目錄安裝到~/data/cmake_demo目錄下。執行結果如下:

【整理】CMake 介紹和 CMake 實踐

其中cmake編譯c、c++工程完畢。