CMake教程---添加庫(第二課)

CMake教程版本號:3.16.3

英文原文鏈接: https://cmake.org/cmake/help/latest/guide/tutorial/index.html#id2

github示例代碼 https://github.com/sxpsxp12/cmake-learning-exampes

自定義庫

第二課內容是講解爲我們的項目添加庫。首先需要創建我們自己的庫。

cmake_minimum_required(VERSION 3.0.0)
project(sayhello VERSION 0.1.0)

add_library(sayhello helloworld.cpp)

庫目錄樹爲:

.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── CPackConfig.cmake
│   ├── CPackSourceConfig.cmake
│   ├── CTestTestfile.cmake
│   ├── DartConfiguration.tcl
│   ├── libhelloworld.a
│   ├── Makefile
│   └── Testing
├── CMakeLists.txt
└── helloworld.cpp

3 directories, 11 files
  • 構建項目,即可看到build目錄下生成的庫
cd build
cmake ..
make

使用自定義庫

示例項目目錄樹爲:

.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── config.h
│   ├── helloworld
│   └── Makefile
├── CMakeLists.txt
├── config.h.in
├── main.cpp
└── sayhellolibrary
    ├── CMakeLists.txt
    ├── helloworld.cpp
    └── helloworld.h

3 directories, 12 files
  • 首先創建項目目錄,然後將自定義庫目錄放置到根目錄下
  • 在根目錄創建CMakefile.txt文件,添加命令,以便庫能夠得到編譯
add_subdirectory(sayhellolibrary)
  • 在根目錄的CMakefile.txt文件中,添加指令,以搜索找到自定義庫的頭文件
target_include_directories(helloworld PUBLIC 
                            "${PROJECT_BINARY_DIR}"
                            "${PROJECT_SOURCE_DIR}/sayhellolibrary"
                          )
  • 爲可執行程序鏈接庫
target_link_libraries(helloworld PUBLIC sayhello)

最終我們看到的根目錄的CMakefile.txt內容爲:

cmake_minimum_required(VERSION 3.0.0)
project(helloworld VERSION 0.1.0)

add_executable(helloworld main.cpp)

add_subdirectory(sayhellolibrary)
target_include_directories(helloworld PUBLIC 
                            "${PROJECT_BINARY_DIR}"
                            "${PROJECT_SOURCE_DIR}/sayhellolibrary"
                          )

target_link_libraries(helloworld PUBLIC sayhello)

最後構建並運行可執行程序

cd build
cmake ..
make

構建可選項

可以通過開關項,來決定庫是否啓用,在大型項目中,該功能非常有用。

  • 首先在根目錄的CMakefile.txt文件中添加可選項
option(USE_SAYHELLO "use say hello to provide info" OFF)
#配置一個頭文件,以便將CMake的配置傳遞到源代碼中
configure_file(config.h.in config.h)
  • 在根目錄創建config.h.in文件,並將配置傳遞到源代碼中
#cmakedefine USE_MYMATH
  • USE_SAYHELLO這個可選項可以控制是否啓用該庫,這個配置項會存儲到Cache中,因此不需要每次構建的時候都設置該值。
  • 接下來在根目錄的CMakefile.txt文件中添加條件邏輯
if(USE_SAYHELLO)
#添加子CMakefile.txt目錄,以便能夠build
add_subdirectory(sayhellolibrary)
#將庫添加到變量EXTRA_LIBS
list(APPEND EXTRA_LIBS sayhello)
#將頭文件路徑添加到變量EXTRA_INCLUDES中
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/sayhellolibrary")
endif(USE_SAYHELLO)

target_include_directories(helloworld PUBLIC 
                            "${PROJECT_BINARY_DIR}"
                            ${EXTRA_INCLUDES}
                          )

target_link_libraries(helloworld PUBLIC ${EXTRA_LIBS})
  • 修改源代碼,以使用可選項
#ifdef USE_SAYHELLO
#include "helloworld.h"
#endif

...

完整的CMakefile.txt爲:

cmake_minimum_required(VERSION 3.0.0)
project(helloworld VERSION 0.1.0)

add_executable(helloworld main.cpp)

option(USE_SAYHELLO "use say hello to provide info" OFF)
#配置一個頭文件,以便將CMake的配置傳遞到源代碼中
configure_file(config.h.in config.h)

if(USE_SAYHELLO)
#添加子CMakefile.txt目錄,以便能夠build
add_subdirectory(sayhellolibrary)
#將庫添加到變量EXTRA_LIBS
list(APPEND EXTRA_LIBS sayhello)
#將頭文件路徑添加到變量EXTRA_INCLUDES中
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/sayhellolibrary")
endif(USE_SAYHELLO)

target_include_directories(helloworld PUBLIC 
                            "${PROJECT_BINARY_DIR}"
                            ${EXTRA_INCLUDES}
                          )

target_link_libraries(helloworld PUBLIC ${EXTRA_LIBS})

最終構建並運行

cd build
cmake ..
make

可自行修改可選項USE_SAYHELLO的值,可刪除構建緩衝,重新構建運行看看效果

總結

這一節,我們新學習的cmake指令如下

add_library

所屬:項目命令,只能用於CMake項目

使用指定的源文件將庫添加到項目中。

普通的庫

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [source1] [source2 ...])

根據命令中的源文件構建一個名爲的庫(如果源文件在之後使用target_sources()添加,那麼此處可以忽略),必須是一個合規的名字,並且必須在項目中是唯一的。

STATIC, SHARED, or MODULE這三個關鍵字可以指定生成庫的類型。靜態庫是目標文件的歸檔,以便其他目標鏈接使用。共享庫動態鏈接,並在運行時加載。MODULE庫是一個插件,不會鏈接到其他目標,但是可以動態加載。

如果關鍵字沒有設置,取決於當前變量BUILD_SHARED_LIBS是否是ON, 關鍵字SHARED和MODULE的配置,會自動將可執行程序的屬性POSITION_INDEPENDENT_CODE(是否創建一個路徑無關的可執行程序或者庫)設置爲ON。

導入的庫

add_library(<name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED
            [GLOBAL])

一個IMPORTED庫表示一個位於項目以外的庫文件。沒有規則構建它,且IMPORTED屬性是True。

對象庫

add_library(<name> OBJECT <src>...)

創建一個對象庫,它會編譯源文件,但是不會是源文件的歸檔或者鏈接這些文件到庫中。

別名庫

add_library(<name> ALIAS <target>)

創建一個別名目標,以便可用於在後續命令中引用。 不會作爲生成目標出現在生成的構建系統中。

接口庫

add_library(<name> INTERFACE [IMPORTED [GLOBAL]])

創建一個接口庫。 INTERFACE庫目標雖然可以設置屬性,並且可以安裝,導出和導入,但它不會直接創建構建輸出

更多信息請查看: https://cmake.org/cmake/help/latest/command/add_library.html

add_subdirectory

所屬:項目命令,只能用於CMake項目

添加要構建的子目錄

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

source_dir表示CMakefile.txt和代碼文件所在的目錄。相對路徑是基於當前路徑,也可以是絕對路徑。binary_dir表示輸出文件的路徑。如果是相對路徑,是基於當前輸出路徑的相對路徑,也可以是絕對路徑。

target_link_libraries

所屬:項目命令,只能用於CMake項目

指定給定可執行程序的鏈接庫或者標誌。

target_link_libraries(<target> ... <item>... ...)

有多種形式,具體信息可查看: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

option

所屬:腳本指令,總是可用的

提供可選項,供用戶選擇

option(<variable> "<help_text>" [value])

提供一個可選項,供用戶選擇ON或者OFF.[value]默認是OFF。


歡迎各位大佬右側關注、點贊、打賞,我們再會。。。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章