百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

如何在 Linux 中使用 make 和 makefile?

ahcoder 2025-06-24 11:11 3 浏览

make 是一个自动化构建工具,用于根据源代码生成可执行文件或其他目标文件。它通过读取 Makefile 文件(或 makefile)中的指令,决定哪些文件需要重新编译,以及如何执行编译、链接等操作。Makefile 是一个文本文件,包含了构建项目的规则、依赖关系和命令。

为什么使用make?

  1. 自动化:自动处理文件依赖关系,仅重新编译发生变化的文件。
  2. 高效:通过并行执行任务(-j 选项)加速构建过程。
  3. 灵活:支持多种编程语言和复杂项目结构。
  4. 跨平台:在Linux、Unix及类似系统中广泛使用。

安装make

在大多数Linux发行版中,make 默认已安装。如果没有,可以通过包管理器安装。例如:

  • Ubuntu/Debian
sudo apt update
sudo apt install make
  • CentOS/RHEL
sudo yum install make
  • Arch Linux
sudo pacman -S make

安装完成后,运行以下命令检查版本:

make --version

Makefile的基本结构

Makefile 由规则组成,每条规则通常包含以下三个部分:

  1. 目标(Target):要生成的文件,如可执行文件或中间文件。
  2. 依赖(Prerequisites):目标文件依赖的其他文件。
  3. 命令(Commands):生成目标所需的shell命令。

基本语法如下:

target: prerequisites
    command
    command
  • 目标和依赖之间用冒号 : 分隔。
  • 命令必须以 Tab 键(而非空格)缩进,否则会报错。
  • 每行命令都在独立的shell中执行。

示例:简单的C程序编译

假设你有以下文件:

  • main.c:主程序
  • math.c:实现数学运算的函数
  • math.h:头文件

创建一个简单的 Makefile

# 简单的Makefile示例
all: program

program: main.o math.o
    gcc -o program main.o math.o

main.o: main.c math.h
    gcc -c main.c

math.o: math.c math.h
    gcc -c math.c

clean:
    rm -f *.o program

运行 make 命令,make 会根据依赖关系编译文件:

make

运行 make clean 删除生成的文件:

make clean

解释:

  • all 是默认目标,运行 make 时会优先执行。
  • program 依赖于 main.omath.o,由 gcc -o 链接生成。
  • main.omath.o 分别依赖源文件和头文件,使用 gcc -c 编译。
  • clean 是一个伪目标(没有实际文件),用于清理。

Makefile的进阶用法

1. 变量

变量可以简化 Makefile 的维护。例如:

CC = gcc
CFLAGS = -Wall -g
OBJECTS = main.o math.o

all: program

program: $(OBJECTS)
    $(CC) -o program $(OBJECTS)

main.o: main.c math.h
    $(CC) $(CFLAGS) -c main.c

math.o: math.c math.h
    $(CC) $(CFLAGS) -c math.c

clean:
    rm -f $(OBJECTS) program
  • CC 定义编译器。
  • CFLAGS 定义编译选项。
  • OBJECTS 定义目标文件列表。
  • 使用 $(variable) 引用变量。

2. 自动变量

make 提供了一些自动变量,简化规则编写:

  • $@:目标文件名。
  • lt;:第一个依赖文件名。
  • $^:所有依赖文件列表。

重写上述 Makefile

CC = gcc
CFLAGS = -Wall -g
OBJECTS = main.o math.o

all: program

program: $(OBJECTS)
    $(CC) -o $@ $^

main.o: main.c math.h
    $(CC) $(CFLAGS) -c lt;

math.o: math.c math.h
    $(CC) $(CFLAGS) -c lt;

clean:
    rm -f $(OBJECTS) program

3. 模式规则

对于大量类似规则,可以使用模式规则。例如:

%.o: %.c
    $(CC) $(CFLAGS) -c lt; -o $@

这表示所有 .o 文件由对应的 .c 文件编译生成。

4. 伪目标

伪目标(如 clean)不对应实际文件,使用 .PHONY 声明:

.PHONY: clean
clean:
    rm -f *.o program

5. 条件语句

Makefile 支持条件判断。例如:

ifdef DEBUG
CFLAGS += -g -DDEBUG
else
CFLAGS += -O2
endif

运行 make DEBUG=1 启用调试模式。

6. 包含其他Makefile

使用 include 指令包含其他 Makefile

include common.mk

常用make命令

以下是 make 的常用选项:

  • make -f file:指定 Makefile 文件名。
  • make -jN:并行执行N个任务(例如 make -j4)。
  • make -n:模拟执行,显示将运行的命令而不实际执行。
  • make -s:静默模式,不显示命令。
  • make -C dir:切换到指定目录执行 make
  • make -k:遇到错误继续执行其他目标。
  • make -d:调试模式,显示依赖检查过程。

示例:

make -j4  # 并行编译,加速构建
make -n   # 查看将执行的命令
make clean -s  # 静默清理

调试Makefile

调试 Makefile 时,可能遇到以下问题:

  1. Tab缩进错误:确保命令以Tab缩进。
  2. 依赖缺失:检查依赖文件是否正确。
  3. 变量未定义:使用 $(info $(variable)) 打印变量值。

示例调试变量:

$(info CFLAGS = $(CFLAGS))

运行 make -d 查看详细的依赖解析过程。

实际案例:构建复杂项目

假设你有一个包含多个子目录的项目:

project/
├── src/
│   ├── main.c
│   ├── util/
│   │   ├── util.c
│   │   ├── util.h
├── include/
│   ├── config.h
├── Makefile

Makefile 示例:

CC = gcc
CFLAGS = -Wall -Iinclude
SRC_DIR = src
OBJ_DIR = obj
SOURCES = $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/util/*.c)
OBJECTS = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SOURCES))
TARGET = program

all: $(TARGET)

$(TARGET): $(OBJECTS)
    $(CC) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
    @mkdir -p $(@D)
    $(CC) $(CFLAGS) -c lt; -o $@

clean:
    rm -rf $(OBJ_DIR) $(TARGET)

.PHONY: clean

解释:

  • wildcard:查找所有 .c 文件。
  • patsubst:将源文件路径转换为目标文件路径。
  • @mkdir -p $(@D):确保目标目录存在。
  • -Iinclude:指定头文件路径。

运行:

make
./program
make clean

与CMake结合

对于大型项目,CMake 常用于生成 Makefile。示例 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_executable(program src/main.c src/util/util.c)
target_include_directories(program PRIVATE include)

生成 Makefile

cmake -B build
cd build
make

相关推荐

卡巴斯基实验室成功将Linux系统的驱动程序移植到“KasperskyOS”

据os.kaspersky.com网站8月8日报道,俄罗斯卡巴斯基实验室启动了一个研究项目,将Linux驱动程序移植到卡巴斯基公司自主研发的操作系统KasperskyOS——这是该实验室创建的“安全...

服务器程序从 Windows 系统移植到 Linux/x86_64 平台时总是崩溃?

清华大学出版社的《高效C/C++调试》一书给出了回答:我们的服务器程序最初是为Windows系统开发的,第一次将它移植到Linux/x86_64平台时,它在回归测试中十次会崩溃八次,且仅在...

Linux系统的移植和裁剪(linux移植lvgl)

本节将嵌入式Linux系统按需求裁剪后移植到ARM处理器中。通过对Linux系统的了解和认识,我们在这里选择Linux4.1.15版本,该版本支持64位处理器,相对于前面几代Linux版本有了更大的提...

搭建RISC-V模拟环境(搭建虚拟环境)

现在RISC-V在主流操作系统上基本都能模拟了,不过我还是觉得Linux下好用。之前在Mac上想用Linux,基本就是在VirtualBox上创建一个虚拟机,从网上下一个Ubuntu的安装iso,安...

CPU虚拟化:陷入和模拟(cpu虚拟模式是什么)

导读:本文摘自于王柏生、谢广军撰写的《深度探索Linux系统虚拟化:原理与实现》一书,重点讨论了虚拟CPU在Guest模式下运行时,由于运行敏感指令而触发虚拟机退出的典型情况。作者:王柏生、谢广军来源...

《模拟山羊》恶搞僵尸主题DLC公布 《DayZ》躺枪!

近日,开发商CoffeeStain为我们带来了一个好消息,那就是奇葩游戏《模拟山羊(GoatSIMulator)》僵尸主题DLC“GoatZ”将于5月7日登陆PC,Mac,Linux,iOS和安卓...

「精品课程」模拟IC设计进阶(模拟ic设计师怎么样)

课程导语模拟集成电路设计最重要的是基础理论知识,基础理论的重要性很多人一开始并没有意识到,工作一段时间,做过几个项目以后就会深有感触。除此之外就是个人的学习能力和分析问题、解决问题的能力,其实这些能力...

跨平台神器:在Linux上轻松运行Windows软件的方法大揭秘!

Wine始于30年前的一个业余爱好项目,当时Windows3.1及其16位API出现了。在一个简单的“HelloWorld”程序之后,它很快就成功地让Solitaire运行起来。...

LAMMPS 模拟教程全新发布,助力科研入门分子模拟世界

https://arxiv.org/html/2503.14020v1本研究发布了8个层层递进的LAMMPS模拟教学教程,并配套开发了专属图形界面LAMMPS–GUI,显著降低了分子模拟的入门门槛。...

Linux趣味命令,每一个都能产生炫酷效果(示例)

Linux趣味命令,每一个都能产生炫酷的效果:cmatrix:模拟《黑客帝国》中的字符矩阵效果。bashCopycodecmatrixfortune:随机显示一句有趣的引语或笑话。bashCopy...

「免费!免费!Chris老师经典模拟课程」CMOS模拟电路设计流程

创芯大讲堂为广大学员发福利各位创芯大讲堂的同学们,即日起,凡当月购买大讲堂课程达到300元的同学可以享受创芯大讲堂全场课程8折优惠,凡当月购买创芯大讲堂课程达到500元的同学可以享受创芯大讲堂全场课程...

Gromacs基本模拟流程(gromacs运行命令)

GROMACS是一个使用经典分子动力学理论研究蛋白质动力学的高端的高效的工具。GROMACS是遵守GNU许可的免费软件,可以从以下站点下载:http://www.gromacs.org,并且可以在l...

国外友人开创Python模拟登陆神库,完美修改它为咱们所用

Awesome-python-login-model是一个国人开发的模拟登陆仓库,在这个仓库上有20几个网站的模拟登陆脚本,你可以基于这个仓库实现的代码做简易的修改,以实现自己的自动化功能。仓库地址...

并发模拟的四种方式+工具,超级实用

原文链接:https://mp.weixin.qq.com/s/jJDJ8YwmzkKS9KvfMamLWA一、PostmanPostman是一个款http请求模拟工具首先演示一下postman最基本...

精选模拟IC设计仿真课程(精选模拟ic设计仿真课程怎么样)

课程介绍本系列课程采用屏幕录制视频及操作解说的形式,注重于模拟芯片设计流程中的电路原理图设计、仿真及优化方法、版图设计、寄生参数提取及后仿真优化等的实际操作,在电路设计过程中学习模拟IC设计和验证方法...