【Linux应用开发·入门指南】Makefile菜鸟教程

目录

1.  概述

2.  准备工作

2.1  安装工具包

2.2  创建Helloworld程序

3.  编写 Makefile 文件

4.  拓展一:clean的使用

5.  拓展二:变量的引入

6.  拓展三:自动推导

7.  拓展四:安装vscode-makefile-term插件


1.  概述

        Makefile是一种用于管理和自动化软件编译过程的文本文件。它通常包含了一系列规则,这些规则描述了如何根据源代码文件生成可执行文件或者其他目标文件。Makefile的核心概念是规则和依赖关系,规则定义了如何生成一个或多个目标文件,而依赖关系则指定了生成目标文件所需要的源文件或其他依赖文件。

        简单点来说,Makefile 就是用来管理项目的,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译。

2.  准备工作

2.1  安装工具包

        要想使用 Makefile,需要要确保我们安装好的Linux上又相关的工具,输入命令:

sudo apt install -y build-essential 

        这是一个工具包,其中包含gcc/g++等开发工具,make-doc就是我们需要的 Makefile:

2.2  创建Helloworld程序

        为了方便观看具体流程,创建三个文件第一个hello.c:

#include<stdio.h>
#include"hello.h"

void Hello_World(void)
{
    printf("Hello World!!!\n");
}

        第二个hello.h:

#ifndef __HELLO_H__
#define __HELLO_H__

void Hello_World(void);

#endif

        第三个main.c:

#include"hello.h"
#include <stdio.h>

#define num 3

//这是一个注释
int main()
{
    int a = 10;

    if(a<num)
    {
       Hello_World();
    }
    else
    {
        printf("This is gcc !!!\n");
    }

    return 0;
}


        为了方便查看代码,我们可以在Linux上下载一个VScode进行查看,但是最终编译代码还是回到终端上进行编译,因为我们如果要在开发板上进行开发,开发板可不会提供给我们VScode,有的只有终端进行编译,VScode在这里只是辅助我们观看代码,当然如果你还是想使用 vi 也是可以的,对编译没有任何影响。

对于VScode的安装,可以参考如下链接:

Linux应用开发·如何在Linux上安装VScode、gcc编译流程以及如何进行静态/动态链接的打包使用·详细步骤演示-优快云博客

只看VScode安装部分即可,如果不了解gcc的编译流程最好看一下。


        在创建一个 Makefile 的文件,可以直接在终端使用命令:

        也可以来到VScode直接右键:

注意:我们平常遇见的xxx.mk 文件或者 Makefile 都统称为 Makefile 脚本文件。

命名只能为 makefile 或者是 Makefile,因为只有这两种命名方式才能被 make 命令识别

        在VScode上创建 Makefile 文件的时候,如果之前没有安装过相关扩展,第一次创建右下角会提示需要安装扩展,安装即可:

        这里的安装扩展,和上面的工具包是两码事,一个是在终端,一个是在VScode,安装完成后:

3.  编写 Makefile 文件

        在编写前,我们先了解一下 Makefile 内容都是由那三部分组成,其格式如下:

# Makefile内容组成部分
# <目标名称>:<前置依赖>
#     \t<需要执行的命令>

# 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格

# 举个例子

main:hello.o main.o
    gcc hello.o main.o -o main

        在VScode上编写:

        或者通过命令在 vi 上编写:

        而这个hello.o和main.o文件是怎么来的呢?这就需要我们通过gcc进行编译:

        此时输入make就会运行:

        不过此时我们会发现,我们在输入make前还需要输入这么多的前置命令非常不方便,那么我们为什么不让make帮我们输入呢:

# Makefile内容组成部分
# <目标名称>:<前置依赖>
#     \t<需要执行的命令>

# 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格

# 举个例子
# 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:hello.o main.o
    gcc hello.o main.o -o main

# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.h
    gcc -c main.c

# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.h
    gcc -c hello.c

        我们将前置的文件全部删除掉:

        运行一下看一下:

        到这里其实已经能进行Makefile的一个简单的使用了,下面我们在做一些拓展。

4.  拓展一:clean的使用

        在我们上面使用完 Makefile 后会发现出现一堆.o文件,此时因为这个只是一个简单的hello world程序,不是很明显,若是一个大型项目,一堆.o文件会影响我们的阅读,若是一个一个删除又比较麻烦:

        这里我们将 Makefile 的代码简单的更改一下,在尾部添加clean程序:

# Makefile内容组成部分
# <目标名称>:<前置依赖>
#     \t<需要执行的命令>

# 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格

# 举个例子
# 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:hello.o main.o
	gcc hello.o main.o -o main

# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.h
	gcc -c main.c

# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.h
	gcc -c hello.c

clean:
	rm -f main.o hello.o

        我们可以通过make clean命令将.o文件删除:

5.  拓展二:变量的引入

       对于 Makefile 有四种变量赋值方式:

:=		# 即时变量
= 		# 延时变量
?= 		# 延时变量,如果是第 1 次定义才起效,如果在前面该变量已定义则忽略这句
+= 		# 附加,他是即时变量还是延时变量取决于前面的定义

        我们更改一下代码:

# Makefile内容组成部分
# <目标名称>:<前置依赖>
#     \t<需要执行的命令>

# 注意\t制表符是一个Tab键,在键盘上,最好自己敲上去,复制有时候会识别为空格

# 举个例子
# 定义变量 example_sum
example_sum := hello.o main.o 

# 放在第一个是默认目标
# 目标是编译出main文件,依赖hello.o和main.o文件
# 编译的命令是gcc hello.o main.o -o main
main:$(example_sum)
	gcc $(example_sum) -o main

# 目标是main.o 依赖main.c和hello.h
# 编译的命令是gcc -c main.c
main.o:main.c hello.h
	gcc -c main.c

# 目标是hello.o 依赖hello.c和hello.h
# 编译的命令是gcc -c hello.c
hello.o:hello.c hello.h
	gcc -c hello.c

clean:
	rm -f $(example_sum)

        可以看到能够正常运行:

6.  拓展三:自动推导

        Makefile 有一个强大特性,可以大大简化编译规则的编写,那就是自动推导,我们上面可以看到 Makefile 里面写了非常多的东西,其实又许多的  Makefile 是可以自动推导出来的,可以直接简写为:

main: main.o hello.o

        可以看到也能正常运行:

        但是对于clean还是需要自己编写,为了后续方便我们还是先加上:

        还需要注意一点的是,他对于hello.h的更改是识别不到的,我来可以来看一下,首先是对main.c进行更改,找一行代码回车一下就行,我们先不进行更改,其显示未更新,因此不会执行别的命令:

        我们随便一行敲一下回车,更改一下main.c保存一下,可以检测到更改,重新执行了main.c的命令,但是对于hello.c未做回应:

        同样的方法,我们更改一下hello.c来看看:

        但是如果我们对hello.h进行更改,可以发现识别不到更新:

        这是因为自动推导不能自动检测头文件依赖,那么如何解决呢?就是将不能推导的给写上去,明确写出头文件依赖:

main: main.o hello.o

main.o:hello.h
hello.o:hello.h

clean:
	rm -f main.o hello.o

        此时就可以检测到跟改:

7.  拓展四:安装vscode-makefile-term插件

        在插件市场搜索并安装vscode-makefile-term插件,完成后,在VScode中打开Makefile文件:

        可以看到每个target上方都出现执行按钮:

        点击三角可以发现下方的运行:

嵌入式Linux·应用开发_时光の尘的博客-优快云博客

Makefile 在 Unix 上写程式的人大概都碰过 Makefile,尤其是用 C 来开发程式的 人。用 make 来开发和编译程式的确很方便,可是要写出一个 Makefile 就不简单了。偏偏介绍 Makefile 的文件不多,GNU Make 那份印出来要几 百页的文件,光看完 Overview 就快阵亡了,难怪许多人闻 Unix 色变。 本文将介绍如何利用 GNU Autoconf 及 Automake 这两套软体来协助我们 『自动』产生 Makefile 档,并且让开发出来的软体可以像 Apache, MySQL 和常见的 GNU 软体一样,只要会 ``./configure'', ``make'', ``make install'' 就可以把程式安装到系统中。如果您有心开发 Open Source 的软体,或只是想在 Unix 系统下写写程式。希望这份介绍文件能 帮助您轻松地进入 Unix Programming 的殿堂。 1. 简介 Makefile 基本上就是『目标』(target), 『关连』(dependencies) 和 『动作』三者所组成的一连串规则。而 make 就会根据 Makefile 的规则 来决定如何编译 (compile) 和连结 (link) 程式。实际上,make 可做的 不只是编译和连结程式,例如 FreeBSD 的 port collection 中, Makefile 还可以做到自动下载原始程式套件,解压缩 (extract) ,修补 (patch),设定,然後编译,安装至系统中。 Makefile 基本构造虽然简单,但是妥善运用这些规则就也可以变出许多不 同的花招。却也因此,许多刚开始学习写 Makefile 时会感到没有规范可 循,每个人写出来的 Makefile 长得都不太一样,不知道从何下手,而且 常常会受限於自己的开发环境,只要环境变数不同或路径改一下,可能 Makefile 就得跟着修改。虽然有 GNU Makefile Conventions (GNU Makefile 惯例) 订出一些使用 GNU 程式设计时撰写 Makefile 的一些标 准和规范,但是内容很长而且很复杂, 并且经常做些调整,为了减轻程式 设计师维护 Makefile 的负担,因此有了 Automake。 程式设计师只需写一些预先定义好的巨集 (macro),交给 Automake 处理 後会产生一个可供 Autoconf 使用的 Makefile.in 档。再配合利用 Autoconf 产生的自动设定档 configure 即可产生一份符合 GNU Makefile 惯例的 Makeifle 了。
Makefile 是一种用来自动化编译程序的工具,使用它可以简化编译过程,提高编译效率。下面是一个简单的 Makefile 菜鸟教程。 假设我们的工程目录结构如下: ``` project ├── src │ ├── main.c │ ├── func1.c │ └── func2.c ├── include │ ├── func1.h │ └── func2.h └── bin ``` 其中,src 目录包含了源代码,include 目录包含了头文件,bin 目录用于存放编译后的可执行文件。 我们的目标是编译出一个名为 project 的可执行文件。下面是一个简单的 Makefile: ```makefile CC = gcc CFLAGS = -Wall -I./include LDFLAGS = -lm SRCS := $(wildcard src/*.c) OBJS := $(patsubst %.c, %.o, $(SRCS)) TARGET = bin/project all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -rf $(OBJS) $(TARGET) ``` 接下来逐行解释每个部分的作用: - `CC` 定义编译器的路径和名称。 - `CFLAGS` 定义编译器的编译选项。这里使用了 `-Wall` 表示开启所有警告信息,`-I./include` 表示头文件的路径为 `./include`。 - `LDFLAGS` 定义链接器的链接选项。这里使用了 `-lm` 表示链接 `libm` 库。 - `SRCS` 使用 `wildcard` 函数获取 `src` 目录下的所有 `.c` 文件。 - `OBJS` 使用 `patsubst` 函数将 `.c` 文件名替换成 `.o` 文件名。 - `TARGET` 定义目标可执行文件的路径和名称。 - `all` 是一个伪目标,表示默认编译所有目标。 - `$(TARGET)` 是一个依赖目标,表示编译目标可执行文件。它依赖于所有的 `.o` 文件。 - `$(OBJS)` 是一个中间变量,表示所有的 `.o` 文件。 - `$@` 表示目标文件名,`$^` 表示所有依赖文件名。 - `%.o: %.c` 是一个模式规则,表示将所有 `.c` 文件编译成 `.o` 文件。 - `clean` 是一个伪目标,表示清除所有中间文件和目标文件。 使用方法: 1. 将上述代码保存为 `Makefile` 文件。 2. 在终端中进入工程目录。 3. 执行命令 `make`,即可自动编译出目标可执行文件。 4. 执行命令 `make clean`,即可清除所有中间文件和目标文件。 以上就是一个简单的 Makefile 菜鸟教程,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光の尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值