CMakeLists.txt編寫和使用方法
一、使用方法
一般把CMakeLists.txt檔案放在工程目錄下,使用時,先建立一個叫build的資料夾(這個並非必須,只是生成的Makefile等檔案放在build裡比較整齊),然後執行下列操作:
cd build
cmake ..
make
其中cmake .. 在build裡生成Makefile,make應當在有Makefile的目錄下,根據Makefile生成可執行檔案。
二、編寫方法
# 宣告要求的cmake最低版本 cmake_minimum_required( VERSION 2.8 ) # 新增c++11標準支援 set( CMAKE_CXX_FLAGS "-std=c++11" ) # 宣告一個cmake工程 project( 工程名 ) MESSAGE(STATUS "Project: SERVER") #列印相關訊息訊息 # 找到後面需要庫和標頭檔案的包 find_package(包的名稱及最低版本) # 例如find_package(OpenCV 2.4.3 REQUIRED) # 標頭檔案 include_directories("路徑") # 例如 #include_directories( # ${PROJECT_SOURCE_DIR} # ${PROJECT_SOURCE_DIR}/include # ${EIGEN3_INCLUDE_DIR} ) # 設定路徑(下面生成共享庫的路徑) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 即生成的共享庫在工程資料夾下的lib資料夾中 # 建立共享庫(把工程內的cpp檔案都建立成共享庫檔案,方便通過標頭檔案來呼叫) add_library(${PROJECT_NAME} SHARED src/cpp檔名 …… ) # 這時候只需要cpp,不需要有主函式 # ${PROJECT_NAME}是生成的庫名 表示生成的共享庫檔案就叫做 lib工程名.so # 也可以專門寫cmakelists來編譯一個沒有主函式的程式來生成共享庫,供其它程式使用 # 連結庫 # 把剛剛生成的${PROJECT_NAME}庫和所需的其它庫連結起來 target_link_libraries(${PROJECT_NAME} /usr/lib/i386-linux-gnu/libboost_system.so ) # 編譯主函式,生成可執行檔案 # 先設定路徑 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) # 可執行檔案生成 add_executable(要生成的可執行檔名 從工程目錄下寫起的主函式檔名) # 這個可執行檔案所需的庫(一般就是剛剛生成的工程的庫咯) target_link_libraries(可執行檔名 ${PROJECT_NAME})
cmake中一些預定義變數
- PROJECT_SOURCE_DIR 工程的根目錄
- PROJECT_BINARY_DIR 執行cmake命令的目錄,通常是${PROJECT_SOURCE_DIR}/build
- CMAKE_INCLUDE_PATH 環境變數,非cmake變數
- CMAKE_LIBRARY_PATH 環境變數
- CMAKE_CURRENT_SOURCE_DIR 當前處理的CMakeLists.txt所在的路徑
- CMAKE_CURRENT_BINARY_DIR target編譯目錄
使用ADD_SURDIRECTORY(src bin)可以更改此變數的值
SET(EXECUTABLE_OUTPUT_PATH <新路徑>)並不會對此變數有影響,只是改變了最終目標檔案的儲存路徑 - CMAKE_CURRENT_LIST_FILE 輸出呼叫這個變數的CMakeLists.txt的完整路徑
- CMAKE_CURRENT_LIST_LINE 輸出這個變數所在的行
- CMAKE_MODULE_PATH 定義自己的cmake模組所在的路徑
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然後可以用INCLUDE命令來呼叫自己的模組 - EXECUTABLE_OUTPUT_PATH 重新定義目標二進位制可執行檔案的存放位置
- LIBRARY_OUTPUT_PATH 重新定義目標連結庫檔案的存放位置
- PROJECT_NAME 返回通過PROJECT指令定義的專案名稱
- CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用來控制IF ELSE語句的書寫方式
假設當前的專案程式碼在src 目錄。 src 下有子目錄:server, utility, lib, bin, build
server ----- 存放專案的主功能類檔案
utility ----- 存放專案要用到相關庫檔案,便已成為庫檔案存放到子目錄lib 中
lib ----- 存放utility 生成的庫
bin ----- 存放association 生成的二進位制檔案
build ----- 編譯目錄,存放編譯生成的中間檔案
cmake 要求工程主目錄和所有存放原始碼子目錄下都要編寫CMakeLists.txt 檔案,注意大小寫(cm 大寫,list中l 大寫且落下s).
src/CMakeLists.txt 檔案如下:
#cmake file for project association #表示註釋
#author:>---double__song
#created:>--2011/03/01
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) #cmake 最低版本要求,低於2.6 構建過程會被終止。
PROJECT(server_project) #定義工程名稱
MESSAGE(STATUS "Project: SERVER") #列印相關訊息訊息
MESSAGE(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")
SET(CMAKE_BUILE_TYPE DEBUG) #指定編譯型別
SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") #指定編譯器
ADD_SUBDIRECTORY(utility) #新增子目錄
ADD_SUBDIRECTORY(server)
相關解釋:
1. CMakeLists.txt 檔案中不區分大小寫
2. PROJECT(project_name) 定義工程名稱
語法:project(projectname [cxx] [c] [java])
可以指定工程採用的語言,選項分別表示:C++, C, java, 如不指定預設支援所有語言
3. MESSAGE(STATUS, "Content") 列印相關訊息
輸出訊息,供除錯CMakeLists.txt 檔案使用。
4. SET(CMAKE_BUILE_TYPE DEBUG) 設定編譯型別debug 或者release。 debug 版會生成相關除錯資訊,可以使用GDB 進行
除錯;release不會生成除錯資訊。當無法進行除錯時檢視此處是否設定為debug.
5. SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") 設定編譯器的型別
CMAKE_C_FLAGS_DEBUG ---- C 編譯器
CMAKE_CXX_FLAGS_DEBUG ---- C++ 編譯器
6. ADD_SUBDIRECTORY(utility) 新增要編譯的子目錄
為工程主目錄下的存放原始碼的子目錄使用該命令,各子目錄出現的順序隨意。
如上便是工程server_project 主目錄src 下的CMakeLists.txt 檔案,下一篇我們解釋子目錄utiltiy中的CMakeLists.txt 檔案。
子目錄utility 下的CMakeLists.txt 檔案如下:
#Cmake file for library utility.a
#Author: double__song
#Created: 2011/3/3
SET(SOURCE_FILES #設定變數,表示所有的原始檔
ConfigParser.cpp
StrUtility.cpp
)
INCLUDE_DIRECTORIES( #相關標頭檔案的目錄
/usr/local/include
${PROJET_SOURCE_DIR}/utility
)
LINK_DIRECTORIES( #相關庫檔案的目錄
/usr/local/lib
)
ADD_LIBRARY(association ${SOURCE_FILES}) #生成靜態連結庫libassociation.a
TARGET_LINK_LIBRARY(association core) #依賴的庫檔案
SET_TARGET_PROPERTIES(utility PROPERTIES #表示生成的執行檔案所在路徑
RUNTIME_OUTPUT_DIRECTORY> "${PROJECT_SOURCE_DIR}/lib")
相關解釋:
1. SET(SOURCE_FILES .....)
表示要編譯的原始檔,所有的原始檔都要羅列到此處。set 設定變數,變數名SOURCE_FILES自定義。
2. INCLUDE_DIRECTORY(...)
include標頭檔案時搜尋的所有目錄
變數PROJECT_SOURCE_DIR 表示工程所在的路徑,系統預設的變數
3. LINK_DIRECTORIES(...)
庫檔案存放的目錄,在程式連線庫檔案的時候要再這些目錄下尋找對應的庫檔案
4. ADD_LIBRARY(...)
表示生成靜態連結庫libassociaiton.a,由${PROJECT_SOURCE_DIR}代表的檔案生成。
語法:ADD_LIBRARY(libname [SHARED|STATIC]
SHARED 表示生成動態庫, STATIC表示生成靜態庫。
5. TARGET_LINK_LIBRARY(association core)
表示庫association 依賴core庫檔案
6. SET_TARGET_PROPERTIES
設定編譯的庫檔案存放的目錄,還可用於其他屬性的設定。如不指定,
生成的執行檔案在當前編譯目錄下的各子目錄下的build目錄下,好拗口!簡單一點:
如指定在: ./src/lib 下
不指定在: ./src/build/utility/build 目錄下
生成的中間檔案在./src/build/utilty/build 目錄下,不受該命令額影響
子目錄server 下的CMakeLists.txt 檔案:
--------------------------------------------------------------------------------------------
SET(SOURCE_FILES
Gassociation.cpp
ConfigurationHandler.cpp
)
INCLUDE_DIRECTORIES(
/usr/local/include
${PROJECT_SOURCE_DIR}/utility
${PROJECT_SOURCE_DIR}/association
)
LINK_LIBRARIES(
/usr/local/lib
${PROJECT_SOURCE_DIR}/lib
)
ADD_EXECUTABLE(server ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(server
utility
)
SET_TARGET_PROPERTIES(server PROPERTIES #表示生成的執行檔案所在路徑
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
相關解釋:
1. ADD_EXECUTABLE() #指定要生成的執行檔案的名稱server
其他用法同utilty/CMakeLists.txt
2. SET_TARGET_PROPERTIES
設定生成的執行檔案存放的路徑,
注意:
執行檔案server 依賴的子目錄utility 子目錄生成的靜態庫libutility.a,在指定的時候要寫成:
TARGET_LINK_LIBRARIES(server utility)
而不能寫成:
TARGET_LINK_LIBRARIES(server libutility.a)
否則編譯總會提示找不到libutility庫檔案。
但使用第三方的庫卻要指定成具體的庫名,如:libACE-6.0.0.so
這一點很詭異,暫時還沒找到原因。
完成對應的CMakeLists.txt 檔案編寫後,便可以進行編譯了。
編譯:
進入 ./src/build
執行cmake ..
make
configure --prefix=/:作用:
指定安裝路徑
不指定prefix,則可執行檔案預設放在/usr /local/bin,庫檔案預設放在/usr/local/lib,配置檔案預設放在/usr/local/etc。其它的資原始檔放在/usr /local/share。你要解除安裝這個程式,要麼在原來的make目錄下用一次make uninstall(前提是make檔案指定過uninstall),要麼去上述目錄裡面把相關的檔案一個個手工刪掉。
指定prefix,直接刪掉一個資料夾就夠了。