Makefile的入门学习

一、Makefile的入门学习

编译工具及构建工具介绍

在之前的课程,都是直接使用gcc对代码进行编译,这对简单的工程是可以的,但当我们遇到复杂的工程时,每次用gcc等编译工具去操作就会显得很低效。因此make工具就出现了, make的出现是为了解决手动编译和链接大型工程的问题,它可以避免重复的工作,提高效率,保证正确性。make工具就根据makefile中的命令进行编译和链接的。但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改,因此更高级的一些构建系统或者工具工具像cmake、qmake、ninja和auto make就出现了,它们可以根据一些配置文件来自动化编译和链接软件项目。

在这里插入图片描述

  • cmake是一个跨平台的构建系统,它可以根据CMakeLists.txt中的指令来生成不同平台和工具的工程文件,例如Makefile、Visual Studio解决方案、Ninja文件等。cmake可以支持多种语言和多种架构,它还提供了一些高级功能,如测试、打包、安装等。
  • qmake是一个用于Qt项目的构建系统,它可以根据.pro或.pri中的指令来生成Makefile或其他形式的工程文件。
  • ninja是一个小巧而快速的构建工具,它可以根据ninja.build中的规则来执行编译和链接命令。ninja主要关注于性能和效率,它可以利用多核处理器和并行处理来加速构建过程。ninja通常不需要用户直接编写配置文件,而是由其他构建系统(如cmake)来生成。
  • auto make是一个用于生成Makefile.in文件的工具,Makefile.in是一种用于auto conf的配置文件格式,auto conf是一个用于生成configure脚本的工具。configure脚本是一个用于检测系统环境并生成最终的Makefile文件的脚本Makefile.am是一种用于auto make的配置文件格式,它包含了一些指令和变量,用于定义程序或库的源文件、目标文件、依赖关系和编译选项等。
  • make是一个经典而通用的构建工具,它可以根据Makefile中的规则来执行编译和链接命令。make可以支持多种平台和工具,它还提供了一些高级功能,如条件判断、函数调用、模式匹配。

二.Makefile的简单讲解

  1. 编译的四个阶段

    回顾下编译的四个过程:预处理(Pre-Processing)、编译(Compiling)、汇编 (Assembliang)、链接(Linking)。

    在这里插入图片描述

  2. Makefile的规则

    TARGET....: prerequisites...
    <tab缩进>command
    <tab缩进>...
    <tab缩进>...
    

    TARGET 也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签( Label),对于标签这种特性,在后续的讲“伪目标”中会有叙述。prerequisites 就是,要生成那个 target 所需要的文件或是目标。command 也就是 make 需要执行的任意shell命令。

    Makefile一个示例:

    #这是一个Makefile
    debug:
    	@echo "hello world"
    

    Makefile采用#进行一行注释,采用\作为续行符。make后,打印hello world@的作用是不打印echo指令本身。

    如果,我们要编译下面这个最简单的例子:

    #include <stdio.h>
    int main(int argc, char *argv[])
    {
    	printf("hello world!\n");
    	return 0
    }
    

    Makefile修改如下:

    debug :
    	@echo "hello world"
    
    hello :
    	gcc -o hello hello.c
    
    clean :
    	@rm -f hello
    
    .PHONY: clean
    

    在终端只输入make,执行第一个命令即make debugmake hello相当于在终端输入gcc -o hello hello.c,同理make clean相当于在终端输入rm -f hello

    .PHONY伪目标,如果一个目标和一个实际文件同名,那么make会认为该目标已经是最新的,不需要重新生成,也不会执行其命令。通过将目标声明为伪目标,可以避免这种情况,强制执行其命令。

  3. 变量赋值和预定义变量

    Makefile中的变量赋值运算符有四种,分别是=:=?=+=

    • = 表示延迟展开赋值,即变量的值是在使用时才确定,可能会受到后面的赋值影响。
    • := 表示直接赋值,即变量的值是在定义时就确定,不会受到后面的赋值影响。
    • ?= 表示条件赋值,即只有当变量没有被赋值时,才使用等号后面的值作为变量的值。
    • += 表示追加赋值,即将等号后面的值追加到变量原来的值之后,形成一个新的值。
    • $@ 表示生成的目标文件;$^ 表示所有的依赖文件;$< 代表第一个依赖文件。

    示例:

    TARGET = hello
    CC := gcc
    TARGET1 := $(CC) $(TARGET)#'='为延迟赋值 ':='为立即赋值
    CC ?= g++# "?=" 表示如果前面没有定义CC,就定义为g++,如果定义了CC,就不定义了
    CC += -g#'+='为追加。在CC后面追加-g
    
    $(TARGET): hello.c
    	$(CC) -o $@ $^
    
    compile: $(TARGET)
    
    clean:
    	@rm -rf $(TARGET_DIR)
    
    .PHONY: clean compile
    

    make compile编译的结果为gcc -g -o hello hello.c

三.Makefile的一些常见函数

Makefile函数的基本格式是: ( ) 或者是 ( )或者是 ()或者是{ },其中,是函数名,是函数的参数,参数之间要用逗号分隔开,参数和函数名之间使用空格分开。调用函数的时候要使用字符“$”,后面可以跟小括号或者大括号。

  1. wildcard 通配符

    Makefile中的wildcard 是一个函数,用于扩展通配符,返回与通配符匹配的文件列表。通配符是一种特殊的字符,可以表示多个文件名或目录名,常见的通配符有 * 和 ?,分别表示任意长度的任意字符和单个任意字符。格式如下:

    #格式:$(wildcard argments)
    #示例:
    SRC = $(wildcard src/*.c)
    #SRC赋值为src目录中的所有.c文件
    
  2. shell

    shell为在终端执行后面的命令并返回结果。

    #格式:$(shell <cmd> <args>)
    #示例:
    SRC = $(shell find . -name *.c)
    #找到当前文件下的所有.c文件
    
  3. patsubst替换函数

    #格式:$(patsubst pattern,replacement,text)
    #`patsubst`将text中的pattern全部替换为replacement,pattern和replacement可以包含%通配符。
    #示例:
    SRC = $(wildcard src/*.c)
    OBJ = $(patsubst %.c,%.o,$(SRC))
    #将SRC中的所有.c文件替换为.o文件
    
  4. subst替换函数

    #格式:$(subst from,to,text)
    #subst和patsubst类似,是将text中的from替换为to,并返回修改后的字符串。
    #示例:
    $(subst ee,EE,feet on the street)
    #返回结果:fEEt on the strEEt
    
  5. dir

    #格式:$(dir NAMES...)
    #dir函数是一个用于从文件名序列中提取目录部分的函数。
    #示例:
    SRC = $(wildcard ./src/*.c)
    OBJ = $(subst .c,,$(SRC))
    TARGET := $(patsubst ./src/%,./obj/%,$(subst .c,,$(SRC)))
    TARGET_DIR = $(dir $(TARGET))
    #SRC为src目录下的所有.c文件,OBJ为将SRC的结果去掉.c,TARGET将OBJ的结果的目录从src变为obj,最后通过TARGET_DIR得到TARGET中的目录,即:./obj/
    
  6. suffix

    #格式:$(suffix <names...>)
    #suffix为从文件名序列中取出各个文件名的后缀,返回文件名序列的后缀序列,如果文件没有后缀,则返回空子串。
    #示例:
    $(suffix ./src/foo.c ./src-1.0/bar.c hacks)
    #返回结果:.c .c
    
  7. basename

    #格式:$(basename <names...>)
    #从文件名序列中取出各个文件名的前缀部分,返回文件名序列的前缀序列,如果文件没有前缀,则返回空字串。
    #示例:
    $(basename ./src/foo.c ./src-1.0/bar.c hacks)
    #返回结果:./src/foo ./src-1.0/bar hacks
    
  8. addsuffix

    #格式:$(addsuffix <suffix>,<names...>)
    #把后缀加到每个单词后面,返回加过后缀的文件名序列。
    #示例:
    $(addsuffix .c,foo bar)
    #返回结果:foo.c bar.c
    
  9. addprefix

    #格式:$(addprefix <prefix>,<names...>)
    #把后缀加到每个单词后面,返回加过后缀的文件名序列。
    #示例:
    $(addprefix src/,foo bar)
    #返回结果:src/foo src/bar
    
  10. foreach循环函数

    #格式:$(foreach <var>,<list>,<text>)
    #把list中使用空格分割的单词依次取出并赋值给变量var, 然后执行text表达式。
    #示例:
    #$(I_FLAGS)可以-I包含INCLUDE里的库
    INCLUDE = /usr/inclue \
    			/usr/local/inclue
    I_FLAGS := $(foreach var,$(INCLUDE),-I$(var))
    @echo $(I_FLAGS)
    #输出结果:-I/usr/include -I/usr/local/include
    
  11. 条件判断

    • ifeq/ifneq语句:

      #ifeq语句:判断参数是否相等,相等为true,否则是false。
      ifeq (arg1, arg2)
          #arg1 arg2 相等执行这里的语句
      else
          #arg1 arg2 不相等执行这里的语句
      endif
      
      #ifneq语句:判断参数是否不等,不等为true,否则为false。
      ifneq (arg1, arg2)
          #arg1 arg2 不相等执行这里的语句
      else
          #arg1 arg2 相等执行这里的语句
      endif
      
    • ifdef/ifndef语句:

      #ifdef语句:判断参数是否有值,有值为true,否则是false。
      ifdef var
          #如果定义了var,执行这里的内容
      else
          #如果没定义var,执行这里的内容
      endif
      
      #ifndef:判断参数是否没有值,没有值为true,否则为false。
      infdef var
          #如果没定义var,执行这里的内容
      else
          #如果定义var,执行这里的内容
      endif
      

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL之主从复制

一&#xff0c;安装MYSQL&#xff0c;两台 二&#xff0c;配置master服务器 vim /etc/my.cnf 在mysqld模块下加入 server-id133 #配置server-id&#xff0c;让主服务器有唯一ID号&#xff08;让从服务器知道 他的主服务器是谁&#xff09;,建议使用ip最后3位 log-binmysql-bi…

coze扣子自定义插件开发

之前用过阿里云的&#xff0c;阿里云的插件填写的内容有点复杂 今天体验coze&#xff0c;没想到如此简单&#xff1b; 访问地址&#xff1a;扣子&#xff0c;注册对应账户&#xff0c;并创建对应空间&#xff1b; 第一步&#xff1a;点击插件&#xff0c;新建插件 选择不需要…

OpenHarmony嵌套类对象属性变化:@Observed装饰器和@ObjectLink装饰器

上文所述的装饰器仅能观察到第一层的变化&#xff0c;但是在实际应用开发中&#xff0c;应用会根据开发需要&#xff0c;封装自己的数据模型。对于多层嵌套的情况&#xff0c;比如二维数组&#xff0c;或者数组项class&#xff0c;或者class的属性是class&#xff0c;他们的第二…

代码随想录算法训练营第四十八天 | 70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数

70. 爬楼梯 &#xff08;进阶&#xff09; 代码随想录 解题思路 1.确定dp数组以及下标的含义 dp[i]&#xff1a;爬到有i个台阶的楼顶&#xff0c;有dp[i]种方法 2.递推公式 dp[j] dp[j - nums[i] ] 装满背包有多少种方法一般用这个 3.遍历顺序 完全背包&#xff0c;且…

Java面试——中间件

OpenFeign 1、openFeign是一个HTTP客户端&#xff0c;它融合了springmvc的注解&#xff0c;使之可以用REST风格的映射来请求转发。 2、可以把openFegin理解为是controller层或是service层。可以取代springmvc控制层作为请求映射&#xff0c;亦或是作为service层处理逻辑&#…

《网络安全技术 生成式人工智能服务安全基本要求》征求意见稿

1. 训练数据安全要求 &#xff08;1&#xff09;数据来源安全&#xff1a; 采集来源管理&#xff1a; 采集数据前应进行安全评估&#xff0c;含违法不良信息超过5%的数据源不得使用。 采集后需核验&#xff0c;含违法不良信息超过5%的数据不得用于训练。 不同来源训练数据搭…

kafka-集群-主题创建

文章目录 1、集群主题创建1.1、查看 efak1.2、创建 主题 my_topic1 并建立6个分区并给每个分区建立3个副本1.2.1、查看 my_topic1 的详细信息 1.3、停止 kafka-01实例&#xff0c;端口号为 9095 1、集群主题创建 1.1、查看 efak 已经有三个kafka实例 1.2、创建 主题 my_topic1…

C语言(数据存储)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…

windows上安装jdk1.8

这篇文章详细地介绍如何在windows上安装jdk1.8 目录 准备工作 第一步 第二步 第三步 第四步 第五步 最后的效果 查看JDK版本 准备工作 下载jdk&#xff1a;通过官网或者以下百度网盘链接下载jdk1.8 链接&#xff1a;https://pan.baidu.com/s/1zuMl0B-S6SDgiu1evw-IPQ?…

React useContext源码分析

React 框架中 useContext Hook 用于数据的传递&#xff0c;组件的数据传递有几种方式&#xff0c;通过 props、状态管理 和 useContext。本文将讲述useContext 在 React 是如何工作的&#xff0c;创建一个简单的 Context 例子并根据源码进行 Debug&#xff1a; 创建 context …

subline text3安装numpy,scipy,matplotlib,pandas,sklearn,ipynb

1&#xff0c;numpy&#xff08;基础数值算法&#xff09; 安装&#xff0c;要是在cmd直接安装到最后会报错, import numpy as np ModuleNotFoundError: No module named numpy 直接进入python环境&#xff0c;输入python -m pip install numpy就不会报错…

《科技与健康》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《科技与健康》期刊万方网可查吗 答&#xff1a;万方、维普可查 问&#xff1a;《科技与健康》是正规期刊吗&#xff1f; 答&#xff1a;万方维普收录的正规期刊。主管单位&#xff1a;长江出版传媒股份有限公司 主办单位&#xff1a;湖北科学技术…

调用阿里云智能云实现垃圾分类

目录 1. 作者介绍2. API3. 阿里云API垃圾分类业务4. 实验过程4.1 接入阿里云4.2 创建并获取AccessKey ID和Secret4.3 登录阿里云官网&#xff0c;搜索垃圾分类技术文档4.4 配置环境变量4.5 代码部分 1. 作者介绍 孙作正&#xff0c;男&#xff0c;西安工程大学电子信息学院&am…

【计算机毕设】基于SpringBoot的图书进销存管理系统设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 本研究旨在设计并实现一款基于SpringBoot的图书进销存管理系统&#xff0c;旨在解决图书馆或书店在图书采购、销售和库存管理等方面的问题&#xff…

扩散模型的技术原理和应用价值

引言 一、扩散模型的基本概念 扩散模型(Diffusion Models)是一种基于概率论的生成模型&#xff0c;最初源自物理学中的扩散过程理论&#xff0c;比如墨水在水中的扩散过程。在机器学习领域&#xff0c;这一概念被创造性地应用于数据生成任务&#xff0c;特别是图像和声音的合成…

文件上传题目练习

[HNCTF 2022 Week1]easy_upload 先尝试上传一个php文件&#xff0c;发现直接就成功了 用蚁剑测试连接成功 找到flag [NISACTF 2022]bingdundun~ 白名单上传 这里因为尝试了很多绕过方式都不成功&#xff0c;去搜索了一下wp&#xff0c;发现要用到Phar://伪协议 补充&#xff…

Overleaf(Latex)论文里插入高清matlab图像,亲测有效!!

如何在论文里插入高清的实验结果是个令人头疼的问题&#xff0c;这里以overleaf对matlab结果为例进行了测试&#xff0c;亲测有效。 在matlab图像结果的左上角选择"文件"->“导出设置” 选择“渲染”&#xff0c;分辨率调至600&#xff1b; 字体和线条粗细视个人…

聊聊限流的一些事儿

一、背景 最近几年&#xff0c;随着微服务的流行&#xff0c;服务与服务之间依赖越来越强&#xff0c;调用也越来越复杂&#xff0c;服务间的稳定性变突显出来。特别是在遇到突发请求时&#xff0c;常常需要通过缓存、限流、熔断降级、负载均衡等多种方式保证服务的稳定性。其…

PhpSpreadsheet表格导出

个人笔记记录 使用PhpSpreadsheet 导出excel。 多重表头生成excel 表 //读取数据库public function demo1(){// 连接spc数据库$config Config::get(databaseedc);$db Db::connect($config);$data $db->name("xxxx")->alias(a)->field(main_header, sub_…

【LeetCode算法】第108题:将有序数组转换为二叉搜索树

目录 一、题目描述 二、初次解答 三、官方解法 四、总结 一、题目描述 二、初次解答 1. 思路&#xff1a;由于数组nums是递增的&#xff0c;采用二分查找法来构造平衡二叉搜索树。首先&#xff0c;选择nums的中间结点作为根节点&#xff0c;然后将左部分的中间值作为左子树…