文章目錄
- CMake 的基本語法和用法
- 1. CMakeLists.txt 基本結構
- 2. 變量和宏
- 3. 條件語句
- 4. 循環語句
- 5. 定義和使用函數
- 6. 導入庫和鏈接庫
- 7. 設置編譯器選項
- message
- 1. 顯示普通消息:
- 2. 顯示帶模式的消息:
- 3. 顯示變量值:
- 4. 顯示多行消息:
- 5. 顯示條件消息:
- set的常見用法
- 1. 簡單的變量定義:
- 2. 定義列表變量:
- 3. 引用變量的值:
- 4. 添加到已有變量:
- 5. 條件設置:
- 6. 緩存變量:
- file
- 1. 復制文件
- 2. 創建目錄
- 3. 移動文件
- 4. 移除文件
- 5. 讀取文件內容
- 6. 寫入文件內容
- add_library
- 1. 添加靜態庫:
- 2. 添加共享庫:
- 3. 添加模塊庫:
- 4. 添加源文件到現有庫:
- target_sources
- target_include_directories
- target_link_libraries
- 1. 鏈接到其他庫:
- 2. 鏈接到多個庫:
- 3. 鏈接到系統庫:
- 4. 鏈接到第三方庫:
- 5. 鏈接到其他目標:
- 6. 指定鏈接選項:
- PUBLIC關鍵字
- 參考
CMake(Cross-platform Make,跨平臺構建)是一個跨平臺的構建工具,用于管理項目的構建過程。它使用簡單的配置文件(CMakeLists.txt
)來生成本地化的構建文件,如 Makefile 或 Visual Studio 解決方案。
以下是 CMake 的基本語法和用法:
CMake 的基本語法和用法
1. CMakeLists.txt 基本結構
一個簡單的 CMakeLists.txt
文件通常包含以下基本結構:
# 最小版本要求
cmake_minimum_required(VERSION 3.10)# 項目名稱
project(MyProject)# 設置 C++ 標準
set(CMAKE_CXX_STANDARD 11)# 添加可執行文件或庫的源文件
add_executable(MyExecutable main.cpp)# 添加子目錄,進入子目錄繼續構建
add_subdirectory(subdirectory_name)
2. 變量和宏
# 定義變量
set(SOURCES file1.cpp file2.cpp)# 使用變量
add_executable(MyExecutable ${SOURCES})# 定義宏
macro(my_macro arg1 arg2)# 宏體message("Arguments: ${arg1}, ${arg2}")
endmacro()# 使用宏
my_macro(value1 value2)
3. 條件語句
# 條件語句
if(CONDITION)# 條件成立時執行的命令
elseif(ANOTHER_CONDITION)# 另一個條件成立時執行的命令
else()# 如果所有條件都不成立時執行的命令
endif()
4. 循環語句
# 循環語句
foreach(item IN LISTS my_list)# 循環體message(${item})
endforeach()
5. 定義和使用函數
# 定義函數
function(my_function arg1 arg2)# 函數體message("Arguments: ${arg1}, ${arg2}")
endfunction()# 使用函數
my_function(value1 value2)
6. 導入庫和鏈接庫
# 導入庫
find_library(MY_LIBRARY my_library)# 鏈接庫
target_link_libraries(MyExecutable ${MY_LIBRARY})
7. 設置編譯器選項
# 設置編譯器選項
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")# 或者
add_compile_options(-Wall)
message
message
命令用于在 CMake 構建過程中輸出信息。它對于調試和顯示構建腳本中的信息非常有用。基本語法如下:
message([<mode>] "message to display" ...)
其中:
<mode>
是可選的,用于指定消息的模式,可以是STATUS
、WARNING
、AUTHOR_WARNING
、SEND_ERROR
、FATAL_ERROR
或DEPRECATION
。如果省略<mode>
,則默認為STATUS
。"message to display"
是要顯示的消息字符串。
以下是一些 message
命令的使用示例:
1. 顯示普通消息:
message("This is a normal message.")
2. 顯示帶模式的消息:
message(STATUS "This is a status message.")
message(WARNING "This is a warning message.")
message(SEND_ERROR "This is an error message.")
message(FATAL_ERROR "This is a fatal error message.")
3. 顯示變量值:
set(my_variable "Hello, CMake!")
message("Value of my_variable: ${my_variable}")
4. 顯示多行消息:
message(STATUS "This is a multi-line message.\n""It spans multiple lines.")
5. 顯示條件消息:
if(MY_CONDITION)message("Condition is true.")
else()message("Condition is false.")
endif()
message
命令對于調試 CMakeLists.txt 文件和構建過程中的問題非常有幫助。通過在適當的位置添加消息,可以更容易地理解 CMake 腳本的執行過程,以及在構建時的一些關鍵信息。
set的常見用法
在 CMake 中,set
命令用于定義變量。這個命令的基本語法是:
set(variable_name value1 value2 ...)
其中,variable_name
是變量的名稱,而 value1 value2 ...
是變量的值。可以通過空格分隔多個值。
以下是一些 set
命令的常見用法:
1. 簡單的變量定義:
set(my_variable "Hello, CMake!")
2. 定義列表變量:
set(my_list_variable "item1" "item2" "item3")
3. 引用變量的值:
message("Value of my_variable: ${my_variable}")
4. 添加到已有變量:
set(my_variable "Hello")
set(my_variable "${my_variable}, CMake!")
5. 條件設置:
if(SOME_CONDITION)set(my_variable "Value1")
else()set(my_variable "Value2")
endif()
6. 緩存變量:
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type (Debug/Release)" FORCE)
在這個例子中,CMAKE_BUILD_TYPE
是一個緩存變量,用于指定構建類型。FORCE
選項表示如果已經存在這個緩存變量,就覆蓋它。
更多的使用場景和用法可以在CMake 官方文檔中查看更詳細的信息:
CMake - set Command。
file
在 CMake 中,file
命令用于操作文件系統。這個命令有多個子命令,用于執行不同的文件操作。以下是一些常見的 file
命令的用法:
1. 復制文件
file(COPY source_file DESTINATION destination_directory)
這個命令用于將文件從一個位置復制到另一個位置。例如:
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
2. 創建目錄
file(MAKE_DIRECTORY directory_path)
這個命令用于創建目錄。例如:
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/my_directory)
3. 移動文件
file(RENAME old_name new_name)
這個命令用于移動或重命名文件。例如:
file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/file.txt ${CMAKE_CURRENT_BINARY_DIR}/new_file.txt)
4. 移除文件
file(REMOVE [files...])
這個命令用于移除文件。例如:
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/unnecessary_file.txt)
5. 讀取文件內容
file(READ filename variable)
這個命令用于讀取文件的內容并存儲到一個變量中。例如:
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.txt VERSION)
message("Version: ${VERSION}")
6. 寫入文件內容
file(WRITE filename content)
這個命令用于將指定的內容寫入文件。例如:
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/output.txt "Hello, CMake!")
以上是 file
命令的一些常見用法,還有其他更多的子命令和選項,可以在 CMake 官方文檔中查看更詳細的信息:
CMake - file Command。
add_library
在 CMake 中,add_library
命令用于定義和構建一個庫。這個命令的基本語法如下:
add_library(<library_name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL]source1 [source2 ...])
其中:
<library_name>
是庫的名稱,可以在后續的target_link_libraries
命令中使用這個名稱引用這個庫。[STATIC | SHARED | MODULE]
用于指定庫的類型,可以是靜態庫(STATIC
,默認),共享庫(SHARED
),或模塊庫(MODULE
)。[EXCLUDE_FROM_ALL]
是一個可選項,如果指定了,將把這個庫從構建過程的默認目標中排除。
以下是一些 add_library
命令的用法示例:
1. 添加靜態庫:
add_library(my_static_lib STATIC source1.cpp source2.cpp)
2. 添加共享庫:
add_library(my_shared_lib SHARED source1.cpp source2.cpp)
3. 添加模塊庫:
add_library(my_module_lib MODULE source1.cpp source2.cpp)
4. 添加源文件到現有庫:
add_library(my_static_lib STATIC source1.cpp)
add_library(my_shared_lib SHARED source2.cpp)# 添加 source2.cpp 到 my_static_lib 和 my_shared_lib
target_sources(my_static_lib PRIVATE source2.cpp)
target_sources(my_shared_lib PRIVATE source2.cpp)
在上述示例中,my_static_lib
和 my_shared_lib
是庫的名稱,source1.cpp
和 source2.cpp
是庫的源文件。
可以在 CMake 官方文檔中查看更詳細的信息:
CMake - add_library。
target_sources
target_sources
命令用于將源文件添加到一個已經存在的 CMake 目標(例如,可執行文件、庫)。這個命令的基本語法如下:
target_sources(target_namePRIVATE source1 [source2 ...]PUBLIC source3 [source4 ...]INTERFACE source5 [source6 ...]
)
target_name
是目標的名稱,可以是可執行文件或庫的名稱,由add_executable
或add_library
命令定義。PRIVATE
,PUBLIC
, 和INTERFACE
是關鍵字,用于指定添加源文件的屬性。
PRIVATE
, PUBLIC
, 和 INTERFACE
關鍵字分別表示:
PRIVATE
: 源文件只會在目標的編譯和鏈接階段中可見,不會傳遞給依賴此目標的其他目標。PUBLIC
: 源文件會在目標的編譯和鏈接階段中可見,并且會傳遞給依賴此目標的其他目標。INTERFACE
: 源文件不會被添加到目標的編譯和鏈接階段中,但會傳遞給依賴此目標的其他目標。
以下是一些 target_sources
命令的使用示例:
# 添加私有源文件到目標
target_sources(my_executable PRIVATE source1.cpp source2.cpp)# 添加公共源文件到目標
target_sources(my_library PUBLIC source3.cpp source4.cpp)# 添加接口源文件到目標
target_sources(my_interface_library INTERFACE source5.cpp source6.cpp)
在上述示例中,my_executable
、my_library
、和 my_interface_library
是目標的名稱,source1.cpp
到 source6.cpp
是源文件的名稱。
target_sources
命令使得在 CMakeLists.txt 文件中添加源文件更加靈活,可以將源文件與目標關聯起來,而不是直接將它們列在 add_executable
或 add_library
命令中。這樣可以更容易地組織代碼,并且在不同目標之間共享源文件。
target_include_directories
target_include_directories
用于向一個目標(例如可執行文件或庫)添加頭文件目錄。這個命令的基本語法如下:
target_include_directories(target_name[SYSTEM] [BEFORE]INTERFACE|PUBLIC|PRIVATE[items1...][INTERFACE|PUBLIC|PRIVATE[items2]...]
)
其中:
target_name
是目標的名稱,可以是可執行文件或庫的名稱,由add_executable
或add_library
命令定義。SYSTEM
關鍵字用于將目錄標記為系統目錄,通常用于禁止特定編譯器的警告。BEFORE
關鍵字用于將目錄添加到當前目錄列表的前面,而不是后面。
INTERFACE
, PUBLIC
, 和 PRIVATE
關鍵字的含義與 target_sources
中的相同:
INTERFACE
: 目錄不會被添加到目標的編譯和鏈接階段中,但會傳遞給依賴此目標的其他目標。PUBLIC
: 目錄會在目標的編譯和鏈接階段中可見,并會傳遞給依賴此目標的其他目標。PRIVATE
: 目錄只會在目標的編譯和鏈接階段中可見,不會傳遞給依賴此目標的其他目標。
以下是一些 target_include_directories
命令的使用示例:
# 添加私有頭文件目錄到目標
target_include_directories(my_executable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)# 添加公共頭文件目錄到目標
target_include_directories(my_library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)# 添加接口頭文件目錄到目標
target_include_directories(my_interface_library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
在上述示例中,my_executable
、my_library
和 my_interface_library
是目標的名稱,${CMAKE_CURRENT_SOURCE_DIR}/include
是頭文件目錄的路徑。
target_include_directories
的主要目的是確保正確的頭文件路徑在編譯和鏈接階段中可用,并且能夠傳遞給依賴此目標的其他目標。這有助于更好地組織項目中的頭文件和確保正確的構建過程。
target_link_libraries
target_link_libraries
是 CMake 中的一個關鍵命令,用于指定一個目標(例如可執行文件或庫)所依賴的其他庫。這個命令的基本語法如下:
target_link_libraries(target_nameitem1item2...
)
其中:
target_name
是目標的名稱,可以是可執行文件或庫的名稱,由add_executable
或add_library
命令定義。item1
,item2
, … 是目標所依賴的其他庫或庫的名稱。
以下是一些 target_link_libraries
命令的使用示例:
1. 鏈接到其他庫:
# 鏈接到名為 my_library 的庫
target_link_libraries(my_executable my_library)
2. 鏈接到多個庫:
# 鏈接到名為 my_library1 和 my_library2 的庫
target_link_libraries(my_executable my_library1 my_library2)
3. 鏈接到系統庫:
# 鏈接到系統庫,例如 pthread
target_link_libraries(my_executable pthread)
4. 鏈接到第三方庫:
# 鏈接到第三方庫,例如 Boost
target_link_libraries(my_executable Boost::filesystem)
5. 鏈接到其他目標:
# 鏈接到另一個目標
target_link_libraries(my_executable my_other_target)
6. 指定鏈接選項:
# 指定鏈接選項
target_link_libraries(my_executable PRIVATE -Wl,-rpath,/custom/library/path)
上述示例中,my_executable
是目標的名稱,my_library
, my_library1
, my_library2
, pthread
, Boost::filesystem
, my_other_target
是目標依賴的庫或目標。
target_link_libraries
命令用于確保在鏈接目標時正確地包含所需的庫。這對于確保可執行文件或庫在構建和運行時都能正確鏈接到依賴項非常重要。
PUBLIC關鍵字
下面以target_link_libraries
為例,分析PUBLIC關鍵字。
target_link_libraries
命令中的 PUBLIC
關鍵字用于指定庫的依賴關系,并將這些依賴關系傳遞給依賴于當前目標的其他目標。用于確保在鏈接時包含正確的依賴項。
基本語法如下:
target_link_libraries(target_namePUBLIC item1PUBLIC item2...
)
使用 PUBLIC
關鍵字的效果是,item1
, item2
, … 這些庫將不僅會被鏈接到當前目標,還會傳遞給依賴于當前目標的其他目標。
示例:
# 定義一個庫
add_library(my_library STATIC my_library.cpp)# 定義一個可執行文件,鏈接到 my_library
add_executable(my_executable main.cpp)
target_link_libraries(my_executable PUBLIC my_library)
示例中,my_executable
依賴于 my_library
,而且 my_library
中的依賴項也會傳遞給 my_executable
。
使用 PUBLIC
關鍵字還允許在 INTERFACE
和 PRIVATE
之間共享依賴關系。例如,PUBLIC
的依賴項既會被當前目標使用,也會被依賴于當前目標的其他目標使用。
參考
https://cmake.org/documentation/