linux makefile教程怎么用?makefile教程视频

Linux Makefile 完整教程

目录

  1. 什么是 Make 和 Makefile
  2. 基本语法
  3. 变量
  4. 模式规则
  5. 自动变量
  6. 函数
  7. 条件判断
  8. 实战示例
  9. 最佳实践

什么是 Make 和 Makefile

Make 是一个自动化构建工具,Makefile 是它的配置文件。

  • 核心思想:只重新编译发生变化的源文件,提高构建效率
  • 应用场景:C/C++ 项目编译、大型工程构建、自动化部署等

基本工作流程

Makefile → make 命令 → 检查依赖关系 → 只编译有变化的文件

基本语法

1 基本结构

# 目标: 依赖
# <Tab> 命令(注意:必须用 Tab,不能用空格!)
target: dependency1 dependency2
    <command1>
    <command2>

2 第一个 Makefile 示例

# 编译 main.c 生成 main 可执行文件
main: main.o utils.o
    gcc -o main main.o utils.o
main.o: main.c
    gcc -c main.c
utils.o: utils.c
    gcc -c utils.c
# 清理生成的文件
clean:
    rm -f .o main

运行:

20分钟Makefile光速入门教程
加载中
20分钟Makefile光速入门教程
make          # 构建
make clean    # 清理

3 伪目标

.PHONY: clean all install
clean:
    rm -f .o main
all: main

.PHONY 声明伪目标,避免与同名文件冲突。


变量

1 变量定义

# 简单赋值(立即求值)
CC = gcc
CFLAGS = -Wall -g
# 递归赋值(延迟求值)
CC ?= gcc        # 如果未定义则赋值
CC := gcc        # 简单赋值,立即展开
CC += -std=c11   # 追加赋值
# 条件赋值
override CC = clang   # 覆盖命令行传入的值

2 常用内置变量

CC       # C 编译器
CXX      # C++ 编译器
CFLAGS   # C 编译选项
CXXFLAGS # C++ 编译选项
LDFLAGS  # 链接选项
LDLIBS   # 链接库
AR       # 归档工具
RM       # 删除命令

3 使用变量

CC = gcc
CFLAGS = -Wall -O2
TARGET = myapp
SRCS = main.c utils.c helper.c
OBJS = $(SRCS:.c=.o)
$(TARGET): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $^
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
clean:
    rm -f $(OBJS) $(TARGET)

linux makefile教程怎么用?makefile教程视频

= 目标名,$^ = 所有依赖,$< = 第一个依赖


模式规则

1 通配符规则

# %.o: %.c 表示所有 .o 文件依赖于同名的 .c 文件
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

2 多模式规则

# 同时匹配 .c 和 .cpp
%.o: %.c %.cpp
    $(CC) $(CFLAGS) -c $< -o $@

3 静态模式规则

OBJS = main.o utils.o helper.o
$(OBJS): %.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

自动变量

变量 含义
目标文件名
$< 第一个依赖文件名
$^ 所有依赖文件名(去重)
所有依赖文件名(不去重)
目标中 匹配的部分
比目标更新的依赖文件列表
所有先决条件(包括 order-only)

示例

main.o: main.c main.h
    gcc -c $< -o $@    # 等价于 gcc -c main.c -o main.o
# 使用 $? 只编译更新的依赖
main: main.o utils.o
    gcc -o $@ $?       # 只链接更新的依赖

函数

1 常用函数

# wildcard: 获取匹配文件
SRCS = $(wildcard .c)
# patsubst: 模式替换
OBJS = $(patsubst %.c,%.o,$(SRCS))
# notdir: 去除路径
DIRS = $(notdir $(SRCS))
# addprefix: 添加前缀
PATHS = $(addprefix src/,$(SRCS))
# realpath: 获取绝对路径
REAL_PATHS = $(realpath $(DIRS))
# foreach: 循环
# $(foreach var,list,text)
OBJS = $(foreach src,$(SRCS),$(src:.c=.o))
# if: 条件判断
# $(if condition,true-part[,false-part])
RESULT = $(if $(CC),using gcc,using clang)
# warning/error: 输出警告/错误
$(warning This is a warning)
$(error This is an error)
# shell: 执行 shell 命令
DATE = $(shell date +%Y%m%d)

2 函数示例

# 获取所有 C 源文件
SRCS = $(wildcard src/.c)
# 转换为对象文件
OBJS = $(patsubst src/%.c,build/%.o,$(SRCS))
# 创建目录
build/%.o: src/%.c | build
    @mkdir -p $(@D)
    $(CC) $(CFLAGS) -c $< -o $@
build:
    mkdir -p build
clean:
    rm -rf build

条件判断

1 ifeq / ifneq

ifeq ($(CC),gcc)
    CFLAGS += -O3
else ifeq ($(CC),clang)
    CFLAGS += -O3 -Qunused-arguments
else
    CFLAGS += -O2
endif

2 ifdef / ifndef

linux makefile教程怎么用?makefile教程视频

ifdef DEBUG CFLAGS += -g -DDEBUG else CFLAGS += -O2 endif ifndef VERBOSE QUIET := @ endif

3 结合变量使用

ifeq ($(OS),Linux)
    LDFLAGS += -lpthread
else ifeq ($(OS),Darwin)
    LDFLAGS += -lpthread
endif

实战示例

1 简单 C 项目

# ==================== 配置区 ====================
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -g
LDFLAGS =
LDLIBS = -lm
TARGET = myapp
SRCDIR = src
OBJDIR = build
BINDIR = bin
SRCS = $(wildcard $(SRCDIR)/.c)
OBJS = $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS))
# ==================== 规则区 ====================
.PHONY: all clean install uninstall
all: $(TARGET)
$(TARGET): $(OBJS) | $(BINDIR)
    $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
    $(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR):
    mkdir -p $(OBJDIR)
$(BINDIR):
    mkdir -p $(BINDIR)
clean:
    rm -rf $(OBJDIR) $(BINDIR) $(TARGET)
install: $(TARGET)
    cp $(TARGET) $(BINDIR)/
uninstall:
    rm -f $(BINDIR)/$(TARGET)

2 C++ 项目

# ==================== 配置区 ====================
CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++17 -O2
LDFLAGS =
LDLIBS = -lpthread -lstdc++fs
TARGET = mycppapp
SRCDIR = src
OBJDIR = build
# 自动收集所有 .cpp 文件
SRCS = $(wildcard $(SRCDIR)/.cpp)
OBJS = $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRCS))
# 自动收集头文件依赖
DEPS = $(OBJS:.o=.d)
# ==================== 规则区 ====================
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
    $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    @mkdir -p $(@D)
    $(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@
# 包含自动生成的依赖文件
-include $(DEPS)
clean:
    rm -rf $(OBJDIR) $(TARGET)

-MMD -MP 自动生成 .d 依赖文件,当修改头文件时会自动重新编译相关源文件。

3 多目标项目

# 构建多个可执行文件
TARGETS = app1 app2 app3
.PHONY: all clean
all: $(TARGETS)
app1: app1.o lib.o
    $(CC) -o $@ $^
app2: app2.o lib.o
    $(CC) -o $@ $^
app3: app3.o lib.o
    $(CC) -o $@ $^
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
clean:
    rm -f $(TARGETS) .o

4 带测试的项目

CC = gcc
CFLAGS = -Wall -g
LDFLAGS =
LDLIBS = -lcheck -lm -lpthread
TARGET = mylib
TEST_TARGET = test_mylib
.PHONY: all clean test
all: $(TARGET) $(TEST_TARGET)
# 编译库
$(TARGET): main.o utils.o
    $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
# 编译测试
$(TEST_TARGET): test_main.o main.o utils.o
    $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
test: $(TEST_TARGET)
    ./$(TEST_TARGET)
clean:
    rm -f $(TARGET) $(TEST_TARGET) .o

linux makefile教程怎么用?makefile教程视频


最佳实践

1 通用模板

# 1. 始终使用 .PHONY 声明伪目标
.PHONY: all clean install uninstall test
# 2. 使用变量而非硬编码
CC ?= gcc
CFLAGS ?= -Wall -Wextra
CXX ?= g++
CXXFLAGS ?= -Wall -Wextra
# 3. 使用自动变量
# 4. 使用模式规则减少重复
# 5. 提供 clean 目标
# 6. 使用 -include 包含依赖文件
# 7. 使用 @ 前缀抑制命令回显(可选)
# 8. 使用 - 前缀忽略错误(可选)
# 示例:安静模式
quiet_cmd = @echo "  CC      $<"
quiet_cmd = @$(CC) $(CFLAGS) -c $< -o $@

2 常见陷阱

# ❌ 错误:使用空格而不是 Tab
target: dep
    command    # 空格!会报错
# ✅ 正确:使用 Tab
target: dep
    command    # Tab
# ❌ 错误:变量名大小写敏感
CC = gcc
$(cc) ...    # cc 未定义!
# ✅ 正确
$(CC) ...
# ❌ 错误:忘记 .PHONY
clean:
    rm -f .o
# 如果当前目录有名为 clean 的文件,make 不会执行
# ✅ 正确
.PHONY: clean
clean:
    rm -f .o

3 调试技巧

# 显示执行的命令
make -n          # 预览命令(dry run)
make -d          # 详细调试信息
make VERBOSE=1   # 自定义 verbose 模式
# 在 Makefile 中调试
$(info CC is $(CC))
$(warning CFLAGS is $(CFLAGS))
$(error Stop here)

快速参考卡片

基本结构:  target: dependencies
                <tab> command
变量:       VAR = value
            $(VAR) 或 ${VAR}
自动变量:   $@ 目标  $< 第一个依赖  $^ 所有依赖
函数:       $(wildcard .c)
            $(patsubst %.c,%.o,$(SRCS))
条件:       ifeq / ifneq / ifdef / ifndef
伪目标:     .PHONY: clean all

概念 要点
核心 依赖关系 + 增量编译
语法 目标: 依赖 → Tab 命令
变量 用 $(VAR) 引用,善用自动变量
模式规则 %.o: %.c 减少重复
函数 wildcard, patsubst, foreach 等
最佳实践 使用 .PHONY、变量抽象、自动依赖

Makefile 是 Linux 开发中不可或缺的工具,掌握它能极大提升构建效率,建议从简单项目开始,逐步掌握高级特性。

首发原创文章,作者:王坚‌,如若转载,请注明出处:https://idctop.com/article/483362.html

赞 (0)
费用中心合并是什么意思?企业财务软件费用中心合并怎么操作
上一篇 2026年7月11日 21:19
Linux课程论文怎么写?Linux系统安装配置教程
下一篇 2026年7月11日 21:22

相关推荐

  • 华硕装linux系统难吗?华硕电脑怎么安装linux系统

    在华硕笔记本上安装Linux不仅完全可行,且通过正确配置驱动和BIOS设置,能获得比Windows更流畅的性能体验,特别适合开发者、极客及注重隐私的用户群体,很多用户听到“装系统”就头大,担心华硕特有的硬件兼容性,或者害怕把电脑变砖,只要掌握核心逻辑,这就像给汽车换轮胎一样,是有章可循的标准化流程,华硕作为全球……

    2026年7月6日
    22300
  • 多ip香港服务器一个月多少钱才划算,怎么选?

    多IP香港服务器月租价格通常在200元至2000元之间,具体取决于IP数量、带宽配置及服务商,多数中小企业选择500-1000元区间即可满足日常需求,多IP香港服务器多少钱一个月?价格区间详解多IP香港服务器的价格并非固定值,而是根据IP数量、带宽大小、硬件配置等因素浮动,以下按常见使用场景划分三个价位段,帮你……

    2026年7月25日
    300
  • 云服务器10t内存一年费用多少,哪家便宜

    对于云服务器10TB内存的年度费用,目前市场上主流方案的年费普遍在数十万元至上百万元区间,具体取决于CPU配置、带宽大小以及机房级别,选择持牌自营的服务商能在同样预算下获得更稳定的性能,10TB内存云服务器到底是什么很多人看到“10TB内存”第一反应是“这得装多少东西”,但这里需要先厘清概念,10TB指的是内存……

    2026年7月29日
    900
  • linux键盘无响应怎么办?linux键盘失灵快速修复

    在 Linux 系统中,“键盘响应”通常涉及从硬件信号到用户界面显示的整个链路,如果你遇到键盘响应慢、无响应、按键延迟或映射错误等问题,可以从以下几个层面进行排查和优化:检查基础硬件与连接有线键盘:尝试更换 USB 端口(优先使用 USB 2.0 端口,有时比 3.0 更稳定),检查线缆是否损坏,无线键盘:更换……

    2026年7月11日
    16800
  • 服务器一般功耗要花多少钱?服务器功率怎么算

    一台标准机架式服务器(按常见400W功率、7×24小时运行)每年的电费大约在1700元到2600元区间,具体取决于你所在地区的电价和实际负载,如果折算到每月,多数场景下是150元到220元,你家或者公司的服务器,一年到底要交多少电费?很多朋友第一次托管服务器或者自建机房,最容易被吓一跳的往往不是硬件采购成本,而……

    2026年9月18日
    000
  • 1m服务器能支持多少人同时使用,服务器带宽多少够用?

    对于一台带宽只有1Mbps的服务器来说,它能支撑的在线人数通常在几十人到几百人之间,具体数字取决于你的业务类型、网站架构以及单次请求消耗的流量大小,如果你做的是纯文字博客,撑起200人同时在线没有太大问题;但若是图片站或视频站,可能连10个人都扛不住,要计算1M服务器的承载力,核心公式只有一条:带宽(1Mbps……

    2026年8月20日
    500
  • 10g高仿服务器真实价格是多少?,哪家更靠谱?

    一台10G高仿服务器(通常指高防服务器)的月租成本根据不同配置和防御方案,大致在300元至1500元之间,具体取决于硬件性能、防御能力以及带宽资源,这个价格区间覆盖了从入门级到企业级的多种选择,但实际成交价会因服务商资质、机房线路和附加服务有所浮动,下面拆解每个环节的具体影响,10G高仿服务器的价格构成要理解为……

    相关资讯 2026年8月9日
    400
  • Linux Vino远程桌面怎么设置?,如何安装?

    Linux内置的Vino远程桌面工具,是GNOME用户实现轻量级VNC远程控制的捷径,但默认配置仅限局域网,且性能与安全性需手动调优才能适应日常远程办公场景,为什么Linux用户选择Vino?Vino作为GNOME桌面环境的标准组件,在Ubuntu、Fedora等发行版中预装,它的最大卖点是“开箱即用”:在“设……

    2026年7月16日
    2400
  • 北京宽带通DNS服务器地址是多少,怎么设置?

    为什么北京宽带通的DNS首选是202.106.0.20北京宽带通本身是二级运营商,骨干网络走的是北京联通的出口,联通的DNS服务器地址长期稳定,北京地区默认分配的就是106.0.20和106.148.1这两个,用它们解析域名,延迟低,缓存命中率高,尤其在访问外省或国外网站时,不容易出现解析超时的情况,有些朋友会……

    2026年9月16日
    000
  • 服务器坏了换一个要多少钱,维修价格贵不贵?

    服务器坏了换一台多少钱,答案很直接:市面上常见的机架式服务器更换成本一般在5000元到5万元之间,具体取决于配置、品牌和采购渠道,但维修与更换的决策,远比单看报价更复杂,很多朋友一听到“服务器坏了”就头皮发麻,脑子里瞬间闪过两个念头:这得花多少钱?数据还能不能保住?别急,这篇文章不绕弯子,结合我们这么多年在ID……

    2026年9月17日
    100

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注