本文適合基礎學者 零基礎
makefile
- 定義:Makefile 是一種傳統的構建工具,用于定義如何編譯和鏈接源代碼。它通過一系列規則來描述如何生成目標文件(如可執行文件或庫)。
功能: - 定義編譯規則(如如何從源文件生成目標文件)。
指定依賴關系(如哪些文件需要重新編譯)。
執行編譯、鏈接等任務。 - 特點:
靈活性高,可以直接控制構建過程。
適用于小型項目或簡單的構建需求。
編寫規則需要手動處理依賴關系和平臺差異。
server:g++ server.cpp -o server && g++ client.cpp -o client
即編譯server.cpp 和clien.cpp 分別命名為server 和client
CMake
- 定義:CMake 是一個跨平臺的構建工具生成器。它通過讀取項目的配置文件(通常是 CMakeLists.txt),生成適合特定平臺的構建系統(如 Makefile、Visual Studio 項目文件等)。
- 功能:
自動生成 Makefile 或其他構建系統文件。
檢測平臺和編譯器特性,自動調整構建規則。
管理項目的依賴關系和庫路徑。
支持復雜的項目結構和多平臺構建。 - 特點:
高度抽象,簡化了跨平臺構建的復雜性。
適用于大型項目或需要跨平臺支持的項目。
需要編寫 CMakeLists.txt 文件來描述項目的結構和依賴關系。
總結兩者關系
- Makefile 是一種具體的構建工具,直接用于編譯和鏈接代碼。
- CMake 是一個構建工具生成器,它通過生成 Makefile 或其他構建系統文件來簡化構建過程。
- 關系:CMake 是 Makefile 的“上層工具”,它生成 Makefile,而 Makefile 是實際執行構建任務的工具。
零基礎寫cmake
創建一個cmakelist.txt
運行命令為 cmake .
然后為 make
最基本的cmake
# 設置 CMake 最低版本
cmake_minimum_required(VERSION 3.10)# 定義項目名稱
project(MyProject)# 指定源文件路徑
set(SOURCE_FILESsrc/main.cppsrc/utils.cpp
)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
- set
set(VARIABLE_NAME VALUE1 VALUE2 ... VALUE_N)
-
- VARIABLE_NAME:變量的名稱。
-
- VALUE1 … VALUE_N:變量的值,可以是字符串、路徑、文件名等(文件路徑為項目根目錄的路徑(相對路徑))
- add_executable
add_executable(TARGET_NAME SOURCE_FILES)
-
- TARGET_NAME:生成的可執行文件的名稱。
-
- SOURCE_FILES:用于生成可執行文件的源文件列表($是代表變量的意思)
你也可以不使用變量:
- SOURCE_FILES:用于生成可執行文件的源文件列表($是代表變量的意思)
-
add_executable(my_program src/main.cpp src/utils.cpp)
疑問:他有兩個文件 你怎么一個變量參數?
set 命令可以將多個值賦給一個變量,形成一個列表。當你將這個變量傳遞給 add_executable 時,CMake 會將這個列表展開,作為多個參數傳遞給add_executable。這就是為什么一個變量可以代表多個文件的原因。
鏈接其他庫
前言
靜態庫
- 定義:靜態庫是編譯后的代碼,直接嵌入到可執行文件中。生成的可執行文件是獨立的,不需要額外的庫文件。
優點:可執行文件是獨立的,不需要額外的庫文件。
適合小型項目或需要獨立分發的程序。
缺點:可執行文件體積較大。
庫的更新需要重新編譯整個程序。
動態庫
- 定義:動態庫是編譯后的代碼,但在運行時加載。生成的可執行文件需要在運行時找到動態庫文件。
- 優點:
可執行文件體積較小。
多個程序可以共享同一個動態庫。
庫的更新不需要重新編譯整個程序。 - 缺點:
可執行文件依賴于動態庫文件,需要確保運行時庫文件存在。
需要管理動態庫的路徑。
系統庫(單個庫)
cmake_minimum_required(VERSION 3.10)
project(MyProject)# 指定頭文件路徑
include_directories(include)# 指定源文件
set(SOURCE_FILESsrc/main.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 查找系統庫
find_library(SSL_LIBRARY ssl)# 鏈接到目標
target_link_libraries(${PROJECT_NAME} ${SSL_LIBRARY})
find_library
find_library(VARIABLE_NAME library_name [PATHS path1 path2 ...])
- VARIABLE_NAME:用于存儲找到的庫文件路徑的變量名。
- library_name:要查找的庫文件名(不包括前綴 lib 和后綴 .so、.a 等)。
- PATHS(可選):指定查找庫文件的路徑列表。如果省略,CMake 會在默認的系統庫路徑中查找。
在 Linux 系統中,CMake 會查找以下默認路徑:
/usr/lib
/usr/local/lib
/lib
/usr/lib64(64位系統)
/usr/local/lib64(64位系統
Windows
C:\Windows\System32
C:\Windows\System
C:\Windows
C:\Program Files
C:\Program Files (x86)
你可以通過運行以下命令查看 CMake 的默認庫查找路徑:cmake --help-variable CMAKE_FIND_ROOT_PATH
include_directories ([AFTER|BEFORE] dir1 [dir2 ...])
-
- AFTER 或 BEFORE(可選):指定目錄的優先級。默認是 AFTER,表示目錄會添加到包含路徑的后面。如果指定 BEFORE,目錄會添加到包含路徑的前面。
-
- dir1, dir2, …:要添加的頭文件路徑。
自己的庫
cmake_minimum_required(VERSION 3.10)
project(MyProject)# 添加子目錄(如果庫在子目錄中)
add_subdirectory(lib/mylib)# 指定頭文件路徑
include_directories(include)# 指定源文件
set(SOURCE_FILESsrc/main.cppsrc/utils.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 鏈接到庫
target_link_libraries(${PROJECT_NAME} mylib)
這個你添加目錄 就行了add_subdirectory(lib/mylib)
第三方庫(多庫 可以算框架吧)
cmake_minimum_required(VERSION 3.10)
project(MyProjectWithDependencies)# 指定頭文件路徑
include_directories(include)# 指定源文件
set(SOURCE_FILESsrc/main.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 查找第三方庫(如 Boost)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})
find_package(PackageName [version] [REQUIRED])
-
- PackageName:要查找的包名稱。
-
- version(可選):指定所需的包版本。
-
- REQUIRED(可選):如果包未找到,CMake 會報錯并停止構建。
并設置
- REQUIRED(可選):如果包未找到,CMake 會報錯并停止構建。
Boost_INCLUDE_DIRS:包含 Boost 的頭文件路徑。
Boost_LIBRARIES:包含 Boost 的庫文件路徑。
跨平臺
cmake_minimum_required(VERSION 3.10)
project(MyCrossPlatformProject)# 指定源文件
set(SOURCE_FILESsrc/main.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 根據平臺設置不同的編譯選項
if(WIN32)target_compile_definitions(${PROJECT_NAME} PRIVATE _WIN32)
elseif(APPLE)target_compile_definitions(${PROJECT_NAME} PRIVATE _MACOS)
elseif(UNIX)target_compile_definitions(${PROJECT_NAME} PRIVATE _LINUX)
endif()
target_compile_definitions(TARGET_NAME [INTERFACE|PUBLIC|PRIVATE] definition1 [definition2 ...]) -
-
- TARGET_NAME:目標名稱(通常是通過 add_executable 或 add_library 定義的)。
-
- INTERFACE、PUBLIC、PRIVATE(可選):指定宏的作用域:
-
-
- INTERFACE:宏對目標本身和依賴該目標的其他目標可見。
-
-
- -PUBLIC:宏對目標本身和依賴該目標的其他目標可見。
-
-
- PRIVATE:宏僅對目標本身可見。
-
- definition1, definition2, …:要定義的宏。
優化和調試
Debug 構建
目的:用于開發和調試階段。
特點:
包含調試信息(如符號表),便于使用調試器(如 GDB)進行調試。
不啟用優化,確保代碼的可讀性和調試的準確性。
通常會定義調試相關的宏(如 _DEBUG)。
編譯選項:
-g:生成調試信息。
用途:幫助開發者快速定位和修復問題。
2. Release 構建
目的:用于生產環境或最終發布。
特點:
啟用優化,提高代碼的執行效率。
不包含調試信息,減小可執行文件的體積。
通常會定義發布相關的宏(如 NDEBUG)。
編譯選項:
-O3:啟用最高級別的優化。
用途:確保程序在生產環境中性能最佳。
cmake_minimum_required(VERSION 3.10)
project(MyOptimizedProject)# 指定源文件
set(SOURCE_FILESsrc/main.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 設置編譯選項
if(CMAKE_BUILD_TYPE STREQUAL "Release") #CMAKE_BUILD_TYPE 內置變量 STREQUAL:是否相等target_compile_options(${PROJECT_NAME} PRIVATE -O3) #:GCC/Clang 編譯器的優化選項,啟用最高級別的優化
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")target_compile_options(${PROJECT_NAME} PRIVATE -g) # -g:GCC/Clang 編譯器的選項,用于生成調試信息
endif()
生成安裝腳本
cmake_minimum_required(VERSION 3.10)
project(MyInstallableProject)# 指定源文件
set(SOURCE_FILESsrc/main.cpp
)# 生成可執行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})# 設置安裝路徑
install(TARGETS ${PROJECT_NAME}DESTINATION bin
)
install(TARGETS target1 [target2 ...]DESTINATION destination[RUNTIME DESTINATION runtime_destination][LIBRARY DESTINATION library_destination][ARCHIVE DESTINATION archive_destination][PERMISSIONS permissions...])
TARGETS:指定要安裝的目標(如可執行文件或庫)。
DESTINATION:指定安裝目標的目錄。
RUNTIME DESTINATION(可選):指定可執行文件的安裝目錄。
LIBRARY DESTINATION(可選):指定動態庫的安裝目錄。
ARCHIVE DESTINATION(可選):指定靜態庫的安裝目錄。
PERMISSIONS(可選):指定安裝文件的權限。
示例
假設你有一個項目,需要將生成的可執行文件安裝到 /usr/local/bin 目錄。
DESTINATION:指定安裝目錄,這里是 bin。如果安裝路徑是絕對路徑(如 /usr/local/bin),則文件會被安裝到該路徑。如果路徑是相對的,則文件會被安裝到 CMake 的安裝前綴(默認是 CMAKE_INSTALL_PREFIX,通常是 /usr/local)下的對應目錄。
cmake .#生成makefile文件
make #執行makefile文件
sudo make install#安裝