彻底掌握Makeifle(三)

前言

在前面的文章彻底掌握Makefile(一)彻底掌握Makefile(二)当中,我们简要的介绍了一些常见的makefile使用方法,在本篇文章当中我们将继续介绍一些makefile当中的常见用法。

Makefile中与文件相关的函数

dir与notdir函数

file = ./files/a.c
fdir = $(dir $(file))
nfdir = $(notdir $(file)) main: demo.c
echo $(fdir)
echo $(nfdir)

dir函数主要书获取文件路径当中的目录部分,而notdir函数主要是获取文件路径当中文件名的部分,执行上面的makefile结果如下所示:

suffix函数

这个函数主要是用于获取文件的后缀名。

file = ./files/a.c
fdir = $(dir $(file))
nfdir = $(notdir $(file))
name = $(suffix $(file))
main: demo.c
echo $(fdir)
echo $(nfdir)
echo $(name)

上面的makefile执行结果如下下图 所示:

basename

这个函数用于获取文件路径当中除去后缀名的部分。

file = ./files/a.c
base = $(basename $(file))
main: demo.c
echo $(base)

addsuffix

这个函数主要是给文件加上后缀的。

file = ./files/a.c
base = $(addsuffix .c, $(file))
main: demo.c
echo $(base)

上面的代码执行结果如下:

上面的结果就表示在文件的末尾加上了对应的后缀名。

addprefix

这个函数的主要作用就是在字符串的前面加上一串字符。

file = files/a.c
base = $(addprefix ./src/main/, $(file))
main: demo.c
echo $(base)

上面的makefile执行结果如下图所示:

循环函数foreach

foreach函数的主要使用规则为:

$(foreach <var>,<list>,<text>)

我们直接使用一个例子来说明这个情况:

files = a.c b.c c.c d.c
new_files = $(foreach n, $(files), $(n)pp)
main: demo.c
echo $(new_files)

上面的makefile输出结果如下图所示:

foreach函数会将files当中的字符串先按照空格、tab键、回车换行符进行分割,然后将分割后的值一个一个的放入变量n当中,然后会产生一个字符串$(n)pp,最终将这些字符串通过空格拼接起来并且赋值给new_files,这才会有最终的结果。

上面的过程对应一个python代码如下所示:

call函数

call函数在makefile当中可以用于调用我们自定义的一个表达式,他的语法个数如下面所示:

$(call <expression>,<parm1>,<parm2>,...,<parmn>)
  • 表示定义的表达式的名字。
  • 表示第n个参数,我们在当中可以使用$(n)进行引用。

我们现在有一个需求就是将两个字符中间加上多个横杠,比如下面的makefile。

a=a.c
b=b.c
c=$(a)-------$(b)
main: demo.c
echo $(c)

上面的makefile执行结果如下图所示:

但是如果我们想要重复实现这个功能的话,我们就不需要每次都去写这样一个表达式,而是我们应该写一个表达式然后进行调用。

a=a.c
b=b.c
c=$(1)-------$(2) # 定义表达式c $(1) 表示使用第一个参数 $(2) 表示使用第二个参数
main: demo.c
echo $(call c, $(a), $(b)) # c 就是定义好的表达式 这里调用表达式c

上面的makefile输出结果和上面一样:

在makefile当中使用shell函数

我们在makefile的表达式当中可以使用shell的函数。

比如现在我们有一个文件叫做test.txt,文件的内容如下所示:

a.c b.c c.c d.c

我们的makefile内容如下:

content=$(shell cat test.txt) # 将shell命令的输出内容赋给content

main: demo.c
echo $(content) # 输出content

上面的makefile执行结果如下图所示:

origin函数

origin这个函数主要是返回变量的定义方式,使用格式如下:

$(origin <variable>) # 其中 variable 是变量名字 这里不需要使用 $ 符号去引用

这个函数的输出结果又下面这些值:

undefined

如果 <variable> 从来没有定义过,origin函数返回这个值 undefined

default

如果 <variable> 是一个默认的定义,比如“CC”这个变量。

GNU make默认变量:

  • AR-->归档维护程序的名称,默认值为ar
  • ARFLAGS-->归档维护程序的选项
  • AS-->汇编程序的名称,默认值为as
  • ASFLAGS-->汇编程序的选项
  • CC-->C编译器的名称,默认为gcc
  • CPP-->C预编译器的名称
  • CCFLAGS-->C编译器的选项
  • CPPFLAGS-->C预编译的选项
  • CXX-->C++编译器的名称,默认为g++
  • CXXFLAGS-->C++编译器的选项
  • FC-->FORTRAN编译器的名称,默认为f77
  • FFLAGS-->FORTRAN编译器的选项
environment

variable是一个环境变量。

file

如果 <variable> 这个变量被定义在Makefile中。

command line

如果 <variable> 这个变量是被命令行定义的。

override

如果 <variable> 是被override指示符重新定义的,关于override的使用,请查看本文彩蛋部分。

现在我们举一个例子,去看看上面这些值对应的例子:

override var = aaaa
file=file
main: demo.c
echo $(origin file) # makefile 内部定义的
echo $(origin data) # 命令行定义的
@echo $(origin var) # override 重写
@echo $(origin JAVA_HOME) # JAVA_HOME 是一个环境变量
@echo $(origin CXX) # 默认定义的变量

我们现在使用make命令测试一下上面的makefile输出结果:

error函数

在makefile当中我们可以使用error函数让makefie停止执行。当我们有需求:让在某种条件下让makefile停止编译

data=data

ifeq ($(data), data)
$(error "data == data")
endif main: main.c
gcc main.c

现在我们执行makefile,输出结果如下:

还有一个函数warning使用方法和上面一样用于产生警告。

彩蛋

@符号

有时候在makefile当中我们不想输出某些命令(如果不进行设置makefile会输出每一条我们执行过的命令),比如下面的makefile。

main: demo.c
echo hello world

上面的makefile输出结果为:

现在我们不想输出echo hello world这条命令,我们可以使用@进行修饰,在makefile当中如果一条命令使用@进行了修饰,那么这条命令就不会输出。

main: demo.c
@echo hello world

上面的makefile输出结果如下:

override使用

在使用make命令的时候可以进行变量的设定,这个变量我们可以在makefile文件当中使用:

main: demo.c
@echo $(var) # 使用变量 var

我们现在输入make命令并且指定参数然后查看结果:

可以看到我们指定的变量在makefile当中可以使用了。

但是如果在我们的makefile当中也有一个变量叫做var那么makefile当中的var就会被覆盖。比如像下面这个例子一样:

如果我们想让我们自己的变量起作用的话我们可以使用override:

总结

在本篇文章当中主要给大家介绍了Makefile当中一些常用的函数的使用,整体比较简单,大家可以对照着makefile和结果自己实现一遍。


以上就是本篇文章的所有内容了,我是LeHung,我们下期再见!!!更多精彩内容合集可访问项目:https://github.com/Chang-LeHung/CSCore

关注公众号:一无是处的研究僧,了解更多计算机(Java、Python、计算机系统基础、算法与数据结构)知识。

彻底掌握Makeifle(三)的更多相关文章

  1. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  2. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  3. Jquery的点击事件,三句代码完成全选事件

    先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  4. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  5. 简谈百度坐标反转至WGS84的三种思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...

  6. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  7. 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  8. 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

    一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...

  9. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率

    之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...

随机推荐

  1. Nginx配置解决NetCore的跨域

    使用Nginx配置解决NetCore的跨域 废话不多说,直接上Nginx配置 server { listen 80; server_name 你的Id或域名; location / { add_hea ...

  2. 作业二、安装CentOS7.9

    一.安装环境 1.VMware Workstation 16 Pro 2.CentOS7.9 二.部署系统 步骤1.进入VMware,点击创建新的虚拟机 步骤2.进入新建虚拟机向导,选择典型(推荐) ...

  3. 发明Linux的帕特里克

    Slackware Linux 是目前市场存活时间最长的 Linux 发行版之一,它基于一个叫做 SLS(Soft Landing Systems)的 Linux 项目而设计,易于使用和稳定. Sla ...

  4. CF1381B Unmerge(位运算的作用)

    题目大意: 给定长度为 \(2n\) 的排列 \(p\) .确定是否存在两个数组 \(a\) 和 \(b\) ,每个数组的长度都为 \(n\) ,并且没有相等的元素,使得 \(p = \operato ...

  5. 渲染优化中那些奇奇怪怪的rules

    禁⽌使⽤ iframe iframe 会阻塞主⻚⾯的 Onload 事件 搜索引擎的检索程序⽆法解读这种⻚⾯,不利于 SEO iframe 和主⻚⾯共享连接池,⽽浏览器对相同域的连接有限制,所以会影响 ...

  6. Odoo 14 升级模块后为什么template不生效?

    # 升级模块后为什么template不生效? # 直接原因是因为你在record标签的父级data标签标签中设置了noupdate为true.这就导致你后面无论你怎么修改data下面的子标签内容,都不 ...

  7. Frida使用文档(一)安装、启动、运行、关闭

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删!企鹅:1033383881 Frida使用 ...

  8. 理解vue中v-for循环中得key原理及一些错误

    作用:给节点做一个标识,相当于人类的身份证号,虚拟DOM中的标识 下列是key值的一些使用场景和带来的问题:   js:    const vm = new Vue({             el: ...

  9. 活动报名|对话贡献者:DolphinScheduler x Pulsar 在线 Meetup

    各位 DolphinScheduler 和 Pulsar 社区的小伙伴们,Apache DolphinScheduler x Pulsar 在线 Meetup 来啦! 导语 大数据任务调度.消息流的订 ...

  10. k8s驱逐篇(2)-kubelet节点压力驱逐

    kubelet节点压力驱逐 kubelet监控集群节点的 CPU.内存.磁盘空间和文件系统的inode 等资源,根据kubelet启动参数中的驱逐策略配置,当这些资源中的一个或者多个达到特定的消耗水平 ...