Makefile 入门教程

makefile,入门教程 · 浏览次数 : 64

小编点评

**Makefile 示例** ```makefile # 基础目标 all: myprogram # 依赖项 SOURCES = main.c utils.c # 命令 CC = gcc CFLAGS = -Wall # 条件语句 ifeq ($(DEBUG), 1) CFLAGS = -g endif # 自动化依赖关系生成 $(DEPS) = $(SOURCES:.c=.d)%.d: %.c $(CC) -M $< -o $@-include $(DEPS) # 多目录项目 SUBDIRS = dir1 dir2all: $(SUBDIRS): $(MAKE) -C $@clean: for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done # 高级变量操作 STR1 = hello STR2 = world STR3 = $(STR1) $(STR2) VAR1 = $(VAR2)VAR2 = value ``` **使用说明** 1. 将该 Makefile 保存为 `Makefile` 文件。 2. 在命令行中运行 `make` 命令,将构建项目。 **注意** * `all` 目标用于构建整个项目。 * `SOURCES` 定义了项目中的源文件。 * `CC` 和 `CFLAGS` 定义了编译器和编译选项。 * `ifeq` 条件语句用于根据条件执行不同的规则。 * `$(wildcard)` 函数用于匹配文件名模式。 * `foreach` 函数用于对列表中的每个元素执行操作。 * `strip` 和 `subst` 函数用于处理字符串。 * `filter` 函数用于筛选字符串。

正文

Makefile 是一个非常强大的构建自动化工具,用于管理项目的编译、链接和其他构建任务。以下是一个详细的 Makefile 使用文档,包括基本概念、语法、示例和常见任务。

1. 基本概念

  • 目标 (Targets):在 Makefile 中,目标是要生成的文件或执行的操作的名称。目标可以是文件名,也可以是伪目标,用于执行特定任务而不生成文件。
  • 依赖项 (Dependencies):依赖项是与目标相关联的文件或其他目标,它们在目标生成之前必须存在或已经生成。
  • 规则 (Rules):规则定义了如何生成目标以及生成目标所需的命令。
  • 命令 (Commands):命令是在生成目标时要执行的操作。命令必须以 Tab 键开头。
  • 变量 (Variables):变量用于存储文本或命令,并可以在整个 Makefile 中重复使用。
  • 伪目标 (Phony Targets):伪目标是不代表实际文件的目标,而是用于执行特定操作的标记。

2. Makefile 语法

一个基本的 Makefile 规则的语法如下:

target: dependencies
    command
  • target:要生成的目标的名称。
  • dependencies:生成目标所需的文件或其他目标的列表。
  • command:生成目标的命令,必须以 Tab 键开头。

3. 示例 Makefile

以下是一个简单的示例 Makefile,用于编译一个 C 程序:

CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c

$(TARGET): $(SOURCES)
    $(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)

clean:
    rm -f $(TARGET)

这个 Makefile 使用了变量 CCCFLAGSTARGETSOURCES,并定义了一个 all 目标用于编译程序,以及一个 clean 目标用于清理生成的文件。

4. 常见任务

4.1 编译项目

all: $(TARGET)

$(TARGET): $(SOURCES)
    $(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)

4.2 清理生成的文件

clean:
    rm -f $(TARGET)

4.3 使用变量

CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c

$(TARGET): $(SOURCES)
    $(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)

4.4 伪目标

.PHONY: clean

clean:
    rm -f $(TARGET)

5. 高级用法

除了基本用法外,还支持一些高级用法,可以用来处理更复杂的构建需求。以下是一些高级用法的详细介绍:

5.1 条件语句和函数

条件语句

Makefile 支持条件语句,可以根据条件来执行不同的规则或命令。通常使用 ifeqifdef 这两个条件语句。

ifeq ($(VARIABLE), value)
    # 条件为真时的规则和命令
else
    # 条件为假时的规则和命令
endif

例如,可以根据是否定义了 DEBUG 变量来设置不同的编译选项:

ifeq ($(DEBUG), 1)
    CFLAGS = -g
else
    CFLAGS = -O2
endif
函数

Makefile 还提供了一些内置函数,用于处理文本和文件列表。以下是一些常见的函数:

  • $(shell command):执行 shell 命令并返回结果。
  • $(wildcard pattern):匹配文件名模式并返回符合条件的文件列表。
  • $(foreach var, list, text):对列表中的每个元素执行指定的操作。
  • $(strip string):删除字符串开头和结尾的空白字符。
  • $(subst find,replace,text):替换文本中的字符串。
  • $(filter pattern, text):从文本中筛选出匹配指定模式的字符串。
  • $(patsubst pattern,replacement,text):用指定字符串替换文本中的模式。
  • $(notdir names):从文件路径中提取文件名。

这些函数可以在 Makefile 中用于各种目的,例如文件操作、文本处理和条件判断。

5.2 自动化依赖关系生成

通常,Makefile 中的依赖关系需要手动维护。但是,对于 C/C++ 项目,您可以使用编译器提供的 -M 选项来自动生成依赖关系。例如:

SOURCES = main.c utils.c
DEPS = $(SOURCES:.c=.d)

%.d: %.c
    $(CC) -M $< -o $@

-include $(DEPS)

在这个示例中,%.d: %.c 规则用于自动生成 .d 文件,其中包含了 .c 文件的依赖关系。然后使用 -include 指令来包含这些 .d 文件,以自动跟踪依赖关系。

5.3 多目录项目

对于大型项目,通常需要将 Makefile 拆分成多个子目录,每个子目录都有自己的 Makefile。然后,可以使用递归或变量传递来管理这些子目录之间的依赖关系。例如:

SUBDIRS = dir1 dir2

all: $(SUBDIRS)

$(SUBDIRS):
    $(MAKE) -C $@

clean:
    for dir in $(SUBDIRS); do \
        $(MAKE) -C $$dir clean; \
    done

在这个示例中,SUBDIRS 变量包含了子目录的列表。$(MAKE) 是一个 Makefile 中的特殊变量,用于启动另一个 Makefile。

5.4 高级变量操作

Makefile 支持高级的变量操作,包括字符串操作、条件赋值、变量展开等。以下是一些示例:

字符串操作
STR1 = hello
STR2 = world
STR3 = $(STR1) $(STR2)

在这个示例中,STR3 的值将是 "hello world"

条件赋值
FOO ?= default_value

如果 FOO 变量未定义,则将其赋值为 default_value

变量展开
VAR1 = $(VAR2)
VAR2 = value

在这个示例中,VAR1 的值将是 value,因为 Make 会递归地展开变量。


孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意


与Makefile 入门教程相似的内容:

Makefile 入门教程

Makefile 是一个非常强大的构建自动化工具,用于管理项目的编译、链接和其他构建任务。以下是一个详细的 Makefile 使用文档,包括基本概念、语法、示例和常见任务。 1. 基本概念 目标 (Targets):在 Makefile 中,目标是要生成的文件或执行的操作的名称。目标可以是文件名,也

make学习

make学习,参考「Makefile 20分钟入门,简简单单,展示如何使用Makefile管理和编译C++代码」 程序见:https://github.com/ShiqiYu/CPP/tree/main/week03/examples/lab 文件结构 make语法 g++ #「只编译不链接」编译.

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)

makefile与gcc常用操作 一、温故知新1、可执行程序的生成过程2、gcc的常用操作 二、make操作三、编写Makefile文件时常用操作注意:在Makefile文件中 空格和缩进是完全不同的,不可以相互转换。1、框架格式2、举例3、优化1). 伪目标 .PHONY2). $ 和 @ 符号的

[转帖]Linux 内核的 Makefile

https://www.cnblogs.com/chenyuting/p/10773313.html Linux内核的配置系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1、Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则; 2、

[转帖]--build=arm-linux

今天在arm上用configure生成makefile时报错:configure: error: cannot guess build type; you must specify one 问题: 不能确定编译的操作系统 解决: 在gcc编译中我们使用 ./configure --build=编译平

[转帖]BPF的可移植性和CO-RE (Compile Once – Run Everywhere)

https://www.cnblogs.com/charlieroro/p/14206214.html 在上一篇文章中介绍了提高socket性能的几个socket选项,其中给出了几个源于内核源码树中的例子,如果选择使用内核树中的Makefile进行编译的话,可能会出现与本地头文件冲突的情况,如重复定