從零開始:Makefile 與 CMake 的基礎入門與實踐


本文適合基礎學者 零基礎


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:用于生成可執行文件的源文件列表($是代表變量的意思)
      你也可以不使用變量
    • 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 會報錯并停止構建。
      并設置

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#安裝

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/74153.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/74153.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/74153.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android開啟Sys V IPC,并使用共享內存編程

參考:安卓開啟Sys V IPC,并使用共享內存編程 | 久奈浜的CS部 刪除config中-# CONFIG_SYSVIPC is not set 在rk3576.config中增加CONFIG_SYSVIPCy CONFIG_SYSVIPCy CONFIG_SYSVIPC_SYSCTLy CONFIG_SYSVIPC_COMPATy CONFIG_IPC_NSy system/sepolicy/pre…

docker pull lss233/one-api:latest 在哪里運行,作用是什么

docker pull lss233/one-api:latest 在哪里運行,作用是什么 1. 在哪里運行? docker pull lss233/one-api:latest 是一個Docker命令,需在已安裝Docker的環境中執行。 適用環境:本地開發機、服務器、云主機等。前提條件:需先安裝Docker并配置好環境。2. 作用是什么? 該命令…

輪胎廠相關筆記

一、術語 圖解:https://news.yiche.com/hao/wenzhang/38498703/ 1、胚胎 在輪胎制造行業中,“胎胚”(也稱“生胎”或“未硫化輪胎”)是指輪胎在硫化(高溫高壓固化)之前的半成品形態。它是輪胎成型的中間…

開發者視角:應用程序中HTTP代理的集成指南

目錄 一、為何需要HTTP代理? 二、集成方式分階解析 三、關鍵配置管理策略 四、安全與性能平衡 五、調試與問題排查 六、最佳實踐總結 結語 在開發需要與外部網絡交互的應用程序時,HTTP代理是繞不開的實用工具。它既能解決網絡限制問題&#xff0c…

從紙質到 AI 時代:我的筆記工具探索之旅

今天清晨,在得到上閑逛時,偶然間發現了一本名為《筆記的方法》的書,這本由Flomo的作者出版的圖書,深入探討了記筆記的藝術。 說起記筆記,這些年來,我嘗試了各種各樣的工具,今天就來梳理一下我的…

Ubuntu22云服務器添加2G Swap分區

Ubuntu22云服務器添加2G Swap分區 步驟 1:檢查當前 Swap 和內存步驟 2:創建 2GB 的 Swap 文件步驟 3:設置權限并格式化步驟 4:啟用 Swap 文件步驟 5:永久保留 Swap 配置可選優化:調整 Swappiness驗證結果注…

網絡空間安全(43)Linux實戰篇

一、系統配置安全 BIOS安全設置 設置BIOS密碼:防止未授權用戶修改BIOS設置。修改引導次序:禁止從軟盤啟動系統,減少潛在的啟動攻擊風險。 文件系統權限管理 最小化SUID權限程序:SUID(Set User ID)程序以ro…

軟件的常用設計模式。可參考一個一個學習

以下是軟件設計中常見的 **23種經典設計模式**(基于《設計模式:可復用面向對象軟件的基礎》GoF 的經典分類),并結合 **Python 語言特性**的簡要說明和典型應用場景。我將它們分為 **創建型、結構型、行為型** 三大類,供…

性能比拼: Go(Gin) vs Python(Flask)

本內容是對知名性能評測博主 Anton Putra Go (Golang) vs Python Performance Benchmark (Kubernetes - OpenTelemetry - Prometheus - S3/Postgres) 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準 在本視頻中,我們將比較 Golang 和 Python 的性能。 但…

Android版本更新服務通知下載實現

在日常開發中,我們肯定會有檢查版本更新的需求,那我版本更新的輪子網上也是有的,想自己實現一下代碼如下: 下載管理類: public class DownLoadManager {private static final String MAIN "main"; //Tagp…

UE5學習筆記 FPS游戲制作33 換子彈 動畫事件

新建動畫蒙太奇 為Rifle和Launcher各自新建一個動畫蒙太奇,拖入動畫,注意動畫的軌道要和動畫藍圖里的一致 在蒙太奇添加動畫事件 在通知一欄新增一個軌道,右鍵軌道,新增一個 換槍完成 通知,不同動畫的同名通知需要…

uniapp中uploadFile的用法

基本語法 uni.uploadFile(OBJECT)OBJECT 是一個包含上傳相關配置的對象,常見參數如下: 參數類型必填說明urlString是開發者服務器地址。filePathString是要上傳文件資源的本地路徑。nameString是文件對應的 key,開發者在服務端可以通過這個 …

Android設計模式之責任鏈模式

一、定義: 使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關系將這些對象連城一條鏈,并沿著這條鏈傳遞該請求,只到有對象處理它為止。 二、模式結構: 抽象處理者(Handler&#xff…

Oracle數據庫數據編程SQL<3.3 PL/SQL 游標>

游標(Cursor)是Oracle數據庫中用于處理查詢結果集的重要機制,它允許開發者逐行處理SQL語句返回的數據。 目錄 一、游標基本概念 1. 游標定義 2. 游標分類 二、靜態游標 (一)顯式游標 【一】不帶參數,普通的顯示游標 1. 顯式…

逗萬DareWorks|創意重構書寫美學,引領新潮無界的文創革命

當傳統文具陷入同質化泥潭時,逗萬DareWorks品牌猶如一顆璀璨的明星,以其獨特的創意理念和卓越的產品品質,迅速贏得了廣大消費者的青睞。 逗萬DareWorks隸屬于東莞司貿文教贈品有限公司,后者深耕制筆行業45年,占地4.6萬…

寫Prompt的技巧和基本原則

一.基本原則 1.一定要描述清晰你需要大模型做的事情,不要模棱兩可 2.告訴大模型需要它做什么,不需要做什么 改寫前: 請幫我推薦一些電影 改寫后: 請幫我推薦2025年新出的10部評分比較高的喜劇電影,不要問我個人喜好等其他問題&#xff…

【React】基于 React+Tailwind 的 EmojiPicker 選擇器組件

1.背景 React 寫一個 EmojiPicker 組件,基于 emoji-mart 組件二次封裝。支持添加自定義背景 、Emoji 圖標選擇!并在頁面上展示! 2.技術棧 emoji-mart/data 、emoji-mart : emoji 圖標庫、元數據 tailwindcss: 原子化 CSS 樣式庫 antd : 組…

Qt中繪制不規則控件

在Qt中繪制不規則控件可通過設置遮罩(Mask)實現。以下是詳細步驟: ?繼承目標控件?:如QPushButton或QWidget。?重寫resizeEvent?:當控件大小變化時,更新遮罩形狀。?創建遮罩區域?:使用QRegion或QPain…

Parallel_Scheduling_of_DAGs_under_Memory_Constraints論文閱讀

內存約束下的 DAG 并行調度 點擊閱讀原文語雀鏈接更清晰 摘要 科學工作流通常被建模為任務的有向無環圖(DAG),這些任務代表計算模塊及其依賴關系,依賴關系表現為任務生成的數據被其他任務使用。這種形式化方法允許使用運行時系統&…

探索MVC、MVP、MVVM和DDD架構在不同編程語言中的實現差異

MVC與MVP/MVVM/DDD架構對比,不同語言實現 MVC 分層架構設計概述 模型-視圖-控制器(Model-View-Controller,簡稱 MVC)是一種經典軟件架構設計,通過分層解耦,使得系統結構清晰和易于維護,具有良…