什么是CMake
你或許聽過好幾種 Make 工具,例如 GNU Make ,QT 的 qmake ,微軟的 MS nmake,BSD Make(pmake),Makepp,等等。這些 Make 工具遵循着不同的規范和標准,所執行的 Makefile 格式也千差萬別。這樣就帶來了一個嚴峻的問題:如果軟件想跨平台,必須要保證能夠在不同平台編譯。而如果使用上面的 Make 工具,就得為每一種標准寫一次 Makefile ,這將是一件讓人抓狂的工作。
CMake就是針對上面問題所設計的工具:它首先允許開發者編寫一種平台無關的CMakeLists.txt文件來定制整個編譯流程,然后再根據目標用戶的平台進一步生成所需的本地化Makefile和工程文件,如Unix的Makefile或Windows的Visual Studio工程。從而做到"Write once, run everywhere"。顯然,CMake是一個比上述幾種make更高級的編譯配置工具。
在linux平台下使用CMake生成Makefile並編譯的流程如下:
1、編寫CMake配置文件CMakeLists.txt。
2、執行命令cmake PATH,其中PATH是CMakeLists.txt所在的目錄。
3、使用make命令進行編譯。
一個通用的模板如下。
源碼目錄結構
├── CMakeLists.txt 根目錄cmakelists.t
├── math
│ ├── inc
│ │ ├── MathFunctions.h
│ ├── src
│ │ ├── MathFunctions.cc
│ └── CMakeLists.txt 子目錄cmakelists.txt
├── main.c main函數
└── README.md
源碼
根目錄CMakeLists.txt
#------------------------------------------------------------------------------- # File: CMakeLists.txt # Description: CMake Configuration File #------------------------------------------------------------------------------- # CMake最低版本要求 cmake_minimum_required(VERSION 2.8) # 項目名稱 project(Template) #------------------------------------------------------------------------------- # project setting #------------------------------------------------------------------------------- # setting for compiling in debug or release mode if(${CMAKE_BUILD_TYPE} MATCHES "Release") message(STATUS "Release版本") set(BuildType "Release") else() message(STATUS "Debug版本") set(BuildType "Debug") endif() # 設置bin和lib庫目錄 # PROJECT_SOURCE_DIR為cmake內置變量,表示工程的根目錄 set(RELEASE_DIR ${PROJECT_SOURCE_DIR}/release) # debug和release版本目錄不一樣 # LIBRARY_OUTPUT_PATH為cmake內置變量,表示目標鏈接庫文件的存放位置 set(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/linux/${BuildType}) set(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/linux/${BuildType}) #----------------------------------------------------------------------------- # compile setting #----------------------------------------------------------------------------- # 設置編譯選項 # -fPIC:標識編譯為位置獨立的代碼,不用此選項的話編譯后的代碼是位置相關的 # add_compile_options是針對所有類型編譯器的 add_compile_options(-fPIC) # 設置c++編譯器編譯選項 set(CXX_FLAGS -std=c++11 -Wno-overflow -Wno-conversion-null -Wno-maybe-uninitialized -Wno-uninitialized -Wno-sequence-point -Wno-write-strings -Wno-unused-label -Wno-unused-variable -Wno-unused-variable -Wno-cpp -Wno-deprecated -Wno-unused-but-set-variable -pthread) # string(REPLACE <match-string> <replace-string> <out-var> <input>...) # 替換CXX_FLAGS變量中的;字符為空格,然后寫入CMAKE_CXX_FLAGS,CMAKE_CXX_FLAGS為cmake內置變量,用於設置C++編譯選項 string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") # CMAKE_CXX_COMPILER為cmake內置變量,用於指定gcc,g++版本編譯 set(CMAKE_CXX_COMPILER "g++") # 指定Debug模式下編譯選項,CMAKE_CXX_FLAGS_DEBUG為cmake內置變量 set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") # 指定Release模式下編譯選項,CMAKE_CXX_FLAGS_RELEASE為cmake內置變量 # -g表示添加gdb調試選項 set(CMAKE_CXX_FLAGS_RELEASE "-g -O2 -finline-limit=1000") MESSAGE(STATUS "CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}") IF( "${CMAKE_BUILD_TYPE}" STREQUAL "Release") MESSAGE(STATUS "CMAKE_CXX_FLAGS : ${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS}") ELSE() MESSAGE(STATUS "CMAKE_CXX_FLAGS : ${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS}") ENDIF() #------------------------------------------------------------------------------- # thirdparty dependencies #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # project generation #------------------------------------------------------------------------------- # 查找當前目錄下的所有源文件 # 並將名稱保存到DIR_SRCS 變量中 aux_source_directory(. DIR_SRCS) # 向當前工程添加存放源文件的子目錄 # 注意,該子目錄中須包含CMakeList.txt文件 add_subdirectory(math) # 添加當前編譯目標使用到的頭文件搜索路徑,多個路徑之間用空格分隔 # 如果路徑包含空格,可以使用雙引號將它括起來 include_directories("${PROJECT_SOURCE_DIR}/math/inc") # 指定生成目標 add_executable(dynamic main.cc) # 添加鏈接庫 target_link_libraries(dynamic mathLib)
子目錄CMakeLists.txt
# 設置release版本還是debug版本 if(${CMAKE_BUILD_TYPE} MATCHES "Release") message(STATUS "Release版本") set(BuildType "Release") else() set(BuildType "Debug") message(STATUS "Debug版本") endif() #設置lib庫目錄 set(RELEASE_DIR ${PROJECT_SOURCE_DIR}/release) # debug和release版本目錄不一樣 #設置生成的so動態庫最后輸出的路徑 set(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/linux/${BuildType}) add_compile_options(-fPIC) # 查找src目錄下的所有源文件 # 並將名稱保存到 DIR_LIB_SRCS 變量 aux_source_directory(src DIR_LIB_SRCS) # 添加當前編譯目標使用到的頭文件搜索路徑,多個路徑之間用空格分隔 # 如果路徑包含空格,可以使用雙引號將它括起來 include_directories("${PROJECT_SOURCE_DIR}/math/inc") # 生成動態庫 add_library (mathLib SHARED ${DIR_LIB_SRCS})