1. 程式人生 > >CMakeLists學習筆記

CMakeLists學習筆記

一、CMakeLists使用方法
1、語法
1)#註釋
2)變數:使用set命令顯式定義及賦值,在非if語句中,使用 ${} 引用,在if中直接使用變數名引用;後續的set命令會清理變數原來的值
3)command(args...) 命令不分大小寫,引數使用空格分隔,使用雙引號引起引數中的空格
4)set(var a;b;c)<=>set(var a b c)#定義變數var並賦值為a;b;c這樣一個string list
5)add_executable(${var}) <=> add_executable(a b c) #變數使用${}引用
6)條件語句
if(var) #var 非empty o N No OFF False... #非運算子使用NOT

...

else/elseif()...endif(var)
7)迴圈語句
set(var a b c)
foreach(f ${var})   ...endforeach(f)

8)迴圈語句
while()...endwhile()

2、內部變數
CMAKE_C_COMPILER :制定C編譯器
EXECUTABLE_OUTPUT_PATH:可執行檔案存放路徑
LIBRARY_OUT_PATH: 庫檔案路徑
CMAKE_BUILD_TYPE: build型別(Debug, Release,...)
BUILD_SHARED_LIBS:選擇靜態.a或者動態連結庫.so
內建變數的使用:
>> 在CMakeLists.txt中指定,使用set

>> cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF
3、命令
project (HELLO)   #指定專案名稱,生成的VC專案的名稱;
>>使用${HELLO_SOURCE_DIR}表示專案根目錄
include_directories:指定標頭檔案的搜尋路徑,相當於指定gcc的-I引數
>> include_directories (${HELLO_SOURCE_DIR}/Hello)  #增加Hello為include目錄

link_directories:動態連結庫或靜態連結庫的搜尋路徑,相當於gcc的-L引數
>> link_directories (${HELLO_BINARY_DIR}/Hello)     #增加Hello為link目錄

add_subdirectory:包含子目錄
>> add_subdirectory (Hello)

add_executable:編譯可執行程式,指定編譯,好像也可以新增.o檔案
 >> add_executable (helloDemo demo.cxx demo_b.cxx)   #將cxx編譯成可執行檔案——

add_definitions:新增編譯引數
>> add_definitions(-DDEBUG)將在gcc命令列新增DEBUG巨集定義;
>> add_definitions( “-Wall -ansi –pedantic –g”)

target_link_libraries:新增連結庫,相同於指定-l引數
>> target_link_libraries(demo Hello) #將可執行檔案與Hello連線成最終檔案demo

add_library:
>> add_library(Hello hello.cxx)  #將hello.cxx編譯成靜態庫如libHello.a

add_custom_target:
message( status|fatal_error, “message”):
set_target_properties( ... ): lots of properties... OUTPUT_NAME, VERSION, ....
link_libraries( lib1 lib2 ...): All targets link with the same set of libs

MESSAGE("MSG") #類比echo 列印訊息
option(var_name "comment" var_value) #給變數var_name賦值為var_value,comment是此變數的註釋,和SET 有類似的功效,用於給某變數設定預設值

link_directories(xxx)
#給編譯器新增庫目錄,類似vs ide中新增庫的包含目錄
add_library(lib_name SHARED or STATIC lib_source_code)
#和add_executable類似,生成庫檔案,SHARED代表動態庫,STATIC代表靜態庫, 最後一個引數代表此庫的原始檔列表,此指令只有三個引數
target_link_libraries(target_name lib_name ...)
 #給目標新增依賴庫,類似與gcc -l lib_name,此指令有兩個用處,一個是給可執行target_name 新增庫依賴,二是給庫target_name 新增庫依賴。

install 指令(主要是生成Makefile中的install target)
install(FILES flie DESTINATION dir_path)
#執行make install時,把file拷貝到dir_path
install(PROGRAMS file DESTINATION dir_path)
 #執行make install時,把file拷貝到dir_path,並給予file可執行許可權
INSTALL(TARGETS ylib ylib_s
#RUNTIME DESTINATION xxx
 LIBRARY DESTINATION lib
 ARCHIVE DESTINATION lib )
# 安裝libylib.so到lib目錄,安裝libylib_s.a到lib目錄,RUNTIME 是安裝可執行檔案到xxx目錄,注意這個指令有個坑,我後面會說明這個問題。

install指令的坑
INSTALL(TARGETS ylib ylib_s
#RUNTIME DESTINATION xxx  
LIBRARY DESTINATION lib
 ARCHIVE DESTINATION lib )
 #對於RUNTIME  和 LIBRARY 兩種目標,在安裝時候,cmake會預設給你移除掉目標檔案中的gcc的Wl,rpath的值,導致某些庫找不到的錯誤。
 以下變數會影響此坑,更詳細的資訊去查查別的資料,我這裡就不詳細說明了。
#set(CMAKE_SKIP_BUILD_RPATH FALSE)                
#set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)       
#set(CMAKE_INSTALL_RPATH "")
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#set(CMAKE_SKIP_INSTALL_RPATH TRUE)
#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
#set(CMAKE_SKIP_RPATH TRUE)
#set(CMAKE_SKIP_INSTALL_RPATH TRUE)

二、CMake如何查詢連結庫——find_package
帽子:
如果編譯軟體使用了外部庫,事先並不知道它的標頭檔案和連結庫的位置。得在編譯命令中加上包含它們的查詢路徑。CMake使用 find_package()命令來解決這個問題。
語法:find_package(<Name>)
如果找到這個包,則可以通過在工程的頂層目錄中的CMakeLists.txt 檔案新增 include_directories(<NAME>_INCLUDE_DIRS) 來包含庫的標頭檔案,新增target_link_libraries(原始檔 <NAME>_LIBRARIES)命令將原始檔與庫檔案連結起來
栗子:
cmake_minimum_required(VERSION 2.8)
project(helloworld)
add_executable(helloworld hello.c)
find_package(BZip2)
if (BZIP2_FOUND)
include_directories(${BZIP_INCLUDE_DIRS})
target_link_libraries (helloworld ${BZIP2_LIBRARIES})
endif (BZIP2_FOUND)

FIND_PACKAGEFIND_PACKAGE(<name>[version][EXACT][QUIET][NO_MODULE] [[REQUIRED|COMPONENTS][componet...])
PROJECT_NAME 返回通過PROJECT指令定義的專案名稱

參考:

簡書網學習筆記: https://www.jianshu.com/p/c417e4ab8b30