CMakeLists.txt 介紹
阿新 • • 發佈:2018-12-10
CMake 簡要內容
CMake 是cross platform make的簡寫,從這裡你完全可以看出,CMake是基於Make來實現相關的內容的,換句話說,CMake就是在Make的基礎上抽象出來的更高階的框架。
CMakeLists.txt的編譯test.cpp生成test可執行檔案的基本例子:
<span style="color:#000000"><code class="language-CMake"><span style="color:#000088">cmake_minimum_required</span>(VERSION <span style="color:#006666">2.8</span>.<span style="color:#006666">10</span>) <span style="color:#000088">SET</span>(PROJECT_NAME test) <span style="color:#000088">project</span>(<span style="color:#666600">${PROJECT_NAME}</span>) <span style="color:#000088">add_executable</span>(test test.cpp) </code></span>
- 1
- 2
- 3
- 4
通過以下Shell Command:
<span style="color:#000000"><code class="language-Shell">mkdir -p build && <span style="color:#4f4f4f">cd</span> build && cmake .. && make </code></span>
- 1
通過上文的shell命令,其實你也已經發現了,cmake會生成Makefile,然後我們需要呼叫make來生成可執行檔案。
CMakeLists.txt 編寫要點
常用的cmake指令解釋
<span style="color:#000000"><code class="language-CMake"><span style="color:#000088">cmake_minimum_required</span>(VERSION xxx) <span style="color:#880000">#cmake最小版本需求,新版本的cmake改了很多東西,提升了便利性,也可能讓你自己挖坑了</span> <span style="color:#000088">project</span>(xxx) <span style="color:#880000">#設定此專案的名稱</span> <span style="color:#000088">add_executable</span>(target target_source_codes) <span style="color:#880000">#生成可執行檔案target ,後面填寫的是生成此可執行檔案所依賴的原始檔列表。</span> <span style="color:#000088">SET</span>(var_name var_value)<span style="color:#880000"># 設定一個名字var_name 的變數,同時給此變數賦值為var_value</span> <span style="color:#000088">MESSAGE</span>(<span style="color:#009900">"MSG"</span>) <span style="color:#880000">#類比echo 列印訊息</span> <span style="color:#000088">option</span>(var_name <span style="color:#009900">"comment"</span> var_value) <span style="color:#880000">#給變數var_name賦值為var_value,comment是此變數的註釋,和SET 有類似的功效,用於給某變數設定預設值</span> <span style="color:#000088">include_directories</span>(xxx) <span style="color:#880000">#新增include路徑,也就是 gcc -I xxx 的意思,或者vs ide中新增標頭檔案包含目錄</span> <span style="color:#000088">add_subdirectory</span>(xxx) <span style="color:#880000">#呼叫xxx子目錄的CMakeLists.txt執行</span> add_compile_options(xxx) <span style="color:#880000">#給編譯器新增xxx引數,但是貌似沒有什麼用,我一般不這樣新增引數,不直接</span> <span style="color:#000088">link_directories</span>(xxx) <span style="color:#880000">#給編譯器新增庫目錄,也就是 gcc -L xxx 的意思,或者vs ide中新增庫的包含目錄</span> <span style="color:#000088">add_library</span>(lib_name SHARED <span style="color:#000088">or</span> STATIC lib_source_code) <span style="color:#880000">#和add_executable類似,生成庫檔案,SHARED代表動態庫,STATIC代表靜態庫, 最後一個引數代表此庫的原始檔列表,此指令只有三個引數</span> <span style="color:#000088">target_link_libraries</span>(target_name lib_name ...) <span style="color:#880000">#給目標新增依賴庫,類似與gcc -l lib_name,此指令有兩個用處,一個是給可執行target_name 新增庫依賴,二是給庫target_name 新增庫依賴。</span> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
我常見的cmake指令也就是上述的這些,還有部分比較常見的指令這裡沒有列出,我放到了下面單獨講解如:install()
cmake 流控制指令相關
條件語句
<span style="color:#000000"><code class="language-CMake"><span style="color:#000088">if</span>(xxx)
<span style="color:#000088">...</span>
elseif(xx)
<span style="color:#000088">...</span>
<span style="color:#000088">else</span>()
<span style="color:#000088">...</span>
endif()
<span style="color:#880000">#常見條件語句用法為:</span>
<span style="color:#880000"># if (va) va為bool型</span>
<span style="color:#880000"># if (va MATCHES xxx) va 是string型別,如果va包含了xxx,則此句為真</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
迴圈語句
<span style="color:#000000"><code class="language-CMake">foreach(va va_lists)
<span style="color:#000088">...</span>
endforeach()</code></span>
- 1
- 2
- 3
在foreach中,va的值會依次被va_lists的值替換
macro 和 function
<span style="color:#000000"><code class="language-CMake">macro(name arg <span style="color:#000088">...</span>)
<span style="color:#000088">...</span>
endmacro()
<span style="color:#000088">function</span>(name arg <span style="color:#000088">...</span>)
<span style="color:#000088">...</span>
endfunction()</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
巨集和函式效果都類似,唯一區別為function中的變數為區域性的。
install 指令(主要是生成Makefile中的install target)
<span style="color:#000000"><code class="language-CMake"><span style="color:#000088">install</span>(FILES flie DESTINATION dir_path) <span style="color:#880000">#執行make install時,把file拷貝到dir_path</span>
<span style="color:#000088">install</span>(PROGRAMS file DESTINATION dir_path) <span style="color:#880000">#執行make install時,把file拷貝到dir_path,並給予file可執行許可權</span>
<span style="color:#000088">INSTALL</span>(TARGETS ylib ylib_s
<span style="color:#880000">#RUNTIME DESTINATION xxx</span>
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)<span style="color:#880000"># 安裝libylib.so到lib目錄,安裝libylib_s.a到lib目錄,RUNTIME 是安裝可執行檔案到xxx目錄,注意這個指令有個坑,我後面會說明這個問題。</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
configure_file指令
<span style="color:#000000"><code class="language-CMake">configure_file(fileA fileB <span style="color:#4f4f4f">@ONLY</span>)
#把fileA 複製並重命名為fileB,此時,fileA中的<span style="color:#4f4f4f">@var</span><span style="color:#4f4f4f">@的</span>值會被替換為cmakelists.txt 中var的值。<span style="color:#4f4f4f">@ONLY</span>是隻轉換<span style="color:#4f4f4f">@va</span><span style="color:#4f4f4f">@這</span>種變數</code></span>
- 1
- 2
CMakeLists.txt常用的內建變數
<span style="color:#000000"><code class="language-CMake">CMAKE_INSTALL_PREFIX <span style="color:#880000">#make install 的安裝路徑</span>
CMAKE_BUILD_TYPE <span style="color:#880000">#生成的目標為debug或者release</span>
CMAKE_C_FLAGS <span style="color:#880000">#gcc 的編譯引數指定,這個非常好用,一般通過set 修改其值</span>
CMAKE_CXX_FLAGS <span style="color:#880000">#g++ 和上面CMAKE_C_FLAGS 類似</span>
CMAKE_CURRENT_SOURCE_DIR <span style="color:#880000"># 當前CMakeLists.txt所在的目錄,主要用來定位某檔案</span>
CMAKE_CURRENT_BINARY_DIR <span style="color:#880000"># 當前CMakeLists.txt對應的編譯時的目錄</span>
</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
XXXConfig.cmake檔案(cmake模組檔案)編寫以及引用
yLibConfig.cmake
<span style="color:#000000"><code class="language-CMake">
<span style="color:#000088">find_path</span>(yLib_INCLUDE_DIR NAMES ylib.h PATHS @[email protected]/<span style="color:#000088">include</span>)
<span style="color:#000088">find_library</span>(yLib_LIBRARY NAMES ylib PATHS @[email protected]/lib)
<span style="color:#880000">#find_library 會到@[email protected]/lib目錄查詢libylib.so</span>
<span style="color:#000088">set</span>(yLib_FOUND <span style="color:#000088">TRUE</span>)
<span style="color:#000088">set</span>(yLib_INCLUDE_DIRS <span style="color:#666600">${yLib_INCLUDE_DIR}</span>)
<span style="color:#000088">set</span>(yLib_LIBS <span style="color:#666600">${yLib_LIBRARY}</span>)
<span style="color:#000088">mark_as_advanced</span>(yLib_INCLUDE_DIRS yLib_LIBS )</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
XXX_INCLUDE_DIR XXX_LIBRARY XXX_FOUND XXX_INCLUDE_DIRS XXX_LIBS 以上變數最好都定義了,不然find_package可能會報錯 .cmake 檔案就是定義了相關include變數和lib變數,沒有什麼其他的東西
呼叫:
<span style="color:#000000"><code class="language-Cmake"><span style="color:#000088">set</span>(yLib_DIR <span style="color:#009900">"@[email protected]/cmake"</span>)
<span style="color:#009900">#設定.cmake 的目錄所在</span>
find_package(yLib REQUIRED)
<span style="color:#009900">#find_package會匯入.cmake 中的相關變數,完成相關模組的匯入</span></code></span>
- 1
- 2
- 3
- 4
一個關於install()指令的深坑
<span style="color:#000000"><code class="language-CMake">INSTALL(TARGETS ylib ylib_s
#RUNTIME<span style="color:#009900"> DESTINATION </span>xxx
<span style="color:#009900"> LIBRARY </span>DESTINATION lib
<span style="color:#009900"> ARCHIVE </span>DESTINATION lib
)
<span style="color:#009900">#對於RUNTIME 和 LIBRARY 兩種目標,在安裝時候,cmake會預設給你移除掉目標檔案中的gcc的Wl,rpath的值,導致某些庫找不到的錯誤。</span>
以下變數會影響此坑,更詳細的資訊去查查別的資料,我這裡就不詳細說明了。
<span style="color:#009900">#set(CMAKE_SKIP_BUILD_RPATH FALSE) </span>
<span style="color:#009900">#set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) </span>
<span style="color:#009900">#set(CMAKE_INSTALL_RPATH "") </span>
<span style="color:#009900">#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) </span>
<span style="color:#009900">#set(CMAKE_SKIP_INSTALL_RPATH TRUE)</span>
<span style="color:#009900">#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")</span>
<span style="color:#009900">#set(CMAKE_SKIP_RPATH TRUE)</span>
<span style="color:#009900">#set(CMAKE_SKIP_INSTALL_RPATH TRUE)</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
注意:cmake會直接修改你的二進位制檔案替換掉rpath的相關資訊。預設替換的值是一個空值,也就是說移除掉了你設定的rpath的值