CMake簡介


一、CMake簡介

  • CMake是一個跨平台的編譯工具,能夠輸出各種各樣的makefile或者project文件。
  • CMake並不直接構建出最終的軟件,而是生成標准的Makefile文件或者VisualStudio項目文件,然后再使用Make或者VisualStudio進行編譯。
  • CMake在Windows平台上生成VisualStudio項目文件,在Linux和Unix平台上生成Makefile文件。

二、CMake典型示例

源代碼 demo.cpp

int main()
{
    return 0;
}

cmake腳本 CMakeLists.txt

# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
# 項目信息
project (demo)
# 指定生成目標
add_executable(demo demo.cpp)

編譯流程

  • Windows

    1. 創建build文件夾
    2. 在build文件夾中執行 cmake .. 命令
    3. 用Visual Studio打開生成的demo.sln,然后編譯
  • Linux

mkdir build
cd build
cmake ..
make

三、CMake常用命令

CMake中常用的語法包含三類:

  • 命令
  • 變量
  • 屬性

常用命令介紹

設置編譯目標類型

  • add_executable 生成可執行文件
  • add_library 生成庫文件

比如:

add_executable(demo demo.cpp)
add_library(common util.cpp)

add_library默認生成靜態庫,可以顯式的控制生成的庫的類型

add_library(common STATIC util.cpp) #生成靜態庫
add_library(common SHARED util.cpp) #生成動態庫或共享庫

通過以上命令生成文件名字,在Windows下是:

demo.exe
common.lib
common.dll

在Linux下是:

demo
libcommon.a
libcommon.so

指定編譯包含的源文件

  1. 明確指定包含的源文件
add_executable(demo demo.cpp test.cpp util.cpp)
  1. 搜索所有的cpp文件
aux_source_directory(. SRC_LIST) #搜索當前目錄下的所有.cpp文件
add_executable(demo ${SRC_LIST})
  1. 自定義搜索規則
file(GLOB SRC_LIST "*.cpp" "*.cc")
add_executable(demo ${SRC_LIST})
  1. 包含多個文件夾的文件
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_executable(demo ${SRC_LIST})
# 或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_executable(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
# 或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_executable(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
  1. 通過模糊搜索的方式包含源文件,當添加新的源文件后,需要通過cmake命令重新生成Makefile或者VS項目文件

設置包含目錄

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

Linux下還可以通過如下方式設置包含目錄

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")

設置鏈接庫搜索目錄

link_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs64
)

Linux下還可以通過如下方式設置包含目錄

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs64")

設置需要鏈接的庫

根據鏈接庫目錄搜索

target_link_libraries(demo Math)
  • 在Windows下,會根據鏈接庫目錄,搜索Math.lib文件
  • 在Linux下,會根據鏈接庫目錄搜索如下文件:
libMath.so
libMath.a

默認優先鏈接動態庫,可以在鏈接時指定動態庫或者靜態庫如:

target_link_libraries(demo Math.a)  # 鏈接libMath.a
target_link_libraries(demo Math.so) # 鏈接libMath.so

指定全路徑

target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.so)

指定多個鏈接庫

target_link_libraries(demo 
    ${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.a 
    boost_system.a 
    boost_thread 
    pthread)

設置變量

  1. set 直接設置變量的值
set(SRC_LIST main.cpp test.cpp)
add_executable(demo ${SRC_LIST})
  1. set 追加變量的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${SRC_LIST} test.cpp)
add_executable(demo ${SRC_LIST})
  1. list 追加或者刪除變量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})

條件控制

  • if else elseif endif
if(MSVC)
    set(LINK_LIBS common)
else()
    set(boost_thread boost_log.a boost_system.a)
endif()

target_link_libraries(demo ${LINK_LIBS})

# 或者
if(UNIX)
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -g")
else()
    add_definitions(-D_SCL_SECURE_NO_WARNINGS 
    -D_CRT_SECURE_NO_WARNINGS 
    -D_WIN32_WINNT=0x601 
    -D_WINSOCK_DEPRECATED_NO_WARNINGS)
endif()

if(${CMAKE_BUILD_TYPE} MATCHES "debug")
    ...
else()
    ...
endif()
  • while break continue foreach end_while end_foreach

其他常用命令

  • message 顯示一些消息
message(${MY_VAR})
message("build with debug mode")
message(WARNING "this is warnning message")
message(FATAL_ERROR "this build has many error") # 會導致生成失敗
  • source_group 在Windows下起作用,設置源文件在項目中的目錄結構
file(GLOB PROTOCOL_FILES "protocol/*.cpp")
source_group("協議" FILES ${PROTOCOL_FILES})
  • set_target_properties 設置項目屬性
  • set_property 設置全局屬性、項目屬性等
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#設置項目在解決方案中的目錄結構,只在Windows下生效
set_target_properties(ServerManager PROPERTIES FOLDER "manager")
  • include 包含其他cmake文件
include(./common.cmake) #指定包含文件的全路徑
include(def) #在搜索路徑中搜索def.cmake文件
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) #設置include的搜索路徑

四、復雜項目示例

多個目錄,多個源文件,多個項目

項目目錄結構如下:

./demo
    |
    +--- main.cc
    |
    +--- math/
          |
          +--- MathFunctions.cc
          |
          +--- MathFunctions.h

這種情況還可以通過add_subdirectory的方式添加子目錄

添加cmake腳本后的目錄結構如下:

./demo
    |
    +--- CMakeLists.txt
    |
    +--- main.cc
    |
    +--- math/
          |
          +--- CMakeLists.txt
          |
          +--- MathFunctions.cc
          |
          +--- MathFunctions.h

demo下的CMakeLists.txt文件如下:

cmake_minimum_required (VERSION 2.8)
project(demo)
aux_source_directory(. DIR_SRCS)

# 添加math子目錄
add_subdirectory(math)

# 指定生成目標
add_executable(demo ${DIR_SRCS})

# 添加鏈接庫
target_link_libraries(demo MathFunctions)

math目錄中的CMakeLists.txt:

aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫
add_library(MathFunctions ${DIR_LIB_SRCS})

五、常用變量

構建類型

cmake默認支持多種構建類型(build type),每種構建類型都有專門的編譯參數變量,詳情見下表

CMAKE_BUILD_TYPE 對應的c編譯選項變量 對應的c++編譯選項變量
None CMAKE_C_FLAGS CMAKE_CXX_FLAGS
Debug CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
Release CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
RelWithDebInfo CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO
MinSizeRel CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL

指定構建類型

  1. Windows的VS項目屬於多配置型,可以在VS中選擇生成的配置
  2. 生成后的項目默認包含四種配置
  3. 改變默認的配置
set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo")
  1. 默認生成的平台類型為Win32,如果需要x64類型,則需要按如下命令執行
cmake -G "Visual Studio 14 2015 Win64" ..
  1. Linux下的Makefile屬於單配置型,需要指定生成配置
  2. 默認執行 cmake ..,會生成None配置
  3. 可以通過命令行指定配置
cmake -DCMAKE_BUILD_TYPE=Debug ..
  1. 可以在CMake文件中指定配置
set(CMAKE_BUILD_TYPE DEBUG)

變量

  • 變量的引用方式是使用“${}”,在if命令中,不需要使用這種方式,直接使用變量名即可
  • 自定義變量使用SET(OBJ_NAME xxxx),使用時${OBJ_NAME}

常用變量

  • CMAKE_BINARY_DIR,PROJECT_BINARY_DIR,_BINARY_DIR:
    這三個變量內容一致,如果是內部編譯,就指的是工程的頂級目錄,如果是外部編譯,指的就是工程編譯發生的目錄。

  • CMAKE_SOURCE_DIR,PROJECT_SOURCE_DIR,_SOURCE_DIR:
    這三個變量內容一致,都指的是工程的頂級目錄。

  • CMAKE_CURRENT_BINARY_DIR:外部編譯時,指的是target目錄,內部編譯時,指的是頂級目錄

  • CMAKE_CURRENT_SOURCE_DIR:CMakeList.txt所在的目錄

  • CMAKE_CURRENT_LIST_DIR:CMakeList.txt的完整路徑

  • CMAKE_CURRENT_LIST_LINE:當前所在的行

  • CMAKE_MODULE_PATH:如果工程復雜,可能需要編寫一些cmake模塊-,這里通過SET指定這個變量

  • LIBRARY_OUTPUT_DIR,BINARY_OUTPUT_DIR:庫和可執行的最終存放目錄

環境變量

  • 使用環境變量:$ENV{Name}
  • 寫入環境變量:set(ENV{Name} value) #這里沒有“$”符號

系統信息

  • CMAKE_MAJOR_VERSION,CMAKE 主版本號,比如2.4.6 中的2
  • CMAKE_MINOR_VERSION,CMAKE 次版本號,比如2.4.6 中的4
  • CMAKE_PATCH_VERSION,CMAKE 補丁等級,比如2.4.6 中的6
  • CMAKE_SYSTEM ,系統名稱,比如Linux-2.6.22
  • CMAKE_SYSTEM_NAME ,不包含版本的系統名,比如Linux
  • CMAKE_SYSTEM_VERSION ,系統版本,比如2.6.22
  • CMAKE_SYSTEM_PROCESSOR,處理器名稱,比如i686
  • UNIX ,在所有的類UNIX平台為TRUE,包括OS X 和cygwin
  • WIN32 ,在所有的win32 平台為TRUE,包括cygwin

主要開關選項

  • BUILD_SHARED_LIBS, 這個開關用來控制默認的庫編譯方式,如果不進行設置,使用add_library 並沒有指定庫類型的情況下,默認編譯生成的庫都是靜態庫。如果set(BUILD_SHARED_LIBS ON) 后,默認生成的為動態庫
  • CMAKE_C_FLAGS 設置C編譯選項,也可以通過指令add_definitions() 添加
  • CMAKE_CXX_FLAGS 設置C++ 編譯選項,也可以通過指令add_definitions() 添加

六、參考資料


免責聲明!

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



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