彻底掌握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. GDOI 2022 普及组游记

    To LuoguDAY -1 期中考成绩下来了,全无了除了历史 (96) 和生物 (95) 还能看,剩下的-,语文 101.5 ,少错一道选择和断句就 107.5 了,居然比雌兔还低 数学少错一道选择 ...

  2. Codeforces Round #801 (Div. 2) and EPIC Institute of Technology Round(C,D题解)

    Codeforces Round #801 (Div. 2) and EPIC Institute of Technology Round C - Zero Path 在这道题目中,不可以真正地进行寻 ...

  3. Sharding-jdbc + Seata + Nacos整合

    前置条件 先了解Sharding-jdbc.Seata.Nacos这三样东西各自的作用以及单独使用时的配置. 整合代码已放在github,详细步骤章节请搭配此项目看,欢迎start 思路 如果已经做过 ...

  4. js for和while两种99乘法表

    <script type="text/javascript"> for(var i=1; i<=9; i++) { for(var j=1; j<=i;j+ ...

  5. Python 支付宝红包二维码制作步骤分享

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! 支付宝红包二维码制作步骤分享 2022. ...

  6. 查找默认安装的python路径,并输出到 FindPythonPathX_output.txt

    在python程序设计教学中,在汉化IDEL时.为PyCharm项目设置解释器时,经常需要查找python安装路径.对老手来说很简单,但对很多刚开始学习编程的学生来说,则很困难.所以,编写了一个批处理 ...

  7. ETCD快速入门-02 ETCD安装

    2.ETCD安装     etcd 安装可以通过源码构建也可以使用官方构建的二进制文件进行安装.我们以二进制文件为例,系统为CentOS 7.9,操作步骤如下所示: 2.1 Linux ETCD_VE ...

  8. 巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09

    流程结构就是指程序逻辑到底怎么执行,进而言之,程序执行逻辑的顺序.众所周知,程序整体都是自上由下执行的,但有的时候,又不仅仅是从上往下执行那么简单,大体上,Go lang程序的流程控制结构一共有三种: ...

  9. Linux —用户和组

    Linux 用户和组 1.用户和组的概念 用户的作用: Authentication:认证 Authorization:授权 Accouting:审计 用户存在的最终目的: 为了实现资源的分派 组的作 ...

  10. redis-hash命令

    一.HDEL key field [field ...] 从 key 指定的哈希集中移除指定的域.在哈希集中不存在的域将被忽略. 如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将 ...