Makefile 從入門到精通:自動化構建的藝術

引入

在軟件開發的世界里,“編譯” 是繞不開的環節,但手動編譯大型項目時,重復輸入編譯命令的痛苦,相信每個開發者都深有體會。Makefile 作為自動化構建的基石,能讓編譯過程“一鍵完成”,甚至智能判斷文件變化,只重新編譯修改的部分。本文將從基礎到進階,帶你吃透 Makefile 的核心邏輯與實戰技巧。

一、基礎認知:Make 和 Makefile 是什么?

1.1 核心角色分工

  • make:是一個 命令行 工具,負責解釋執行 Makefile 中的規則,判斷哪些文件需要編譯、如何編譯。
  • Makefile:是一個 文本文件 ,定義了 “目標 → 依賴 → 命令” 的規則,描述項目的構建邏輯(哪些文件先編譯、哪些后編譯)。

類比:make 是“工人”,Makefile 是“施工圖紙”,兩者配合完成自動化構建。

1.2 為什么需要 Makefile?

想象一個場景:項目有 100 個 .c 文件,每次修改一個文件,都要手動輸入 gcc -o app a.c b.c ... z.c,效率極低。而 Makefile 能做到:

  • 自動化:只需 make 命令,自動完成編譯、鏈接。
  • 增量編譯:僅重新編譯修改過的文件(通過比較文件的**修改時間(Modify Time)**判斷)。
  • 可擴展:支持清理、測試、打包等自定義操作(如 make clean)。

1.3 Make的核心工作邏輯

Make的核心任務是**“維護目標的最新狀態”**,它判斷是否執行命令的依據是:
比較“目標”和“依賴”的“最后修改時間”

  • 如果“目標不存在” → 必須執行命令生成目標;
  • 如果“目標存在,但依賴的修改時間比目標更新” → 必須執行命令更新目標;
  • 如果“目標存在,且依賴沒更新(比目標舊)” → 認為執行命令(認為目標已最新)。

二、初體驗:單文件項目的 Makefile

2.1 代碼示例(myproc.c

#include <stdio.h>
int main() {printf("Hello Makefile!\n");return 0;
}

2.2 最簡 Makefile 編寫

#  目標    :   依賴
myproc.exe: myproc.c  # 命令gcc -o myproc.exe myproc.c  #(必須以 Tab 開頭!)# 清理操作(偽目標)
.PHONY: clean  # 聲明 clean 是偽目標
clean:   #依賴可以為空,這就意味著不需要任何依賴rm -f myproc.exe  #(必須以 Tab 開頭!)

2.3 關鍵概念解析

  1. 目標(Target)
    • 可以是 實際文件(如 myproc.exe,需要生成的產物),也可以是 偽目標(如 clean,代表一個動作)。
    • Make 默認執行 第一個目標(這里是 myproc.exe),也可以通過 make clean 顯式指定目標。
  2. 依賴(Prerequisites)
    • 生成目標所需的文件(如 myproc.c 是編譯 myproc.exe 的依賴)。
    • Make 會比較 目標和依賴的修改時間:如果依賴的修改時間更晚(比如修改了 myproc.c),就會重新執行命令。
  3. 命令(Recipe)
    • 生成目標的具體操作(如 gcc 編譯、rm 刪除)。
    • 必須以 Tab 開頭:這是 Makefile 的語法要求,用空格代替會導致語法錯誤。
  4. 偽目標(.PHONY)
    • 作用:告訴 Make,clean 不是一個實際文件,而是一個“動作”。
    • 場景:如果當前目錄有一個叫 clean 的文件,沒有 .PHONY 聲明時make clean 會認為“目標已存在,無需執行”;.PHONY 聲明時,即使存在 clean 文件,也會執行 rm 命令。

2.4 常見的問題

問題1: 聲明.PHONY和不聲明的核心區別 ?

關鍵區別在于:Make是否會檢查“目標名是否對應一個實際存在的文件”

我們用同一個clean目標對比:

場景1:不聲明.PHONY: clean
# 沒有.PHONY聲明
clean:rm -f myproc.exe

當一個目標沒有被.PHONY聲明時,Make會默認把它當作一個“需要生成的文件”,執行以下嚴格檢查:

檢查步驟:
  1. 檢查“目標是否對應實際文件”
    • 比如目標是clean,Make會先看當前目錄有沒有叫clean的文件。
  2. 檢查“依賴是否比目標更新”
    • 如果目標文件存在,再看它的依賴(如果有)的修改時間是否比目標文件晚。
執行邏輯:

只有滿足以下任一條件,才會執行命令:

  • 目標文件不存在
  • 目標文件存在,但依賴的修改時間比目標更新
場景2:聲明.PHONY: clean
.PHONY: clean  # 有聲明
clean:rm -f myproc.exe

當目標.PHONY聲明后,Make會明確:“這不是一個需要生成的文件,而是一個動作”,因此跳過所有“文件相關的檢查”

跳過的檢查:
  1. 不檢查目錄中是否存在同名文件(哪怕有clean文件,也假裝沒看見);
  2. 不比較依賴的修改時間(即使有依賴,也默認“需要執行命令”)。
執行邏輯:

只要你調用make 偽目標(如make clean),就一定會執行下面的命令,無論任何情況。

一句話結論

.PHONY的作用是給目標“去文件化”

  • 不聲明:Make把目標當文件,用“存在性+時間戳”判斷是否執行命令(可能被同名文件卡住);
  • 聲明后:Make把目標當動作,跳過所有文件檢查,每次調用必執行命令(永遠生效)。

問題2: 為什么make執行時只運行前面的代碼,后面的不運行?

因為Make的默認行為是:只執行第一個目標(稱為“默認目標”),其他目標需要“顯式指定”才會運行。

比如你的Makefile:

# 第一個目標(默認目標)
myproc.exe: myproc.c  gcc -o myproc.exe myproc.c  # 第二個目標(非默認)
.PHONY: clean  
clean:  rm -f myproc  
  • 當你直接輸入 make 時,Make只會找第一個目標myproc.exe,執行它的編譯命令,后面的clean目標完全不碰。
  • 如果你想運行后面的clean,必須顯式指定:make clean(此時才會執行rm命令)。

總結概括

  1. “忽略同名文件”:偽目標的命令是否執行,和有沒有同名文件沒關系,一定執行。
  2. .PHONY的作用:給目標打“動作標簽”,避免被同名文件干擾,保證命令100%執行。
  3. Make默認只跑第一個目標,其他目標需要用make 目標名(如make clean)顯式調用。

2.5 實驗:理解“增量編譯”

  1. 執行 make:生成 myproc.exe,首次編譯所有代碼。
  2. 修改 myproc.c 后,再次執行 make:僅重新編譯 myproc.c(因為它的修改時間比 myproc.exe 新)。
  3. 執行 make clean:刪除 myproc.exe,為下次編譯做準備。

背后邏輯make 通過比較 文件修改時間(Modify Time) 判斷是否需要重新編譯。可用 stat myproc.c 查看文件時間戳。

三、深入:編譯過程的分解與依賴鏈

實際編譯分為 4 個階段:預處理(.i)→ 編譯(.s)→ 匯編(.o)→ 鏈接(可執行文件)。我們可以在 Makefile 中分解每個階段,觀察依賴鏈的遞歸處理。

3.1 分解編譯步驟的 Makefile

#最終目標
myproc.exe:myproc.ogcc myproc.o -o myproc.exe  # 鏈接階段# 匯編 → 目標文件myproc.o:myproc.sgcc -c myproc.s -o myproc.o  # 匯編階段# 編譯 → 匯編代碼myproc.s:myproc.igcc -S myproc.i -o myproc.s  # 編譯階段# 預處理 → 展開頭文件myproc.i:myproc.cgcc -E myproc.c -o myproc.i  # 預處理階段

在這里插入圖片描述

3.2 Make 的依賴解析流程

當執行 make 時,make 會:

  1. 找到第一個目標 myproc.exe,檢查它是否存在,或依賴的 myproc.o 是否更新。
  2. myproc.o 不存在,遞歸查找 myproc.o 的依賴 myproc.s,繼續遞歸直到最底層的 myproc.c
  3. myproc.c 開始,依次執行預處理、編譯、匯編、鏈接,最終生成 myproc.exe

類比:像“剝洋蔥”一樣,從終極目標層層拆解,直到最基礎的源文件,再反向構建。

四、Make 的工作原理:規則與時間戳

4.1 核心機制:文件時間戳比較

每個文件有三個關鍵時間戳(可通過 stat 命令查看):

  • Modify Time(Mtime):文件內容修改時更新(決定編譯是否觸發)。

  • Change Time(Ctime):文件屬性(如權限)修改時更新。

  • Access Time(Atime):文件被訪問時更新(Linux 早期版本會頻繁更新,現在默認關閉)。
    在這里插入圖片描述
    make 只關注 Mtime:如果目標文件的 Mtime 比依賴的 Mtime 新,就不會進行編譯,反觀就會執行。

    在這里插入圖片描述

4.2 執行流程詳解

  1. 找規則:在當前目錄找 Makefilemakefile
  2. 定目標:以第一個目標為“終極目標”(如 myproc.exe)。
  3. 查依賴:檢查目標是否存在,或依賴的文件 Mtime.exe 是否更新。
  4. 遞歸處理:若依賴不存在,遞歸查找依賴的依賴(如 myproc.exemyproc.omyproc.s → … → myproc.c)。
  5. 執行命令:按規則執行命令,生成目標。
  6. 錯誤處理:依賴缺失直接報錯;命令執行失敗(如編譯出錯),默認繼續執行后續命令(可通過 .DELETE_ON_ERROR 改變)。

4.3 常見問題:為什么修改了文件,make 沒反應?

  • 原因 1:依賴沒寫對(比如頭文件修改了,但 Makefile 沒聲明頭文件為依賴)。
  • 原因 2:文件時間戳沒更新(比如通過網絡復制文件,Mtime 可能被覆蓋)。
  • 解決
    • touch 文件名 強制更新 Mtime。
    • 顯式聲明頭文件依賴(后續會講自動生成依賴的方法)。

五、擴展語法:高效管理多文件項目

當項目有多個 .c 文件時,手動寫每個文件的規則效率極低。利用 變量、模式規則、自動變量 可大幅簡化 Makefile。

綜合案例:

BIN=NJ.exe
#SRC=$(shell ls *.c)
SRC=$(wildcard *.c) # wildcard函數,獲取當前目錄下的所有的原文件
OBJ=$(SRC:.c=.o)
CC=gcc
Echo=echo
Rm=rm -rf$(BIN):$(OBJ)@$(CC) -o $@ $^@$(Echo) "linking $^ to $@ ... done"
%.o:%.c@$(CC) -c $<@$(Echo) "compling $< to $@ ... done".PHONY:clean
clean:$(Rm) $(OBJ) $(BIN).PHONY:test
test:@echo "Debug-------"@echo $(SRC);@echo "Debug-------"@echo $(OBJ);@echo "Debug-------"

1、變量定義:給文件/命令起“外號”

BIN=NJ.exe  
#SRC=$(shell ls *.c)  
SRC=$(wildcard *.c)  
OBJ=$(SRC:.c=.o)  
CC=gcc  
Echo=echo  
Rm=rm -rf  
代碼行符號/語法解析實際作用
BIN=NJ.exe定義變量 BIN,值為 NJ.exe(最終生成的可執行文件名)。后續用 $(BIN) 代替 NJ.exe,修改文件名只需改這里。
#SRC=$(shell ls *.c)(注釋行)使用 shell 函數執行 ls *.c 獲取 .c 文件,不推薦(依賴系統 Shell,兼容性差)。被更安全的 wildcard 替代。
SRC=$(wildcard *.c)- wildcard:Make 內置函數,獲取當前目錄所有 .c 文件(如 a.c b.c)。自動識別所有 .c 文件,新增文件無需修改 Makefile。
OBJ=$(SRC:.c=.o)- 變量替換:把 SRC 中每個字符串的 .c 后綴替換為 .o(如 a.c→a.o)。自動生成目標文件列表(.o),無需手動寫 a.o b.o
CC=gcc定義編譯器為 gcc(可改為 clang 等,統一修改)。方便切換編譯器,避免遍歷命令修改。
Echo=echo定義 echo 命令(統一管理輸出)。后續用 $(Echo) 代替 echo,修改輸出行為更方便。
Rm=rm -rf定義刪除命令(帶 -rf 參數,強制遞歸刪除)。后續用 $(Rm) 代替 rm -rf,統一控制刪除邏輯。

2、鏈接規則:把 .o 拼成可執行文件

$(BIN):$(OBJ)  @$(CC) -o $@ $^  @$(Echo) "linking $^ to $@ ... done"  
代碼行符號/語法解析實際作用
$(BIN):$(OBJ)- 目標:$(BIN)(可執行文件,如 NJ.exe);
- 依賴:$(OBJ)(所有 .o 文件)。
只有當 .o 文件存在且最新時,才會觸發鏈接操作
@$(CC) -o $@ $^- @抑制命令回顯(執行時不打印 gcc ...,只顯示結果);
- $@:當前規則的目標文件$(BIN),如 NJ.exe);
- $^:當前規則的所有依賴文件$(OBJ),如 a.o b.o)。
調用 gcc,將所有 .o 文件鏈接成可執行文件(如 gcc -o bite.exe a.o b.o)。
@$(Echo) "linking $^ to $@ ... done"- $^ 替換為 .o 文件列表,$@ 替換為可執行文件名。打印鏈接完成提示(如 linking a.o b.o to NJ.exe ... done)。

3、模式規則:批量編譯 .c→.o

%.o:%.c  @$(CC) -c $<  @$(Echo) "compiling $< to $@ ... done"  
代碼行符號/語法解析實際作用
%.o:%.c- %通配符,匹配任意字符串(如 a.o 匹配 a.cb.o 匹配 b.c)。批量處理所有 .c 文件,無需為每個 .c 寫單獨規則。
@$(CC) -c $<- $<:當前規則的第一個依賴文件(即匹配的 .c 文件,如 a.c);
- -c:只編譯,不鏈接(生成 .o 中間文件)。
調用 gcc,將單個 .c 文件編譯.o(如 gcc -c a.c)。
@$(Echo) "compiling $< to $@ ... done"- $< 替換為 .c 文件名,$@ 替換為 .o 文件名。打印編譯完成提示(如 compiling a.c to a.o ... done)。

4、偽目標 clean:刪除編譯產物

.PHONY:clean  
clean:  $(Rm) $(OBJ) $(BIN)  
代碼行符號/語法解析實際作用
.PHONY:clean聲明 clean偽目標(不是實際文件,而是“動作”)。即使目錄有 clean 文件,make clean 仍會執行(否則會因“文件已存在”跳過)。
$(Rm) $(OBJ) $(BIN)- $(Rm)rm -rf$(OBJ) 是所有 .o 文件,$(BIN) 是可執行文件。刪除編譯中間產物(.o)和最終可執行文件(如 rm -rf a.o b.o NJ.exe)。

5、逐個拆符號:像學“暗號”一樣記

1. $(變量名) → “引用外號”
  • 作用:用一個簡單的名字代替長內容(類似給文件起外號)。
  • 例子:
    前面定義了 BIN = myprog.exe,后面寫 $(BIN) 就等于寫 myprog.exe
    比如規則1的目標 $(BIN) 其實就是 myprog.exe
2. $@ → “當前規則的目標”
  • 作用:在命令里代替“當前要生成的文件”(規則中冒號左邊的內容)。
  • 例子:
    規則1中,目標是 $(BIN)(也就是 myprog.exe),所以命令里的 $@ 就代表 myprog.exe
    命令 gcc -o $@ $^ 其實就是 gcc -o myprog.exe main.o
3. $^ → “當前規則的所有依賴”
  • 作用:在命令里代替“當前規則中冒號右邊的所有文件”。
  • 例子:
    規則1的依賴是 main.o,所以 $^ 就代表 main.o
    (如果依賴有多個,比如 a.o b.o$^ 就代表 a.o b.o
4. $< → “當前規則的第一個依賴”
  • 作用:在命令里代替“當前規則中冒號右邊的第一個文件”。
  • 例子:
    規則2的依賴是 main.c(只有一個),所以 $< 就代表 main.c
    命令 gcc -c $< 其實就是 gcc -c main.c
5. % → “通配符(任意名字)”
  • 作用:寫“通用規則”,不用為每個文件單獨寫規則(省事兒)。
  • 例子:
    如果有 a.cb.c 多個源文件,不用寫 a.o:a.cb.o:b.c,直接寫:
    %.o: %.c  # 意思是:所有的 .o 文件,都由對應的 .c 文件生成gcc -c $<  # $< 會自動換成 a.c、b.c 等
    
    這里的 % 就像“占位符”,a.o 對應 a.cb.o 對應 b.c
6. @ → “命令前加@,不顯示命令本身”
  • 作用:讓終端只顯示命令的結果,不顯示命令本身(看起來干凈)。
  • 例子:
    規則1里的 @echo "搞定了!",執行時終端只顯示 搞定了!
    如果不加 @,會顯示 echo "搞定了!" 再顯示 搞定了!
7. wildcard → “找文件的工具”
  • 作用:自動找出所有符合條件的文件(比如所有 .c 文件)。
  • 例子:
    SRC = $(wildcard *.c) 意思是“把當前目錄下所有 .c 文件的名字都找出來,存到變量 SRC 里”。
    如果有 a.cb.cSRC 就等于 a.c b.c
8. $(變量名:舊后綴=新后綴) → “批量改后綴”
  • 作用:把變量里的文件名批量改后綴(比如 .c 全改成 .o)。
  • 例子:
    已知 SRC = a.c b.c,那么 OBJ = $(SRC:.c=.o) 就會把 a.c 改成 a.ob.c 改成 b.o,所以 OBJ = a.o b.o

6、偽目標 test:調試變量值

.PHONY:test  
test:  @echo "Debug---------"  @echo $(SRC);  @echo "Debug---------"  @echo $(OBJ);  @echo "Debug---------"  
代碼行符號/語法解析實際作用
.PHONY:test聲明 test 是偽目標。標記為“動作”,確保 make test 必執行。
@echo $(SRC);- @:抑制命令回顯;
- $(SRC):輸出 .c 文件列表(如 a.c b.c)。
調試:檢查 SRC 是否正確識別了所有 .c 文件。
@echo $(OBJ);- $(OBJ):輸出 .o 文件列表(如 a.o b.o)。調試:檢查 OBJ 是否正確生成了目標文件列表。

核心符號速記表(簡易)

符號/語法通俗解釋記憶法
$(變量)引用變量(外號)$(BIN) 就是 NJ.exe
wildcard *.c找所有 .c 文件(內置放大鏡)ls *.c 但更安全
$(SRC:.c=.o)批量改后綴(.c→.o).c 全換成 .o
%通配符(任意名字)匹配任意文件名,如 a 匹配 a
$@當前規則的目標(要生成的文件)“目標”的拼音首字母
$^當前規則的所有依賴(需要的文件)“所有”的拼音首字母
$<當前規則的第一個依賴(最關鍵的)“第一個”的拼音首字母
@命令執行命令但不顯示命令本身“安靜模式”
.PHONY:xxx標記xxx是動作(不是文件)“假目標”,只做事不生成文件

7、為什么這樣寫?(設計邏輯)

  1. 自動化
    • 通過 wildcard 和模式規則,自動識別所有 .c 文件,新增文件無需修改 Makefile。
  2. 高效性
    • Make 會對比文件修改時間,只重新編譯修改過的 .c 文件(增量編譯),提升速度。
  3. 可維護性
    • 變量集中定義(如 CCBIN),修改編譯器或文件名只需改變量,無需遍歷命令。

掌握這些后,這份 Makefile 就像一個 “智能編譯管家”:自動找文件、自動編譯、自動鏈接、支持清理和調試,完美適配多文件項目 ?。

六、進階實踐:多目錄與庫編譯

6.1 多目錄項目結構

project/
├── src/      # 源碼目錄(.c 文件)
├── include/  # 頭文件目錄(.h 文件)
├── build/    # 中間文件目錄(.o、.d 等)
└── Makefile  # 主構建文件

6.2 多目錄 Makefile 示例

# 目錄變量
SRC_DIR = src
BUILD_DIR = build
INC_DIR = include# 生成文件路徑
SRC = $(wildcard $(SRC_DIR)/*.c)
OBJ = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC))  # 替換路徑
DEP = $(OBJ:.o=.d)# 編譯選項(添加頭文件路徑)
CFLAGS = -I$(INC_DIR) -Wall -g# 創建構建目錄(若不存在)
$(shell mkdir -p $(BUILD_DIR))# 模式規則:編譯 .c → .o(輸出到 build 目錄)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c  $(CC) $(CFLAGS) -c $< -o $@  $(CC) -MM $(CFLAGS) $< > $(@:.o=.d)  # 生成依賴文件# 終極目標
myproc: $(OBJ)  $(CC) $^ -o $@  # 清理(刪除 build 目錄和可執行文件)
.PHONY: clean  
clean:  $(RM) -r $(BUILD_DIR) myproc  # 包含依賴文件
-include $(DEP)  

6.3 靜態庫與動態庫編譯

# 生成靜態庫(libmylib.a)
libmylib.a: $(OBJ)  ar rcs $@ $^  # 生成動態庫(libmylib.so)
libmylib.so: $(OBJ)  gcc -shared -o $@ $^  # 鏈接庫(示例)
myproc: $(OBJ) libmylib.a  $(CC) $^ -L. -lmylib -o $@  

七、避坑指南:常見錯誤與解決

7.1 語法錯誤:Tab 鍵問題

  • 錯誤:命令行前用了空格(而非 Tab),make 會報錯:Makefile:xx: *** missing separator. Stop.
  • 解決:確保所有命令行以 Tab 開頭(編輯器可設置“將空格轉換為 Tab”)。

7.2 依賴遺漏:頭文件沒聲明

  • 現象:修改頭文件后,make 不重新編譯。
  • 解決:用 gcc -MM 自動生成依賴(見 5.4 節)。

7.3 偽目標未聲明

  • 現象:若存在名為 clean 的文件,make clean 會提示“clean 已是最新”。
  • 解決:必須用 .PHONY: clean 聲明偽目標。

7.4 變量作用域問題

  • 問題A = helloB = $(A) worldA = hiB 會變成 hi world(遞歸展開)。
  • 解決:用 := 定義“簡單展開變量”:A := helloB := $(A) worldA 后續修改不影響 B

八、工具鏈擴展:Make 與 CMake、Autotools

  • Makefile:適合小型、Linux 專屬項目,靈活但語法復雜。
  • CMake:跨平臺(生成 Makefile、Visual Studio 工程等),語法更簡潔,適合大型項目。
  • Autotools:生成可移植的 configure 腳本,適合開源項目(如 GNU 軟件)。

選擇建議

  • 快速迭代的小項目 → 直接寫 Makefile。
  • 跨平臺或復雜項目 → 用 CMake。
  • 開源項目需高度可配置 → 用 Autotools。

結語:掌握 Makefile,解放生產力

Makefile 是 Linux 下自動化構建的“基石”,從單文件到多目錄項目,從簡單規則到復雜依賴,它都能高效應對。學習時,建議:

  1. 從簡到繁:先寫單文件示例,再擴展多文件、多目錄。
  2. 善用工具:用 make -n 預覽命令,make -d 調試依賴。
  3. 擁抱實踐:遇到問題時,通過 touch 修改文件時間、故意寫錯誤規則,觀察 make 的反應。

掌握 Makefile 后,你會發現編譯不再是負擔,而是一種“一鍵啟動”的享受。讓自動化成為你的生產力工具,把精力聚焦在更有價值的代碼邏輯上吧!

(歡迎在評論區分享你的 Makefile 踩坑經歷或優化技巧 😊)

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

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

相關文章

利用DeepSeek將Rust程序的緩沖輸出改寫為C語言實現提高輸出效率

在前面多語言測試中&#xff0c;遇到一個難以置信的問題&#xff0c;rust的輸出到文件比c語言還快&#xff0c;這是不合情理的&#xff0c;通過對兩者輸出語句的比較&#xff0c;發現了不同。 rust程序在輸出到stdout前有這么一句 let mut writer BufWriter::with_capacity(6…

Java Optional 類教程詳解

一、Optional 類核心定位Optional 是 Java 8 引入的函數式容器類&#xff08;java.util.Optional&#xff09;&#xff0c;專為??顯式空值處理??設計。其核心價值在于&#xff1a;消除 60% 以上的傳統 null 檢查代碼通過類型系統強制空值聲明&#xff0c;降低 NPE 風險支持…

Agent X MCP 把想法編譯成現實

多模態GUI智能體協作型AI魔搭社區MCPMCP 硬件

cv快速input

效果<view class"miniWhether-box-lss"><view class"content-inp-text">快遞單號</view><input class"content-inp-input" type"text"v-model"expressInfo.expressNo" placeholder"填寫快遞單號&…

[AI8051U入門第十二步]W5500-Modbus TCP從機

學習目標: 1、了解Modbus Tcp協議 2、學習Modbus Tcp 從機程序驅動 3、使用 Modbus Pull調試一、Modbus TCP介紹? Modbus TCP 是一種基于 TCP/IP 網絡的工業通信協議,是 Modbus 協議家族中的一員,專門為以太網環境設計。它是 Modbus RTU(串行通信)協議的擴展,將 Modbus…

Python編程基礎與實踐:Python循環結構基礎

循環結構 學習目標 通過本課程的學習&#xff0c;學員可以掌握Python中for循環和while循環的基本使用方法&#xff0c;了解如何利用循環結構來重復執行代碼塊&#xff0c;以及如何使用break和continue語句來控制循環的執行流程。 相關知識點 循環結構 學習內容 1 循環結構 1.1 …

趣談設計模式之模板方法模式-老板,你的數字咖啡制作好了,請享用!

模板方法模式 定義了一套算法的骨架&#xff0c;講某些具體的步驟延遲到子類中實現。 主要用于不改變算法結構的情況下重新定義算法的某些步驟&#xff0c;以適應新的需求。 模板方法的角色 抽象類&#xff1a; 作為算法的骨架&#xff0c;該抽象類中包含了算法的核心部分和…

技術棧:基于Java語言的搭子_搭子社交_圈子_圈子社交_搭子小程序_搭子APP平臺

一、市場背景1、社會發展與生活方式轉變城市化進程加快&#xff1a;隨著城市化不斷推進&#xff0c;大量人口涌入城市&#xff0c;人們生活的物理空間距離拉近了&#xff0c;但人際關系卻在一定程度上變得疏離。傳統的基于血緣、地緣建立起的緊密社交關系難以滿足城市生活中的多…

字典在VBA與VB.NET的區別,舉例說明

簡述&#xff1a;在VBA中&#xff0c;字典通常使用Scripting.Dictionary對象&#xff0c;通過CreateObject("Scripting.Dictionary")創建。它需要引用Microsoft Scripting Runtime庫&#xff08;scrrun.dll&#xff09;。VBA字典的方法包括Exists、Add、Remove等&…

2024年網絡安全案例

以下是2024年造成嚴重損失的網絡安全典型案例&#xff0c;涵蓋市政系統、金融交易、區塊鏈平臺、國家級攻擊及全球性IT故障五大領域&#xff0c;按損失規模和技術危害性綜合排序&#xff1a;---一、市政基礎設施攻擊 1. 加拿大漢密爾頓市勒索軟件事件 - 損失&#xff1a;183…

PINN+貝葉斯:深度學習中的魔改新思路

2025深度學習發論文&模型漲點之——PINN貝葉斯PINN通過將物理定律&#xff08;如偏微分方程PDEs&#xff09;嵌入神經網絡的損失函數中&#xff0c;使得模型能夠利用已知的物理規律來指導學習過程&#xff0c;從而在數據有限或噪聲較多的情況下實現更高的準確性。然而&…

零基礎-動手學深度學習-8.3. 語言模型和數據集

很至關重要的一章: 8.3.1. 學習語言模型 8.3.2. 馬爾可夫模型與n元語法 n元語法看的序列長度是固定的&#xff0c; 存儲的序列長是有限且可控的&#xff0c;使用統計方法的時候通常使用這個模型&#xff01;&#xff01;&#xff01;統計方法&#xff01;&#xff01;&#x…

C++ 模板初階

什么是模板&#xff1f; 模板&#xff08;Template&#xff09;是 C 中實現泛型編程的核心工具。它允許我們編寫與具體數據類型無關的代碼&#xff0c;從而實現代碼復用和類型安全。為什么需要模板&#xff1f; 舉個生活中的例子&#xff1a;如果你要造一個能裝水的杯子&#x…

DockerFile文件執行docker bulid自動構建鏡像

文章目錄一、Dockerfile介紹二、Dockerfile鏡像制作和流程使用三、Dockerfile文件的制作鏡像的分層結構四、Dockerfile文件格式五、Dockerfile相關指令5.1 FROML&#xff1a;指定基礎鏡像5.2 LABEL&#xff1a;指定鏡像元數據5.3 RUN&#xff1a;執行shell指令5.4 ENV&#xff…

osloader!DoGlobalInitialization函數分析之HW_CURSOR--NTLDR源代碼分析之設置光標

第一部分&#xff1a; VOID DoGlobalInitialization(IN PBOOT_CONTEXT BootContextRecord){//// Turn the cursor off//HW_CURSOR(0,127);D:\srv03rtm\base\boot/inc/bldrx86.h:258:#define HW_CURSOR (*ExternalServicesTable->HardwareCursor)第二部分&#xff…

Elasticsearch 索引及節點級別增刪改查技術

以下是針對 Elasticsearch 索引及節點級別增刪改查技術做的簡短總結&#xff1a; 一、索引操作創建索引 功能&#xff1a;指定分片、副本數及映射規則[2][4]。示例&#xff1a;PUT /<index_name>?&#xff0c;可定義 settings&#xff08;如分片數&#xff09;和 mappin…

烽火HG680-KD_海思MV320處理器-安卓9-原廠系統升級包-針對解決燒錄不進系統的問題

烽火HG680-KD_海思MV320處理器-安卓9-原廠系統升級包&#xff08;注意是&#xff08;原機系統&#xff09;&#xff09;-主要是針對解決TTL燒錄后仍然不進系統使用。HG680-KD&#xff0f;HG680-KE&#xff0f;HG680-KF&#xff0f;HG680-KX 均通用。 說明&#xff1a; 前一個…

VS2019安裝HoloLens 沒有設備選項

第一步先檢查VS有沒有安裝C組件第二步把VS工程最后一個設置為啟動項

【云計算】云主機的親和性策略(二):集群節點組

《云主機的親和性策略》系列&#xff0c;共包含以下文章&#xff1a; 1?? 云主機的親和性策略&#xff08;一&#xff09;&#xff1a;快樂旅行團2?? 云主機的親和性策略&#xff08;二&#xff09;&#xff1a;集群節點組3?? 云主機的親和性策略&#xff08;三&#xf…

【人工智能】AI代理在零售業的崛起:從草莓訂購到全流程購物體驗

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 在零售業快速演變的格局中,AI代理正作為變革力量崛起,連接消費者需求與無縫履行。本文深入探討AI代理在零售中的興起,從通過對話界面訂購…