CMake 屬性之目錄屬性

梦起丶發表於2024-10-10

【寫在前面】

CMake 的目錄屬性是指在特定目錄(及其子目錄)範圍內有效的設定。

這些屬性不同於全域性變數或目標(Target)屬性,它們提供了一種機制,允許開發者為專案中的不同部分定義不同的構建行為。

透過目錄屬性,你可以指定編譯器選項、包含路徑、預處理定義等,而無需在每個目標或檔案中重複這些設定。


【正文開始】

CMake 目錄範圍的屬性有( CMake 3.30 ):

  • ADDITIONAL_CLEAN_FILES
  • BINARY_DIR
  • BUILDSYSTEM_TARGETS
  • CACHE_VARIABLES
  • CLEAN_NO_CUSTOM
  • CMAKE_CONFIGURE_DEPENDS
  • COMPILE_DEFINITIONS
  • COMPILE_OPTIONS
  • DEFINITIONS
  • EXCLUDE_FROM_ALL
  • IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
  • IMPORTED_TARGETS
  • INCLUDE_DIRECTORIES
  • INCLUDE_REGULAR_EXPRESSION
  • LABELS
  • LINK_DIRECTORIES
  • LINK_OPTIONS
  • LISTFILE_STACK
  • MACROS
  • PARENT_DIRECTORY
  • RULE_LAUNCH_COMPILE
  • RULE_LAUNCH_CUSTOM
  • RULE_LAUNCH_LINK
  • SOURCE_DIR
  • SUBDIRECTORIES
  • SYSTEM
  • TESTS
  • TEST_INCLUDE_FILES
  • VARIABLES
  • VS_GLOBAL_SECTION_POST_
  • VS_GLOBAL_SECTION_PRE_
  • VS_STARTUP_PROJECT

定義目錄屬性:

define_property( <DIRECTORY>
                 PROPERTY <name> [INHERITED]
                 [BRIEF_DOCS <brief-doc> [docs...]]
                 [FULL_DOCS <full-doc> [docs...]]
                 [INITIALIZE_FROM_VARIABLE <variable>])

在範圍內定義一個屬性,用於 set_property()get_property() 命令。它主要用於定義屬性的初始化或繼承方式。從歷史上看,該命令還將文件與屬性相關聯,但這不再被視為主要用例。

示例:

# 定義一個名為 CURRENT_DIRECTORY 的目錄屬性
define_property(DIRECTORY 
    # 目錄屬性的名稱
    PROPERTY CURRENT_DIRECTORY
    # 簡短的文件說明
    BRIEF_DOCS "The current directory"
    # 詳細的文件說明
    FULL_DOCS "The current directory"
)

設定目錄屬性:

set_property(<[DIRECTORY <dirs> ...] [TARGET_DIRECTORY <targets> ...]>
             [APPEND] [APPEND_STRING]
             PROPERTY <name> [<value1> ...])

在範圍的零個或多個物件上設定一個屬性。

DIRECTORY 範圍預設為當前目錄,但其他目錄(已由 CMake 處理)可以按完整路徑或相對路徑命名。相對路徑被視為相對於當前源目錄。另請參閱 set_directory_properties() 命令。

在 3.19 版本加入: <dir> 可以引用一個二進位制目錄。

如果給出 APPEND 選項,列表將附加到任何現有的屬性值(除了忽略和不附加空值)。如果給出 APPEND_STRING 選項,字串將作為字串附加到任何現有屬性值,即它會產生更長的字串而不是字串列表。當使用 APPENDAPPEND_STRING 以及定義為支援 INHERITED 行為的屬性時(請參閱 :command:define_property),在找到要附加到的初始值時不會發生繼承。如果該屬性尚未在指定範圍內直接設定,則該命令的行為就好像沒有給出 APPENDAPPEND_STRING 一樣。

示例:

# 設定當前目錄屬性為當前原始碼目錄
set_property(DIRECTORY PROPERTY CURRENT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

其中,有一個專用於設定目錄屬性的命令:

set_directory_properties(PROPERTIES prop1 value1 [prop2 value2] ...)

在鍵值對中設定當前目錄及其子目錄的屬性。

另請參閱 set_property(DIRECTORY) 命令。

獲取目錄屬性:

get_property(<[DIRECTORY <dir> | TARGET_DIRECTORY <target>]>
             PROPERTY <name>
             [SET | DEFINED | BRIEF_DOCS | FULL_DOCS])

從範圍內的一個物件獲取一個屬性。

DIRECTORY 作用域預設為當前目錄,但另一個目錄(已由 CMake 處理)可能由完整或相對路徑命名為“<dir>”。相對路徑被視為相對於當前源目錄。另請參閱 get_directory_property() 命令。

在 3.19 版本加入: <dir> 可以引用一個二進位制目錄。

如果給出了 SET 選項,變數將被設定為一個布林值,指示該屬性是否已被設定。如果給出了 DEFINED 選項,變數將被設定為一個布林值,指示該屬性是否已被定義,例如使用 define_property 命令。 如果給出了BRIEF_DOCSFULL_DOCS,那麼該變數將被設定為一個字串,其中包含所請求屬性的文件。如果為尚未定義的屬性請求文件,則返回“NOTFOUND”。

示例:

# 獲取當前目錄屬性
get_property(CURRENT_DIR DIRECTORY PROPERTY CURRENT_DIRECTORY)

其中,有一個專用於獲取目錄屬性的命令:

get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>)

將目錄範圍的屬性儲存在命名的<variable>中。

DIRECTORY 引數指定從中檢索屬性值的另一個目錄,而不是當前目錄。相對路徑被視為相對於當前源目錄。 CMake 必須已經知道該目錄,或者透過呼叫 add_subdirectory 新增它或者是頂級目錄。

在 3.19 版本加入: <dir> 可以引用一個二進位制目錄。

如果沒有為指定的目錄範圍定義該屬性,則返回一個空字串。對於 INHERITED 屬性,如果在指定的目錄範圍內找不到該屬性,則搜尋將連結到父範圍,如 define_property() 命令所述。

get_directory_property(<variable> [DIRECTORY <dir>]
                       DEFINITION <var-name>)

從目錄中獲取變數定義。這種形式對於從另一個目錄獲取變數定義很有用。

示例:

# 新增預處理定義,定義宏TEST_DEFINED的值為1
add_compile_definitions(TEST_DEFINED=1)

# 獲取當前目錄的屬性COMPILE_DEFINITIONS,即定義的宏
get_directory_property(DEFS COMPILE_DEFINITIONS) 

# 列印獲取到的定義資訊
message("DEFS: ${DEFS}")

最後完整測試一遍:

# 要求 CMake 最低版本為 3.16
cmake_minimum_required(VERSION 3.16)

# 定義一個名為 CURRENT_DIRECTORY 的目錄屬性
define_property(DIRECTORY 
    # 目錄屬性的名稱
    PROPERTY CURRENT_DIRECTORY
    # 簡短的文件說明
    BRIEF_DOCS "The current directory"
    # 詳細的文件說明
    FULL_DOCS "The current directory"
)

# 設定當前目錄屬性為當前原始碼目錄
set_property(DIRECTORY PROPERTY CURRENT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

# 獲取當前目錄屬性
get_property(CURRENT_DIR DIRECTORY PROPERTY CURRENT_DIRECTORY)

# 列印當前目錄資訊
message("CURRENT_DIR: ${CURRENT_DIR}")

# 新增預處理定義,定義宏TEST_DEFINED的值為1
add_compile_definitions(TEST_DEFINED=1)

# 獲取當前目錄的屬性COMPILE_DEFINITIONS,即定義的宏
get_directory_property(DEFS COMPILE_DEFINITIONS) 

# 列印獲取到的定義資訊
message("DEFS: ${DEFS}")

# 將庫目錄連結到當前目錄下的lib目錄
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)

# 獲取連結目錄屬性
get_property(LINK_DIR DIRECTORY PROPERTY LINK_DIRECTORIES)

# 獲取源目錄屬性
get_property(S_DIR DIRECTORY PROPERTY SOURCE_DIR)

# 列印連結目錄和源目錄資訊
message("LINK_DIR: ${LINK_DIR} S_DIR: ${S_DIR}")

# 設定當前目錄及其子目錄的編譯器標誌  
set_directory_properties(PROPERTIES COMPILE_FLAGS "-Wall -Wextra")

# 獲取當前目錄的編譯標誌
get_directory_property(COMPILE_FLAGS COMPILE_FLAGS)

# 列印獲取到的編譯標誌資訊
message("COMPILE_FLAGS: ${COMPILE_FLAGS}")

CMake 輸出如下:

image


【結語】

專案連結(多多star呀..⭐_⭐):

Github 地址:https://github.com/mengps/LearnCMake