CMake: (四) CMake語法規則


CMake支持大寫、小寫、混合大小寫的命令


實例一

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)  #聲明Cmake版本,如果低於指定版本則會停止處理工程文件,並報告錯誤
PROJECT(XXX)
 
SET(CMAKE_BUILD_TYPE Release)
SET(CMAKE_CXX_FLAGS "-std=c++11 -O2 -mfloat-abi=hard -mfpu=neon")
 
#micro
#ADD_DEFINITIONS( -DENABLE_OPENCV -D__SDK4__)
 
#include and libs path
SET(INCLUDE_PATH . ../ /usr/include/eigen3 /srv/boost_1_63_0 )
 
SET(LINK_PATH /srv/boost_1_63_0/stage/lib )
 
INCLUDE_DIRECTORIES(${INCLUDE_PATH})
LINK_DIRECTORIES(${LINK_PATH} )
 
#source files in dir
 
#dir CommonH
AUX_SOURCE_DIRECTORY(filepath name)
 
#execuable
ADD_EXECUTABLE(XX mainV2.cpp ${name} )
 
TARGET_LINK_LIBRARIES(XX libnames)

語法分析

CMAKE_MINIMUM_REQUIRED

聲明Cmake版本,如果低於指定版本則會停止處理工程文件,並報告錯誤,語法為

CMAKE_MINIMUM_REQUIRED(VERSION major[.minor[.patch[.tweak]]] [FATAL_ERROR])

PROJECT(PROJECTNAME)

PROJECT(PROJECTNAME [CXX] [C])

可選項: [指定工程支持的語言,如果忽略,表示支持所有語言]

ADD_DEFINITIONS

ADD_DEFINITIONS( -DENABLE_OPENCV -D__SDK4__)

添加編譯參數

CMAKE_BUILD_TYPE

設置構建工程類型

INCLUDE_DIRECTORIES

添加頭文件目錄

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

它相當於g++選項中的-I參數的作用,也相當於環境變量中增加路徑到CPLUS_INCLUDE_PATH變量的作用。

添加需要鏈接的庫文件目錄

LINK_DIRECTORIES(directory1 directory2 ...)

它相當於g++命令的-L選項的作用,也相當於環境變量中增加LD_LIBRARY_PATH的路徑的作用。

添加需要鏈接的庫文件路徑

LINK_LIBRARIES(library1 <debug | optimized> library2 ...)

使用實例

link_libraries(“/home/install/libopencv_core.so”) #直接是全路徑
link_libraries(opencv_highgui) #下只有庫名,cmake會自動去所包含的目錄搜索
link_libraries(${RUNTIME_LIB}) #傳入變量
link_libraries("/srv/lib-aarch64/libboost_atomic.so" "/srv/lib-aarch64/libpcl_common.so") #也可以鏈接多個,需要空格間隔

設置要鏈接的庫文件的名稱

TARGET_LINK_LIBRARIES (<target> [item1 [item2 [...]]][[debug|optimized|general] <item>] ...)

如下寫法都可以

TARGET_LINK_LIBRARIES (ProjectName comm)       # 連接libhello.so庫,默認優先鏈接動態庫
TARGET_LINK_LIBRARIES (ProjectName libcomm.a)  # 顯示指定鏈接靜態庫
TARGET_LINK_LIBRARIES (ProjectName libcomm.so) # 顯示指定鏈接動態庫
TARGET_LINK_LIBRARIES (ProjectName -lcomm)

ADD_EXECUTABLE

為工程生成目標文件

add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 [source2 ...])

AUX_SOURCE_DIRECTORY

查找指定目錄下的所有源文件,然后將結果存進指定變量名

AUX_SOURCE_DIRECTORY(<dir> <variable>)

ADD_LIBRARY

ADD_LIBRARY(NAME [STATIC| SHARED|MODULE] [EXCLUDE_FROM_ALL] source1, source2,...)
  • <name> : 庫的名字,直接寫名字即可,不要寫lib,會自動加上前綴
  • 庫類型:[STATIC | SHARED | MODULE] 三種。
SHARED,動態庫
STATIC,靜態庫
MODULE,在使用 dyld 的系統有效,如果不支持 dyld,則被當作 SHARED 對待。
  • EXCLUDE_FROM_ALL:這個庫不會被默認構建,除非有其他的組件依賴或者手工構建

SET_TARGET_PROPERTIES

設置動態庫的版本號

#VERSION 指代動態庫版本,SOVERSION 指代 API 版本。
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)

其實不管你的動態庫版本是什么,對外調用總是libxxx.so

MESSAGE

打印過程信息

 MESSAGE( [STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR]"message to display" ...)

可選項說明

 (無) = 重要消息;
 STATUS = 非重要消息;
 WARNING = CMake 警告, 會繼續執行;
 AUTHOR_WARNING = CMake 警告 (dev), 會繼續執行;
 SEND_ERROR = CMake 錯誤, 繼續執行,但是會跳過生成的步驟;
 FATAL_ERROR = CMake 錯誤, 終止所有處理過程;

編譯和鏈接選項

全局設置

SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -DEMBED")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS } -DEMBED")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")

這種寫法的好處是,不會覆蓋CMAKE_CXX_FLAGS本來的信息。只是把需要添加的內容添加進去.

針對特定工程類型的設置

CMAKE_BUILD_TYPE = Debug/Release
CMAKE_CXX_FLAGS_DEBUG = "${CMAKE_CXX_FLAGS_DEBUG} -DXXX"
CMAKE_CXX_FLAGS_RELEASE = "${CMAKE_CXX_FLAGS_RELEASE} -DXXX"

當CMAKE_BUILD_TYPE設置為Debug,則編譯時采用CMAKE_CXX_FLAGS_DEBUG。
當CMAKE_BUILD_TYPE設置為Release,則編譯時采用CMAKE_CXX_FLAGS_RELEASE.

#set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -Wno-unused-but-set-variable")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -Wno-unused-but-set-variable")

多目錄結構的cmake使用

假設一個工程Hello,實際的目錄結構其實並不是所有源碼都存放在src目錄內。它的目錄結構是:

src: 存放生成庫的源碼。source1.cpp, source2.cpp
test:存放使用庫的測 試程序: main.cpp
include: 存放頭文件: source1.h
resource: 存放第三方庫
build:存放編譯過程的文件
build/lib: 存放生成的libv4l2_utils.so
build/bin:存放main.cpp所產生的測試程序可執行文件。

此時,可以采用頂層目錄和每個有源碼的目錄中均創建CMakeLists.txt的方式來處理(和Makefile處理方式類似),頂層目錄的CMakeLists.txt 內容如下:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(Hello)
ADD_SUBDIRECTORIES(src lib)
ADD_SUBDIRECTORIES(test bin)

ADD_SUBDIRECTORIES

構建添加一個子路徑

ADD_SUBDIRECTORIES([source dir] [bin dir] [exclude_from_all])
  • source_dir選項指定了CMakeLists.txt源文件和代碼文件的位置。如果source_dir是一個相對路徑,那么source_dir選項會被解釋為相對於當前的目錄,但是它也可以是一個絕對路徑。binary_dir選項指定了輸出文件的路徑。如果binary_dir是相對路徑,它將會被解釋為相對於當前輸出路徑。

SOURCE_DIR算相對路徑時,是從CMakeLists.txt算起。所以src指的是當前 CMakeLists.txt所在路徑下的src. 而bin, lib 指的是當前輸出路徑下的bin,lib. 也就是build/bin build/lib

src內的CMakeLists.txt

SET(LIB_SRC_LIST source1.cpp)
SET(CMAKE_BUILD_TYPE Release)
INCLUDE_DIRECTORIES(../include)
ADD_LIBRARY(SOURCE1 SHARED ${LIB_SRC_LIST})

test內的CMakeLists.txt

SET(EXEC_SRC_LIST main.cpp)
SET(INCLUDE_DIRECTORIES ../include)
SET(LINK_DIR ../../resource)
SET(LINK_DIR "${LINK_DIR} ../../libs/")
SET(CMAKE_BUILD_TYPE Release)
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})
LINK_DIRECTORIES(${LINK_DIR})
ADD_EXECUTABLE(Test_Hello ${EXEC_SRC_LIST})
TARGET_LINK_LIBRARIES(Test_Hello SOURCE1 )

文件移動

將某一個工程放置於某一個文件夾下(指的是工程位於某目錄下)

SET_PROPERTY(TARGET NetLib PROPERTY FOLDER "Common")

將NetLib移動到Common文件夾下

INSTLLL(FILES ${CMAKE_LINK_PATH}/odbc/libodbc.so DESTINATION bin)

將動態庫移動到bin目錄下

顯示編譯細節

SET(CMAKE_VERBOSE_MAKEFILE ON)

如果不希望改變CMakeLists.txt,可以在創建Makefile時候加入

cmake -DCMAKE_VERBOSE_MAKEFILE=ON

如果連Makefile都不希望修改可以:make VERBOSE=1

相對路徑

SET(LIBRARY_DIRECTORIES ../resource)
LINK_DIRECTORIES(${LIBRARY_DIRECTORIES})

這里會出警告:

This command specifies the relative path:../resource

可以做如下處理:

SET(LIBRARY_DIRECTORIES ../resource)
LINK_DIRECTORIES($PROJECT_SOURCE_DIR}/${LIBRARY_DIRECTORIES})

但是如果LIBRARY_DIRECTORIES 是個列表的話,此種方式仍然會引起警告。

CMakeList.txt所在位置

CMAKE_CURRENT_SOURCE_DIR
CMAKE_CURRENT_BINARY_DIR
PROJECT_SOURCE_DIR
PROJECT_BIANRY_DIR

內部編譯時,以上四種變量沒有區別,都是CMakeLists.txt所在位置,但是外部編譯時

CMAKE_CURRENT_BINARY_DIR
PROJECT_BIANRY_DIR

在build文件夾


FIND_PACKAGE

可以被用來在系統中自動查找配置構建工程所需的程序庫。在linux和unix類系統下這個命令尤其有用。CMake自帶的模塊文件里有大半是對各種常見開源庫的find_package支持,支持庫的種類非常多,例如

FIND_PACKAGE(OpenCV 2.4 REQUIRED COMPONENTS core highgui)
函數定義如下
```bash
FIND_PACKAGE( Name [version] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [components...]] [NO_POLICY_SCOPE])

查找並加載外來工程的設置。該命令會設置Name_FOUND變量,用來指示要找的包是否被找到了。如果這個包被找到了,與它相關的信息可以通過包自身記載的變量中得到。REQUIRED選項表示如果報沒有找到的話,cmake的過程會終止,並輸出警告信息。

  • 在REQUIRED選項之后,或者如果沒有指定REQUIRED選項但是指定了COMPONENTS選項,在它們的后面可以列出一些與包相關的部件清單(components list)。
  • 每一個模塊都會產生如下變量,_FOUND, _INCLUDE_DIR _LIBRARY和_LILBRARIES,如果_FOUND為真,_INCLUDE_DIR加入到INCLUDE_DIRECTORIES中,_LIBRARY加入到TARGET_LINK_LIBRARIES中就會有相應的變量OpenCV_FOUND,OpenCV_INCLUDE_DIRS等相應的變量生效。
    例如
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})

PKG_CHECK_MODULES

檢測所有給出的modules

PKG_CHECK_MODULES(<PREFIX> [REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] <MODULE> [<MODULE>]*)

例如

PKG_CHECK_MODULES(PC_OPENNI2 libopenni2)
if (NOT PC_OPENNI2_FOUND)
PKG_CHECK_MODULES(PC_OPENNI2 REQUIRED openni2)
endif()

如果找到,PC_OPENNI2_INCLUDE_DIRSPC_OPENNI2_LIBRARY_DIRS 等被設置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM