實例-1
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( -DDDDDDDDD) #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(VERSION major[.minor[.patch[.tweak]]] [FATAL_ERROR])
聲明Cmake版本,如果低於指定版本則會停止處理工程文件,並報告錯誤
PROJECT(PROJECTNAME [CXX] [C])
[指定工程支持的語言,如果忽略,表示支持所有語言]
ADD_EXECUTABLE([WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 ...)
引入一個名為的可執行目標,該目標會由調用該命令時在源文件列表中指定的源文件來構建。對應於邏輯目標名字,並且在工程范圍內必須是全局唯一的,如果構成可執行文件的源文件很多,
AUX_SOURCE_DIRECTORY(. DIRSRCS)
則可以指定一個源文件列表或者添加文件夾內所有文件
CMAKE_MINIMUM_REQUIRED(VERSION 3.2) PROJECT(Hello) SET (SRC_LIST main.cpp v4l2_util.cpp tran_data.cpp) MESSAGE(${SRC_LIST}) ADD_EXECUTABLE(Hello ${SRC_LIST})
ADD_EXECUTABLE:可執行程序由哪些.o文件生成
實例-2 編譯靜態庫,並讓主程序調用靜態庫最終生成一個可執行程序
即先生成一個hello.a,再讓主程序main.cpp使用libhello.a,最終生成Hello
CMAKE_MINIMUM_REQUIRED(VERSION 3.2) PROJECT(Hello) SET(LIB_SRC_LIST source1.cpp source2.cpp) SET(EXEC_SRC_LIST main.cpp) ADD_LIBRARY(LIB STATIC ${LIB_SRC_LIST}) ADD_EXECUTABLE(Test_Hello ${EXEC_SRC_LIST}) TARGET_LINK_LIBRARIES(Test_Hello LIB)
創建一個名字name的庫文件,SHARED STATIC 制定生成庫的類型
ADD_LIBRARY(NAME [STATIC| SHARED|MODULE] [EXCLUDE_FROM_ALL] source1, source2,...)
將給定的庫鏈接到target上,默認優先鏈接動態庫,類似於靜態鏈接,必須放置在ADD_EXECUTABLE后面,否則都會出現undefied reference函數
TARGET_LINK_LIBRARIES(target [item1 [item2] [ ...] ]),LINK_DIRECTORIES
- 指定include路徑
一般情況下,src和include為同級目錄,需要指定include路徑src才可以正確定位頭文件
SET(INCLUDE_DIRECTORIES " ../include") INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})
它相當於g++選項中的-I參數的作用,也相當於環境變量中增加路徑到CPLUS_INCLUDE_PATH變量的作用。
- 添加第三方庫,不需要編譯,將他放在resource目錄下,需要指定搜索庫路徑
SET(LINK_DIR "../../resource") LINK_DIRECTORIES(${LINK_DIR })
相當於g++命令的-L選項的作用,也相當於環境變量中增加LD_LIBRARY_PATH的路徑的作用。
如果想設置更多的關於動態庫的參數例如: -Wl,-rpath=usr/local/lib
LINK_LIBRARY("/usr/local/lib") ADD_EXECUTABLE(main main.c)
- 創建Release和Debug版本
SET(CMAKE_BUILD_TYPE Release) SET(CMAKE_BUILD_TYPE Debug)
二者模式區別在於
Release: -O3 -DNDEBUG Debug: -g
也可不加在MakeFiles.txt里面,在產生Makefiles時候才加入
cmake -DCMAKE_BUILD_TYPE=Release
#增加編譯和鏈接選項
CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS
分別相當於:CFLAGS, CXXFLAGS, LDFLAGS。
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEMBED")
這種寫法的好處是,不會覆蓋CMAKE_CXX_FLAGS本來的信息。只是把需要添加的內容添加進去
Debug和Release版本:
關鍵在於三個CMake設置:
CMAKE_BUILD_TYPE
CMAKE_CXX_FLAGS_DEBUG, CMAKE_CXX_FLAGS_RELEASE
當CMAKE_BUILD_TYPE設置為Debug。 則編譯時采用CMAKE_CXX_FLAGS_DEBUG。
當CMAKE_BUILD_TYPE設置為Release。 則編譯時采用CMAKE_CXX_FLAGS_RELEASE
例如
cmake_minimum_required (VERSION 2.6) project (CMAKE_Test) add_executable(CMAKE_Test src/banchmark.cpp) #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.6) PROJECT(Hello) ADD_SUBDIRECTORIES(src lib) ADD_SUBDIRECTORIES(test bin)
構建添加一個子路徑
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 是個列表的話,此種方式仍然會引起警告。
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(Qt5Widgets)
FIND_PACKAGE( [version] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [components...]] [NO_POLICY_SCOPE])
查找並加載外來工程的設置。該命令會設置_FOUND變量,用來指示要找的包是否被找到了。如果這個包被找到了,與它相關的信息可以通過包自身記載的變量中得到。REQUIRED選項表示如果報沒有找到的話,cmake的過程會終止,並輸出警告信息。
- 在REQUIRED選項之后,或者如果沒有指定REQUIRED選項但是指定了COMPONENTS選項,在它們的后面可以列出一些與包相關的部件清單(components list)。
- 每一個模塊都會產生如下變量,_FOUND, _INCLUDE_DIR _LIBRARY和_LILBRARIES,如果_FOUND為真,_INCLUDE_DIR加入到INCLUDE_DIRECTORIES中,_LIBRARY加入到TARGET_LINK_LIBRARIES中就會有相應的變量Qt5Widgets_FOUND,Qt5Widgets_INCLUDE_DIRS等相應的變量生效。
PKG_CHECK_MODULES
PKG_CHECK_MODULES(<PREFIX> [REQUIRED] [QUIET] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] <MODULE> [<MODULE>]*)
檢測所有給出的modules
PKG_CHECK_MODULES(PC_OPENNI2 libopenni2) if (NOT PC_OPENNI2_FOUND) PKG_CHECK_MODULES(PC_OPENNI2 REQUIRED openni2) endif()
PC_OPENNI2_INCLUDE_DIRS, PC_OPENNI2_LIBRARY_DIRS 等被設置。