【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

相关推荐
PcVue China2 小时前
PcVue + SQL Grid : 释放数据的无限潜力
大数据·服务器·数据库·sql·科技·安全·oracle
舞动CPU4 小时前
linux c/c++最高效的计时方法
linux·运维·服务器
皮锤打乌龟4 小时前
(干货)Jenkins使用kubernetes插件连接k8s的认证方式
运维·kubernetes·jenkins
钰@4 小时前
小程序开发者工具的network选项卡中有某域名的接口请求,但是在charles中抓不到该接口
运维·服务器·小程序
wanhengwangluo5 小时前
云服务器和物理服务器的区别有哪些?
运维·服务器
秦jh_5 小时前
【Linux】多线程(概念,控制)
linux·运维·前端
yaosheng_VALVE6 小时前
稀硫酸介质中 V 型球阀的材质选择与选型要点-耀圣
运维·spring cloud·自动化·intellij-idea·材质·1024程序员节
看山还是山,看水还是。7 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率
扣得君7 小时前
C++20 Coroutine Echo Server
运维·服务器·c++20
keep__go7 小时前
Linux 批量配置互信
linux·运维·服务器·数据库·shell