编写 Makefile文件 (一)

article/2025/9/26 21:06:39

参考:《linux程序设计(第四版)》

本文的编写从简单到复杂,一步一步完成Makefile文件的编写和完善。首先看一下我们的程序有哪些文件:

文件内的程序也很简单,就是输出该文件已经被调用,代码如下:

void funcPrintf(void)
{printf("------ func.c ------\n");
}

 如果我们想要编译一个文件,首先想到的是在shell 下执行gcc命令,那么我们先通过几个shell脚本来实现文件的编译。

#! /bin/bash set -evgcc -o myApp main.c func.c func.hecho "bulid successful!"

下面是执行结果,编译生成了myApp,程序包含了main.c 和 func.c ,运行程序后打印在了终端上。 

实际上我们是执行了gcc -o myApp main.c func.c func.h命令完成了程序的编译,那么我们看一下如何用Makefile文件来完成这个操作。

myApp: main.c func.ogcc -o myApp main.c func.ofunc.o: func.h func.cgcc -c func.h func.c

我们分解了一步,提出了一个func.o 进行单独编译。其实完全可以写成下面的样子。

myApp: main.c func.h func.cgcc -o myApp main.c func.h func.c

 然后我们在Makefile文件所在目录执行make命令即可完成编译。

很显然,从目前的情况看Makefile让我们程序编译变得更加复杂,因为我们不得不去遵守Makefile的一些规则。

1. myApp 最终生成的目标文件

2. :后面的这些内容是编译生成目标文件所依赖的文件

3. gcc -o myApp main.c func.h func.c 是编译生产目标文件需要执行的指令(指令需要以TAB开头

上面就是Makefile的基本规则,可以理解为按照一定的规则将编译的shell 脚本写进一个名叫Makefile的文件,然后执行make指令后系统就会根据Makefile文件的规则执行编译shell指令。

既然上面的Makefile文件有两个,其中一个将func.o文件单独列出来了,这里就补充一下:我们用命令编译的时候可以分成两步:

gcc -c func.h func.c
gcc -o myApp main.c func.o

先生成连接文件func.o然后再连接func.o文件生成myApp,只是在Makefile文件编写时需要先告诉make指令编译生成myApp需要依赖main.c和func.o,然后make就会去寻找func.o文件。接着make发现生成func.o又依赖func.c和func.h文件,需要执行的指令是gcc -c func.h func.c 。总结一下:make会从最终目标出发,依次找到每个依赖,每个依赖的依赖....

编译过程中会生成各种文件,因此需要clean一下,添加一下clean指令。完善一下我们的Makefile文件,增加clean操作,删除连接文件、预编译文件和最终生成的目标文件。

myApp: main.c func.ogcc -o myApp main.c func.ofunc.o: func.h func.cgcc -c func.h func.cclean:-rm func.o *.h.gch myApp

执行 make clean 

插播一个知识点,不做过多解释,链接库

老规矩先上shell脚本:

#! /bin/bash set -evgcc lib.c lib.h -fPIC -shared -o lib.so# 编译生成链接库指令
gcc -o myApp main.c func.c func.h lib.socp lib.so /usr/libecho "bulid successful!"

 对比Makefile脚本:

myApp: main.c func.o lib.sogcc -o myApp main.c func.o lib.sofunc.o: func.h func.cgcc -c func.h func.clib.so: lib.c lib.hgcc lib.c lib.h -fPIC -shared -o lib.soclean:-rm func.o *.h.gch myApp *.so

通过上面的操作我们可以完成Makefile文件的编写,也能完成所有的工作,但是看上去不是那么的灵活。接下来需要讲一下变量,先上Makefile文件:

all: myAppCC: gccINCLUDE = .CFLAGS = -g -Wall -ansi#CFLAGS = -O -Wall –ansimyApp: main.c func.o lib.so$(CC) -o myApp main.c func.o lib.sofunc.o: func.h func.c$(CC)  -I$(INCLUDE) -c func.h func.clib.so: lib.c lib.h$(CC)  -I$(INCLUDE) lib.c lib.h -fPIC -shared -o lib.soclean:-rm func.o *.h.gch myApp *.soinstall:cp *.so /usr/lib ;\echo "make install";\./myApp;\echo "myApp running ...";

例子很简单,用了两个变量 CC: gcc 指定了编译器, CFLAGS = -g -Wall -ansi 指定了编译等级,变量引用使用方法$(变量名),上面的Makefile文件的执行结果如下:

Makefile本身也规定了几个常用的变量:

$@  表示目标文件

$^  表示所有的依赖文件

$<  表示第一个依赖文件

$?  表示比目标还要新的依赖文件列表

all: myAppCC: gccINCLUDE = .CFLAGS = -g -Wall -ansi#CFLAGS = -O -Wall –ansimyApp: main.c func.o lib.so$(CC) $(CFLAGS) -o $@ $^func.o: func.h func.c$(CC)  -I$(INCLUDE) $(CFLAGS) -c $^lib.so: lib.c lib.h$(CC)  -I$(INCLUDE) $(CFLAGS) $^ -fPIC -shared -o $@clean:-rm func.o *.h.gch myApp *.soinstall:cp *.so /usr/lib ;\echo "make install";\./myApp;\echo "myApp running ...";

这个Makefile文件除了增加了一个install 操作之外,其他的动作和上面的Makefile文件规定的一致,只是用变量做了替代。解释一下install,可以理解为一些列shell操作来完成程序的安装,其实并不一定是安装操作,比如上面的install操作只是将库文件拷贝进入/usr/lib目录并且执行了该文件。

我们还有两个文件在file文件夹内,现在我们也将这两个文件的编译加入进去。当然这里是一种简单的方法,后面介绍如何多文件夹递归编译。

all: myAppCC: gccINCLUDE = .INSTDIR = /usr/libCFLAGS = -g -Wall -ansi#CFLAGS = -O -Wall –ansimyApp: main.c func.o lib.so file.o$(CC) $(CFLAGS) -o $@ $^func.o: func.h func.c$(CC)  -I$(INCLUDE) $(CFLAGS) -c $^lib.so: lib.c lib.h$(CC)  -I$(INCLUDE) $(CFLAGS) $^ -fPIC -shared -o $@file.o: file/file.c file/file.h$(CC)  -I$(INCLUDE) $(CFLAGS) -c $^clean:-rm *.o *.h.gch myApp *.soinstall:cp *.so $(INSTDIR) ;\echo "make install";\./myApp;\echo "myApp running ...";

 

最后经过了修改和完善我们完成了最终的Makefile文件:

INCLUDE = .INSTDIR = /usr/libCFLAGS = -g -Wall -ansi
#CFLAGS = -O -Wall –ansiTARGET = myAppall: $(TARGET)CC: gcc$(TARGET): main.c func.o lib.so file.o$(CC) $(CFLAGS) -o $@ $^func.o: func.h func.c$(CC)  -I$(INCLUDE) $(CFLAGS) -c $^lib.so: lib.c lib.h$(CC)  -I$(INCLUDE) $(CFLAGS) $^ -fPIC -shared -o $@file.o: file/file.c file/file.h$(CC)  -I$(INCLUDE) $(CFLAGS) -c $^.PHONY: clean
clean:-rm *.o *.h.gch $(TARGET) *.soinstall:cp *.so $(INSTDIR) ;\echo "make install";\./$(TARGET);\echo "$(TARGET) running ...";

 


http://chatgpt.dhexx.cn/article/V5qon1Za.shtml

相关文章

如何编写makefile文件

文章目录 1. makefile文件的作用2. makefile文件编写格式C代码举例编写makefile文件 3. makefile编写习惯优化使用中间文件定义变量自动变量通配符假想目标 1. makefile文件的作用 在很多的生产环境中&#xff0c;一个项目的运行往往要有很多源程序文件生成最终的可执行文件&am…

Linux下makefile文件的编写

在学习如何编写makefile文件之前&#xff0c;我们首先需要了解什么是makefile文件&#xff1a; makefile描述了整个工程的编译和链接等规则。它指明了哪些文件需要先编译&#xff0c;哪写文件需要后编译&#xff0c;哪些文件需要重新编译&#xff0c;甚至进行更复杂的功能操作。…

Makefile文件详解一(怎么在Windows下使用Makefile文件)

前言&#xff1a;如果熟悉在Linux开发的话&#xff0c;肯定知道Makefile文件的用处&#xff0c;它给我们带来很多的便利。在Linux系统下并不会像Windows那么多开发工具&#xff0c;在Windows下&#xff0c;只要在开发工具上点击一个按钮&#xff0c;就能将工程的所有源码进行编…

makefile文件编写

makefile文件用于管理和组织代码工程的编译和链接&#xff0c;其不是可执行文件&#xff0c;其被make工具解析并完成相关动作&#xff0c;下面笔者将介绍makefile中常用的一些语法说明&#xff1a; 1、文件包含&#xff1a; 语法&#xff1a;include 文件名 作用&#xff1a;…

make中makefile文件的创建和使用

Makefile文件就是一种定义规则的文件&#xff0c;规则不同但格式基本相同&#xff0c;如图 一个makefile中有多个规则&#xff0c;但最终形成一个makefile文件&#xff0c;且只有一个终极目标&#xff0c;第一行就是终极目标。 格式: 1.目标文件&#xff1a;&#xff08;如mai…

【Linux基础】如何编写Makefile文件?

文章目录 前言一、make工具简介1.什么是make?2.如何安装make? 二、编写Makefile文件1.文件组成2.工作原理3.Makefile文件优点4.单级目录下的Makefile文件编写5.多级目录下的Makefile文件编写 总结 前言 我们刚开始在Linux系统下进行编程时&#xff0c;采用的编译方法为&#…

从0开始教你编写Makefile文件

目录 编写Makefile第一步&#xff0c;了解什么是Makefile&#xff1f; 编写Makefile第二步&#xff0c;明白编译链接过程 编写Makefile第三步&#xff0c;实现简单的Makefile(生成单个可执行文件) 解释一下一个简简单单的make都干了什么&#xff1f; 编写Makefile第四步&am…

C语言makefile文件

文章目录 一、makefile的编写二、make命令三、makefile文件中的变量四、应用经验五、课后作业六、版权声明 在软件的工程中的源文件是很多的&#xff0c;其按照类型、功能、模块分别放在若干个目录和文件中&#xff0c;哪些文件需要编译&#xff0c;那些文件需要后编译&#xf…

【Linux】Makefile文件

1.Makefile的作用 Makefile文件定义了一系列的规则来指定哪些文件需要先编译&#xff0c;哪些文件需要后编译&#xff0c;哪些文件需要重新编译&#xff0c;可以实现自动化编译&#xff0c;一旦写好&#xff0c;只需要一个make命令&#xff0c;整个工程完全自动编译&#xff0…

计算一幅图像的信噪比

计算一幅图像的信噪比 适用情况计算步骤附matlab代码example计算结果计算峰值信噪比 大家好&#xff0c;这是我两年前写的一篇博客修正版本&#xff0c;本来打算删掉了&#xff0c;但是阅读量很多&#xff0c;可能对大家会有一点小小的帮助&#xff0c;就重新放上来吧。 适用情…

两种常用的全参考图像质量评价指标——峰值信噪比(PSNR)和结构相似性(SSIM)

原文&#xff1a;https://blog.csdn.net/zjyruobing/article/details/49908979 1.PSNR&#xff08;Peak Signal to Noise Ratio&#xff09;峰值信噪比&#xff1a; MSE表示当前图像X和参考图像Y的均方误差&#xff08;Mean Square Error&#xff09;&#xff0c;H、W分别为图…

图像信噪比的理解

图像的信噪比和图像的清晰度一样&#xff0c;都是衡量图像质量高低的重要指标。图像的信噪比是指视频信号的大小与噪波信号大小的比值&#xff0c;其公式为&#xff1a; S/N&#xff08;信噪比&#xff09; 20 log (信号/噪声)dB信噪比大&#xff0c;图像画面就干净&#xff0…

相机的信噪比

在图像传感器的成像过程中&#xff0c;真实的信号是无法探测到的理想值。在成像过程中理想值被引入了一系列的不确定性&#xff0c;最终形成读出信号也即图像。此过程中的不确定性被统一称为噪声。而信号与噪声的比值被定义为信噪比&#xff08;Signal-to-NoiseRatio, SNR&…

信噪比(SNR)

信噪比&#xff08;Signal-to-noise ratio&#xff0c;缩写为 SNR 或 S/N&#xff09;&#xff0c;也称作信杂比或讯杂比。 信噪比&#xff0c;为有用信号功率(Power of Signal)与噪声功率(Power of Noise)的比。因此为幅度&#xff08;Amplitude&#xff09;比的平方&#xff…

信干噪比、信噪比

信干噪比 名词定义 信干噪比SINR&#xff08;Signal to Interference plus Noise Ratio&#xff09;&#xff0c;指的是系统中信号与干扰和噪声之和的比。 信号是指来自设备外部需要通过设备进行处理的电子信号。 干扰是指系统本身以及异系统带来的干扰&#xff0c;如同频干扰…

图像的峰值信噪比(peak signal to noise ratio, PSNR)

峰值信噪比&#xff08;PSNR&#xff09;是一个表示信号最大可能功率和影响它的表示精度的破坏性噪声功率的比值的工程术语。由于许多信号都有非常宽的动态范围&#xff0c;峰值信噪比常用对数分贝单位来表示。 在图像处理中&#xff0c;要对图像进行客观的评价&#xff0c;常…

图像处理随笔之峰值信噪比(peak signal to noise ratio)

图像处理随笔之峰值信噪比&#xff08;peak signal to noise ratio&#xff09; the definition from WIKI&#xff1a;an engineering term for the ratio between the maximum power of a signal and the power of corrupting noise that affects the fidelity of its repre…

python求不同分辨率图像的峰值信噪比,一文搞懂

可以使用 Python 的 NumPy 和 OpenCV 库来实现这个任务。提前准备一张图片作为素材。 文章目录 什么是峰值信噪比PSNR 峰值信噪比补充说明 使用 OpenCV 库来实现这个任务PSNR 的计算值受图像的亮度影响计算不同分辨率图像的 PSNRpython 求不同分辨率图像的峰值信噪比 | 其他知识…

【深度学习】图像去雾,去噪里常用的相似评价指标:PSNR(峰值信噪比) SSIM(结构相似度)MSE(均方误差)

文章目录 一、PSNR&#xff08;峰值信噪比&#xff09;二、SSIM&#xff08;结构相似度&#xff09;三、MSE&#xff08;均方误差&#xff09;小插曲&#xff1a;plt.savefig&#xff08;&#xff09;保存的图片为空白 一、PSNR&#xff08;峰值信噪比&#xff09; 公式直接抄我…

信噪比

fft原理 能量谱 &#xff08;5&#xff09;能量信号频谱通常既含有幅度也含有相位信息&#xff1b;幅度谱的平方&#xff08;二次量纲&#xff09;又叫能量谱&#xff08;密度&#xff09;&#xff0c;它描述了信号能量的频域分布&#xff1b;功率信号的功率谱&#xff08;密…