首页 > 其他分享 >Makefile 入门教程

Makefile 入门教程

时间:2023-10-10 09:35:04浏览次数:403  
标签:TARGET 入门教程 Makefile 生成 SOURCES 目标 变量

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: 恋水无意


标签:TARGET,入门教程,Makefile,生成,SOURCES,目标,变量
From: https://www.cnblogs.com/lianshuiwuyi/p/17753755.html

相关文章

  • PyQT5 PyQT入门教程(之三)
    REFhttp://code.py40.com/pyqt5/22.html 事件Event所有的GUI程序都是事件驱动的。事件主要由用户触发,但也可能有其他触发方式:例如网络连接、windowmanager或定时器。当我们调用QApplication的exec_()方法时会使程序进入主循环。主循环会获取并分发事件。在事件模型中,有三个参与......
  • PyQT5 PyQT入门教程(之二)
    REFhttps://www.jianshu.com/p/3832eb48f3d5 布局(Layout)管理QtDesigner中,在工具箱中最上方可以看到有4种布局。分别是垂直布局、水平布局、栅格布局和表单布局。  四种布局布局名称   布局含义垂直(Vertical)布局   布局内的控件按照从上到下的顺序纵向排列水平(Horizon......
  • PyQT5 PyQT入门教程(之一)
    REFhttps://www.jianshu.com/p/5b063c5745d0 本篇博客对应的视频讲解:https://www.bilibili.com/video/BV1NZ4y1Z7ue/ QtDesigner的介绍在PyQt中编写UI界面可以直接通过代码来实现,也可以通过QtDesigner来完成。QtDesigner的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现......
  • shell脚本执行make不一定调用Makefile
    今天在研究安卓编译流程时发现,shell脚本内执行make并不会调用当前路径下的Makefile,这有点让我大吃一惊。一番定位过后,发现执行make时调用的是另外一个shell脚本内定义的make函数,所以猜想可能GNUMake工具发现make有定义,所以直接调用该函数去了。于是我做了如下实验进行猜想验......
  • FreeRTOS入门教程(队列详细使用示例)
    (文章目录)前言上篇文章我们已经讲解了队列的概念和队列相关的API函数,那么本篇文章的话就开始带大家来学习使用队列。一、队列基本使用这个例子将会创建三个任务,其中两个任务用来发送数据到队列中,另一个任务用来从队列中读取数据。voidTask1Function(void*param){ intv......
  • Android入门教程 | UI布局之RelativeLayout 相对布局
    RelativeLayout简述RelativeLayout继承于android.widget.ViewGroup,按照子元素之间的位置关系完成布局,作为Android系统五大布局中最灵活也是最常用的一种布局方式,非常适合于一些比较复杂的界面设计。RelativeLayout和LinearLayout类似,都是ViewGroup,能“容纳”多个子view。R......
  • FreeRTOS入门教程(同步与互斥)
    (文章目录)前言前几篇文章一直在围绕FreeRTOS中的任务创建,删除,优先级,调度算法进行讲解,那么从本篇文章开始将围绕同步与互斥来展开讲解。一、同步与互斥概念当多个任务或线程共享资源并发执行时,同步和互斥是两个关键的概念。1.同步(Synchronization)是指协调多个任务或线程的执......
  • Spring Boot 入门教程
    大家好,我是深码青年,作为一名迄今为止已经有四年码龄的人来说,springboot已经深入了自己的脑子里面,所以借此机会,我们来仔细说一说关于springboot2.0的那些事儿一、SpringBoot是什么以下截图自[SpringBoot官方文档](https://spring.io/projects/spring-boot"SpringBoot官方......
  • NO.4 Makefile文件制作
    一、Makefile定义变量(1)用户自定义变量变量定义直接用=使用变量值用$(变量名)如:下面是变量的定义和使用foo=abc//定义变量并赋值bar=$(foo)//使用变量,$(变量名)(2)Makefile自带变量CC=gcc#arm-linux-gccCPPFLAGS:C预处理的选......
  • 【代码片段】makefile 中通过 shell 函数执行 sed
    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!cnblogs博客zhihuGithub公众号:一本正经的瞎扯先上代码:(在macos上调试通过)#defineashellfunctiontosetdebugmodetoreleasemode#whenosismacbook,usegsedasseddefinefunction_sed_set_rel......