makefile中的两个函数(wildcard和patsubst)

(1) wildcard函数

作用是查找指定目录下指定类型的文件,并最终返回一个环境变量,需要用$取值赋值给另一个环境变量!该函数只有一个参数,如取出当前目录下的所有.c文件,并赋值给allc普通变量:  allc=$(wildcard ./*.c)。

(2) patsubst函数

作用是更换文件的后缀格式,共有三个参数。如将allc的所有.c的文件更换为.o的文件: allo=$(patsubst %.c,%.o,$(allc))。 

注意以上两个函数的返回值都为变量值,都必须用$取值。makefile中的所有函数都必须要有返回值。

allo1=$(patsubst %.c,./bin/%.o,$(allc))  将替换后生成的.o文件都存放在./bin/中,指出路径。

(3)不带依赖条件的规则

对于没有依赖条件,只有目标和命令的规则,说明为了实现该目标,不需要任何依赖条件,直接执行命令即可。makefile直接执行命令。下面举例说明:  再次强调一点,每一行的命令前必须有一个tab缩进,这是makefile识别命令的判断符号。

clean:

        -mkdir /aa   //-表示,该条命令执行失败了,也会继续向下执行下一条命令

        rm -f $(allo) $(target)

 

hello:          //举例说明,这一项在以后中不要

        echo "hello, makefile"

[root@localhost src]# make clean   //只是执行clea后面的命令即可

[root@localhost src]# make hello   //只是执行hello后面的命令即可

如果在makefile文件目录中有一个以clean或hello名字为名的文件(即相同了),则make clean和make hello不会执行命令,需要进行伪目标声明,即:

.PHONY:clean        //伪目标的声明

clean:

        -mkdir /aa   //-表示,该条命令执行失败了,也会继续向下执行下一条命令

        rm -f $(allo) $(target)

 

.PHONY:hello        //伪目标的声明

hello:          //举例说明,这一项在以后中不要

        echo "hello, makefile"

最后,如果makefile文件不是以makefile或Makefile为名字,需要加上-f参数:make -f filename

下面给出之前例子makefile书写的最终版,即把一个规则,两个变量和三个函数结合:

[root@localhost src]# ls
a  add.c  div.c  main.c  makefile  mul.c  sub.c
[root@localhost src]# vim zsxmakefile

allc=$(wildcard ./*.c)    //获取所有的.c文件
obj=$(patsubst %.c,%.o,$(allc))   //更换为.o文件,取得目标文件
target=zsx

$(target):$(obj)
        $(CC) -ggdb3 $^ -o $@

main.o:main.c
        $(CC) -pedantic -Wall -pipe -c $^ -o $@ -I ../include

%.o:%.c
        $(CC) -pedantic -Wall -pipe -c $< -o $@
        
.PHONY:clean1  //伪目标的声明

clean1:
        -mkdir b    //-代表该条命令执行失败了,也会继续向下执行下一条命令
        rm -f $(obj) $(target)

.PHONY:hello     //伪目标的声明

hello:
        echo "hello, makefile"


[root@localhost src]# rm -f makefile 
[root@localhost src]# ls
a  add.c  div.c  main.c  mul.c  sub.c  zsxmakefile
[root@localhost src]# make -f zsxmakefile   //此时需要加-f参数
cc -pedantic -Wall -pipe -c mul.c -o mul.o
cc -pedantic -Wall -pipe -c main.c -o main.o -I ../include
cc -pedantic -Wall -pipe -c add.c -o add.o
cc -pedantic -Wall -pipe -c div.c -o div.o
cc -pedantic -Wall -pipe -c sub.c -o sub.o
cc -ggdb3 mul.o main.o add.o div.o sub.o -o zsx
[root@localhost src]# ls
a  add.c  add.o  div.c  div.o  main.c  main.o  mul.c  mul.o  sub.c  sub.o  zsx  zsxmakefile
[root@localhost src]# make -f zsxmakefile clean1    //注意使用方法  如果文件名字是makefile或Makefile,则直接为make clean1
mkdir b
rm -f ./mul.o ./main.o ./add.o ./div.o ./sub.o zsx
[root@localhost src]# ls
a  add.c  b  div.c  main.c  mul.c  sub.c  zsxmakefile
[root@localhost src]# make -f zsxmakefile hello //注意使用方法
echo "hello, makefile"
hello, makefile

 

//注意区分makemake cleanmake hello的作用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C库函数

Linux的系统I/O函数&#xff08;read、write、open、close和 lseek等&#xff09;与C语言的C库函数&#xff08;libc.so库文件中&#xff09;都是相对应的&#xff0c;它们都是动态库函数。如下图所示&#xff0c;C库函数有fopen、fclose、fwrite、fread和fseek等。这些C库函数…

C库函数与Linux系统函数之间的关系

由上小节知道&#xff0c;C库函数是借助FILE类型的结构体来对文件进行操作的&#xff0c;其本身只是在用户空间&#xff08;I/O缓冲区&#xff09;进行读写操作&#xff0c;而数据在内核与用户空间之间的传递、以及将内核与I/O设备之间的数据传递都是该C库函数进行一系列的系统…

open函数和errno全局变量

&#xff08;1&#xff09;open函数 man man 查看man文档的首页 其中DESCRIPTION部分描述了man文档的每一章的章节内容 第2章System calls为系统调用&#xff0c;即Liunx系统函数。 man 2 open 查看第二章的open函数的详细帮助文件。 open函数用于打开一个已经的文件或者创…

open函数和close函数的使用

学习几个常用的Linux系统I/O函数&#xff1a;open、close、write、read和lseek。注意&#xff0c;系统调用函数必须都考虑返回值。 &#xff08;1&#xff09;open函数的使用 首先&#xff0c;需要包含三个头文件&#xff1a;<sys/types.h> <sys/stat.h> <…

1091. Acute Stroke (30)

One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core. Input Speci…

stat函数(stat、fstat、lstat)

#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> //需包含头文件 有如下三个函数的函数原型&#xff1a; int stat(const char *path, struct stat *buf); 第一个形参&#xff1a;指出文件&#xff08;文件路径&#xff09;&…

【Leetcode | 235】 235. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己…

CPU和MMU(内存管理单元)

CPU的架构&#xff1a;要求能够理解从源程序到微指令的整个经历过程&#xff1a;存储器的层次结构&#xff08;网络资源下载到硬盘、磁盘缓存、内存、Cache、寄存器&#xff09;&#xff1b;CPU的四大部分&#xff1a;ALU、CU、中断系统和寄存器&#xff1b;程序执行的整个过程…

【C++ Primer | 09】容器适配器

一、stack s.push(): 向栈内压入一个成员&#xff1b; s.pop(): 从栈顶弹出一个成员&#xff1b; s.empty(): 如果栈为空返回true&#xff0c;否则返回false&#xff1b; s.top(): 返回栈顶&#xff0c;但不删除成员&#xff1b; s.size(): 返回栈内元素…

进程控制块PCB(进程描述符)

&#xff08;1&#xff09;PCB 每个进程在内核中都有一个进程控制块&#xff08;PCB&#xff09;来维护进程相关的信息&#xff0c;Linux内核的进程控制块是task_struct结构体。grep -r “task_struct” / 可以查找根目录下&#xff0c;包含task_struct的文件文件。或者 find…

【C++ Primer | 19】控制内存分配

1. 测试代码&#xff1a; #include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;if (void* p…

【第15章】虚函数

一、为什么基类中的析构函数要声明为虚析构函数&#xff1f; 直接的讲&#xff0c;C中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说&#xff0c;如果派生类中申请了内存空间&#xff0c;并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数&am…

【C++ Primer | 08】IO库

一、istringstream类 描述&#xff1a;从流中提取数据&#xff0c;支持 >> 操作 这里字符串可以包括多个单词&#xff0c;单词之间使用空格分开 #include <iostream> #include <sstream> using namespace std; int main() {istringstream istr(&quo…

EXEC函数族的一般规律

事实上&#xff0c;只有execve是真正的系统调用&#xff0c;其它五个函数最终都调用execve&#xff0c;所以execve在man手册第2节&#xff0c;其它函数在man手册第3节。这些函数之间的关系如下图所示。

进程间通信的方法

Linux环境下&#xff0c;进程地址空间相互独立&#xff0c;每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程和进程之间不能相互访问&#xff0c;要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲区&#xff0c;进…

pipe函数

#include <unistd.h> int pipe(int pipefd[2]); 作用&#xff1a;创建管道 成功&#xff1a;0&#xff1b;失败&#xff1a;-1&#xff0c;设置errno 函数调用成功返回r/w两个文件描述符。无需open&#xff0c;但需手动close。规定&#xff1a;fd[0] …

mmap内存映射、system V共享内存和Posix共享内存

linux内核支持多种共享内存方式&#xff0c;如mmap内存映射&#xff0c;Posix共享内存&#xff0c;以system V共享内存。当内核空间和用户空间存在大量数据交互时&#xff0c;共享内存映射就成了这种情况下的不二选择。它能够最大限度的降低内核空间和用户空间之间的数据拷贝&a…

匿名映射

通过使用我们发现&#xff0c;使用映射区来完成文件读写操作十分方便&#xff0c;父子进程间通信也较容易。但缺陷是&#xff0c;每次创建映射区一定要依赖一个文件才能实现。通常为了建立映射区要open一个temp文件&#xff0c;创建好了再unlink、close掉&#xff0c;比较麻烦。…

信号的产生和状态

信号的产生&#xff1a;1.按键产生&#xff0c;如&#xff1a;Ctrlc&#xff08;内核向进程发送信号&#xff0c;杀死该进程&#xff09;、Ctrlz、Ctrl\&#xff1b;2.系统调用产生&#xff0c;如&#xff1a;kill、raise、abort&#xff1b;3.软件条件产生&#xff0c;如&…

【C++ Priemr | 15】虚函数常见问题

1. 在成员函数中调用虚函数&#xff1a; #include <iostream> using namespace std; class CBase { public:void func1(){func2();}virtual void func2() { cout << "CBase::func2()" << endl; } }; class CDerived : public CBase { public:virt…