1. 程式人生 > >CMake語法學習筆記

CMake語法學習筆記

最近一直在忙新需求,本來想記錄一下自己學CMake的一些筆記,拖到了現在……

一、CMakeLists.txt檔案

  • 如果工程存在多個目錄,需要確保每個要管理的目錄都存在一個CMakeLists.txt檔案,這是CMake的構建定義檔案。

二、CMake的基本語法規則

  • CMake的基本語法規則:指令(引數1 引數2 …),其中引數使用括號括起,引數之間使用空格或分號隔開。
  • 指令與大小寫無關的,引數和變數是大小寫相關的。

三、CMake常用指令

  • project(projectname [CXX][C][Java])
    用來定義工程名稱,並指定工程支援的語言,支援的語言列表可忽略不寫,預設支援所有語言。
    例如:

    //定義bzip2工程目錄
    project(bzip2)
  • set(var [value])
    用來顯示地定義變數,有多個變數用空格或分號隔開。
    例如:

    //定義變數FILE_PATH,用來儲存兩個檔案路徑
    set(FILE_PATH C:\\cpp\\\main.c C:\\cpp\\bspatch.c)

    注:
    1.當我們需要用到這個變數FILE_PATH時,可以採用var{FILE_PATH}
    2.在IF控制語句中是直接使用變數名的,無需${}

  • cmake_minimun_required(VERSION 3.4.1)
    用來指定CMake的最低版本為3.4.1

  • aux_source_directory(dir variable)


    將dir目錄下的所有原始碼檔案的名字儲存在變數variable中。
    例如:

    //將當前目錄下的原始碼名字儲存在DIR_SRCS變數中
    aux_source_directory(. DIR_SRCS)
  • target_link_libraries(target library1 library2 …)
    指定target需要連結的library,這裡的target必須已經被建立。
    例如:

    //指定main工程需要連結hello共享庫或so檔案
    target_link_libraries(main hello)
    //或者:
    target_link_libraries(main libhello.so)
  • add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    用於向當前工程新增一個需要進行構建的子目錄,並且可以指定中間二進位制檔案和目標二進位制檔案存放的位置。
    例如:

    //當執行到該指令時,會進入到bzip2目錄執行此目錄的CMakeLists.txt檔案
    add_subdirectory(bzip2)
  • add_library(name [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
    將一組原始檔source1 source2 … sourceN編譯出一個庫檔案,並且儲存為libname.so檔案(在此不需寫全libname,只需填寫name即可,CMake會自動為你生成libname.so)。
    其中SHARED表示動態庫,在程式碼中使用loadLibrary動態呼叫;STATIC表示靜態庫,整合到程式碼中會在編譯時呼叫;MODULE只有在使用dyld的系統有效,如果不支援dyld,則被當作SHARED對待。
    EXCLUDE_FROM_ALL表示這個庫不被預設構建,除非有其他元件依賴或手工構建。
    例如:

    //將bspatch.c編譯為一個名為libbspatch.so的共享庫
    add_library(bspatch SHARED bspatch.c)

    add_library命令也可以用來建立匯入的庫目標。

    add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED)

    匯入的庫目標是引用了在工程外的一個庫檔案的目標。沒有生成構建這個庫的規則。這個目標名字的作用域在它被建立的路徑及以下有效。它可以向任何在該工程內構建的目標一樣被引用。匯入庫為類似於target_link_libraries命令中引用它提供了便利。關於匯入庫細節可以通過指定那些以IMPORTED_的屬性設定來指定。其中最重要的屬性是IMPORTED_LOCATION(以及它的具體配置版本,**IMPORTED_LOCATION**_),它指定了主庫檔案在磁碟上的位置。

  • find_library(variable name1 path1 path2 …)
    查詢庫檔案name1的全路徑(包含庫檔名),如果找到將路徑儲存在變數variable中,如果沒有找到則結果為variable_NOT_FOUND。
    例如:

    //將log庫檔案路徑儲存在變數log_lib中,並將bspatch工程連結引入log庫
    find_library(log_lib log)
    target_link_libraries(bspatch ${log_lib})
  • set_target_properties(target1 target2 … PRORERTIES prop1 value1 prop2 value2 …)
    用來設定輸出的名稱。
    例如:

    //匯入libavutil-55.so庫檔案
    add_library(avutil-55 SHARED IMPORTED)
    //設定需要引用的libavutil-55.so庫檔案路徑,其中IMPORTED_LOCATION庫檔案在磁碟上的位置
    set_target_properties(avutil-55 PROPERTIES IMPORTED_LOCATION ../libs/armeabi-v7a/libavutil-55.so)

四、CMake常用變數

一般來說,我們可以用set指令顯示定義一個變數,但CMake系統已經幫我們隱式預定義了一些變數,可以採用${VAR}方式來呼叫這些變數,以下記錄一些Android CMakeLists.txt檔案中常用的變數。

  • PROJECT_SOURCE_DIR
    當前工程的原始碼路徑。

  • PROJECT_BINARY_DIR
    指向工程構建目錄的全路徑。

  • CMAKE_VERSION
    CMake的完整版本號;格式為major.minor.patch[.tweak[-id]]

  • CMAKE_CURRENT_SOURCE_DIR
    呼叫這個變數的CMakeLists.txt所在路徑

  • CMAKE_CURRENT_LIST_FILE
    呼叫這個變數的CMakeLists.txt的完整路徑

  • CMAKE_CURRENT_LIST_LINE
    這個變數所在的行數

  • PROJECT_NAME
    返回通過project指令定義的專案名稱

  • 以上只是最近學NDK總結出的小部分CMake知識點,對於真正使用CMake的人來說,猶如大海里的一根針般渺小,勿噴

真正想了解CMake構建工具的朋友,可以參看以下連結: