【Linux】Makefile项目管理工具(第八篇)

目录

[makefile 1.0](#makefile 1.0)

[makefile 2.0](#makefile 2.0)

[makefile 3.0](#makefile 3.0)


Makefile 可以简单的认为是一个工程文件的编译规则,描述了整个工程的编译和链接等规则。其中包含了哪些文件需要编译,哪些文件不需要编译,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重建等等。编译整个工程需要涉及到的,在 Makefile 中都可以进行描述。换句话说,Makefile 可以使得我们的项目工程的编译变得自动化,不需要每次都手动输入一堆源文件和参数。

makefile 1.0

在linux下编写Makefile脚本帮助开发者编译管理工程 Makefile的用途与优势 1.可以让开发者实现编译管理复杂工程 2.使用MakeFile编译工程,可以大大节省编译时间(企业级工程) 3.MakeFile脚本编写时,开发者应该注重高重用性 一次编写终生受益

Makefile脚本编写基础: 项目管理脚本命名: Makefile makefile 文件类型:常规文件 文件类型 .mk(可缺省)

Makefile 脚本三要素:目标、依赖、命令 # 理想、能力、行动力 #代表单行注释

示例1: vi test.c

int main() { while(1); return 0; } gcc test.c -o app

vi Makefile

#makefile 三要素 #目标:依赖 依赖 依赖 Tab键 命令(易错必须是TaB 不可以是空格) app:test.c

gcc test.c -o app

Makefile 编写成功后,如何使用? make(命令)----find--->Makefile--执行--->编译结果

make 回车

示例2:

bash 复制代码
mkdir project
cd project
mkdir include
mkdir library
mkdir source
touch   Makefile
cd source  touch Makefile
cd  include/  
touch demo.h int ADD(int,int);   int SUB(int,int);  int MUL(int,int); int DES(int,int);
touch add.c sub.c mul.c des.c  main.c
cd source/  add.c sub.c mul.c des.c main.c
复制代码
​
vi main.c
​
cpp 复制代码
#include <demo.h>
int main()
{
     printf(%d,ADD(1,2));
     return 0;
}

#-I 路径m gcc add.c sub.c des.c mul.c main.c -I../include -o app ./app tree

复制代码
vi makefile
app:add.c sub.c mul.c des.c main.c (不允许用*.c,makefile 脚本语言不支持通配符,终端支持)   
    gcc *.c  -I../include -o app

编译XX系统可以花了10个小时 ld链接器:将工程资源进行组合链接,变成可执行程序

add.c---->add.o ​ sub.c---->sub.o ​ mul.c---->mul.o ​ des.c---->des.o ​ main.c---->main.o _START--------id success--->app(ELF) ​ 工程源码 可重新定位的核心二进制 ​ 临时文件

编译浪费时间,怎么节省时间呢? Makefile 节省编译时间:空间换时间,将第一次安装过程中.o二进制文件保留,下次编译时,被修改的.c源码需要重新生成.o,未修改的可直接重用.o,可以大大节省第二次编译时间

makefile 2.0

gcc中-c和-o是编译时可选的参数

-加-c, (compile)只编译生成中间同名目标文件,不链接 -加-o,(output)指定输出文件名,该文件为可执行文件,不加-o会默认生成a.out

示例: #include <stdio.h> .... gcc while.c -c -o app 产生.o 文件

可以使用gcc -c 将二进制文件创建并保留到当前目录

复制代码
vi makefile 
bash 复制代码
app:add.o sub.o mul.o main.o
       gcc *.o -o app
​
add.o:add.c
           gcc  -I../include -c add.c
sub.o:sub.c
            gcc  -I../include -c sub.c
mul.o:mul.c
            gcc  -I../include -c mul.c
des.o:des.c
            gcc  -I../include -c des.c
main.o:main.c
            gcc  -I../include -c main.c

使用方法: make 这个makefile 已经具备节省时间得功能,只编译更改的文件:比如 改动其中一个文件 重新make

如果没有改动 make,则显示is up to date

Makefile 原理

默认的情况下,make执行的是Makefile中的第一个规则,此规则的第一个目标称之为"最终目的"或者"终极目标"。从上至下建立依赖关系 分析目标,自底向上 执行任务 makefile 怎么知道哪个文件更新呢? 文件上的时间标签 FILE 最近访问时间 最近修改时间(修改文件内容) 最近改动时间(改动的文件Inode 文件属性) makefile 文件依赖项: add.o add.c #目标修改时间要比依赖文件的修改时间新 检测到依赖比目标新,执行命令更新目标 gcc -I../include -c add.c 永远保持目标文件修改时间最新

makefile 3.0

最大限度的提高makefile的可用性与重用性 1.makefile 变量定义和使用(常见变量) 2.特殊变量的使用 3.makefile内建语法规则 4.makefile内置函数 5.伪目标 6.功能目标

1.makefile 变量定义和使用(常见变量) 如:变量一般是大写 没有类型 1)默认情况下变量存储为字符串数据(定义时无需指定类型) 2)变量名尽可能定义为大写(变量 名可以由大写字母、下划线、数字 变量的首字符不允许数字) 3)需要使用变量的值必须对变量进行取值操作,取值符为$(如:NAME=aaa $NAME)

vi makefile NAME="2021-10-27"

output:

echo $(NAME) #为了防止识别异常

make

INCLUDE_PATH=../include # 存储头文件位置 #常见变量

-g 调试信息 -c 生成.o文件 -Wall 严格编译有点问题就报错)

CFLAGS=-I(INCLUDE_PATH) -g -c -Wall #用于存储编译时选项 #-E生成预处理信息 -D编译时定义宏 -o1 -o2 -o3编译时优化(优化代码) CPPFLAGS=-E -D -O1 -O2 -O3 #存储预处理选项 #-L 库路径 -l 指定库名 比如:libpthread.so 真实库名一般叫pthread LIBRARY_PATH= ../library LDFLAGS= -L(LIBRARY_PATH) -lpthread #存储库选项 TARGET=app #存储目标名 cc=gcc #存储编译器名(版本) gcc c g++ c++

INSTALL_PATH=/usr/bin #程序安装路径

特殊变量 三个 $@ $^ \< 每个特殊变量都表示一个目标中的某一部分,不同目标含义不同 #@目标名 $^依赖 $<依赖项中第一个 示例: apk:a.c b.c c.c d.c $@: 代表apk $^:代表a.c b.c c.c d.c $<:代表a.c

app:e.c f.c g.c h.c $@:代表app $^:代表e.c f.c g.c h.c $< :代表e.c


wildcard #获取工程目录下的文件名 .x后缀文件

一 、作用

获取工程目录下的文件名

二、格式

$(wildcard PATTERN...) 。

在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别。

示例:

一般我们可以使用"$(wildcard *.c)"来获取工作目录下的所有的.c文件列表。

patsubst函数用于将文件模式进行替换

一、作用

替换文件后缀。

二、格式

$(patsubst 原模式, 目标模式, 文件列表):

示例:

(patsubst %.c,%.o,(wildcard *.c)) # 首先使 用"wildcard"函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。

复制代码
SRCFILE=$(wildcard  *.c)   #调用函数返回值为SRCFILE
DESFILE=$( patsubst %.c,%.o,$(SRCFILE) )
output:
           echo $(SRCFILE)   #()为了防止识别异常
​
           echo $(DESFILE)
​
#使用内建语法完成迭代处理
$(TARGET):$(DESFILE)
       $(cc) $^ -o $@
%.o:%.c
      $(cc)  $(CFLAGS) $<

其中:

复制代码
这句话的意思就是 %.o : %.c
也就是说,所有的.o文件,依赖于对应的.c文件
比如有三个a.c b.c c.c
那么就会有 a.o b.o c.o
a.o : a.c
b.o : b.c
c.o : c.c
这是makefile依赖的一种简写方法。makefile的依赖关系有很多种写法。这是其中一种

注意事项:要注释上面的output,然后再make

功能目标,没有依赖,完成特定任务,执行功能目标, make output clean: rm $(DESFILE) -rf rm $(TARGET) -rf install: #安装 sudo mv $(TARGET) $(INSTALL_PATH) disclean:#卸载 sudo rm (INSTALL_PATH)(TARGET) -rf #千万不要写错,比如TARGET写成TRAGET sudo rm /usr/bin/ -rf 会把整个目录下的内容全部删掉 make clean make output make install #修饰符 @可以隐藏修饰的命令本身, 只显示结果 -如果被修饰的命令出错,可以向后执行,如果不修饰,遇到错误则退出 output:

复制代码
     - @ echo $(SRCFILE)   #()为了防止识别异常
              - @echo $(DESFILE)

source中的makefile :管理编译源码 工程目录下的makefile : 使用此makefile 调度运行source中的makefile完成代码管理编译。 vi makefile #使用次makefile 用户管理执行source_makefile #-c 去哪里执行 makestart:./source make -C ./source #执行source 下的make makeclean:./source

make clean -C ./source

相关推荐
Tak1Na12 分钟前
2024.9.18
linux·运维·服务器
A^mber17 分钟前
828华为云征文|云服务器Flexus X实例|Ubunt部署Vue项目
运维·服务器·华为云
安得权22 分钟前
Ubuntu 20.04 部署 NET8 Web - Systemd 的方式 达到外网访问的目的
linux·前端·ubuntu
chnyi6_ya22 分钟前
深度学习的笔记
服务器·人工智能·pytorch
让学习成为一种生活方式27 分钟前
解析药用植物重楼甾体皂苷生物合成中的连续糖基化及其抗真菌作用-文献精读49
linux·数据库·算法·天然产物化学
凯哥是个大帅比1 小时前
ubuntu20.04 GLIBC从2.35降级到2.31
linux
iHero1 小时前
【Ubuntu】在 Ubuntu 22.04.3 LTS 安装 davfs2 通过 Nextcloud WebDAV 挂载到 Ubuntu 的目录上
linux·ubuntu·nextcloud
心勤则明1 小时前
Netty配置SSL证书加密
服务器·https·ssl
清园暖歌1 小时前
Ubuntu 不重装系统增加交换空间大小
linux·运维·ubuntu·交换空间
黎相思1 小时前
操作系统迁移(CentOs -> Ubuntu)
linux·ubuntu·gitee·centos