makefile中的shell调用---注意事项

在之前一次编写makfile时候,有看到相关的makefile中使用$$来引用变量,而且尝试后发现$$使用居然和${}有类似的功能。当时也没具体追究相关的用法,当然刚才所说的都是错误的观念


$$:在makefile中会被替换成一个$。

    相关资料是这么描述的:makefile中变量在声明时需要赋予初值,在使用时,需要在使用的变量前加"$"符号,但是最好使用"()"或者"{}"将变量包括起来。如果想使用真实的"$"符号,需要用"$$"来表示


在makefile中使用shell:

1. 使用makefile中的$(shell ...) eg:CUR_DIR=$(shell pwd)

2. 直接使用shell。在此有几点需要注意的:

  • shell命令必须是在规则里面(可以参考以下例1)
  • shell命令在makefile调用时候每行shell都是一个单独的进程。上一行定义的变量在下一行是无效的(参考例2)
  • makefile调用shell时候(其实在执行时候都会有这个动作,不光光是shell),会对变量进行替换:如果是makefile中定义的变量(使用$()来引用的)会被替换成变量的值;如果是$$符号,会替换成$。然后传给shell来执行

--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------

以下内容转自:Makefile与Shell的问题

大概只要知道Makefile的人,都知道Makefile可以调用Shell脚本。但是在实际使用时,并不那么简单,一些模棱两可的地方可能会让你抓狂。你若不信,可以先看几个例子,想象一下这些这些例子会打印什么内容,记下你想象的结果,然后在计算机上运行这些例子,对照看一下。

 

示例一:

if [ "$(BUILD)" = "debug" ]; then  echo "build debug"; else echo "build release"; fi

all:

    echo "done"

示例二:

all:

    @CC=arm-linux-gcc

    @echo $(CC)

示例三:

CC=arm-linux-gcc

all:

    @echo $(CC)

示例四:

SUBDIR=src example

all:

    @for subdir in $(SUBDIR); /

    do/

        echo "building " $(subdir); /

    done

 

 

说明:

1.         Shell脚本在target里才有效,其它地方都被忽略掉了。所以示例一中,”build debug”之类的字符串根本打印不出来。示例一的正确写法是:

示例一:

all:

    if [ "$(BUILD)" = "debug" ]; then  echo "build debug"; else echo "build release"; fi

    echo "done"

 

2.         make把每一行Shell脚本当作一个独立的单元,它们在单独的进程中运行。示例二中,两行Shell脚本在两个莫不相干的进程里运行,第一个进程把CC设置为arm-linux-gcc,第二个进程是不知道的,所以打印的结果自然不是arm-linux-gcc了。示例二的正确写法是:

示例二:

all:

    @CC=arm-linux-gcc; echo $(CC)

或者:

all:

@CC=arm-linux-gcc; /

echo $(CC)

 

3.         make在调用Shell之前先进行预处理,即展开所有Makefile的变量和函数。这些变量和函数都以$开头。示例三中,Shell拿的脚本实际上是echo arm-linux-gcc,所以打印结果正确。

 

4.         make预处理时,所有以$开头的,它都不会放过。要想引用Shell自己的变量,应该以$$开头。另外要注意,Shell自己的变量是不需要括号的。示例四的正确写法是:

示例四:

SUBDIR=src example

all:

    @for subdir in $(SUBDIR); /

    do/

        echo "building " $$subdir; /

    done

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

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

相关文章

网络基础2(分层模型,通信过程,以太网,ARP协议格式和具体功能详解)

分层模型 OSI七层模型 OSI模型 1 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0&#…

为github帐号添加SSH keys

使用git clone命令从github上同步github上的代码库时,如果使用SSH链接(如我自己的beagleOS项目:gitgithub.com:DamonDeng/beagleOS.git),而你的SSH key没有添加到github帐号设置中,系统会报下面的错误&…

网络基础3(IP段格式,UDP数据报格式,TCP数据报格式)

IP段格式 IP数据报的首部长度和数据长度都是可变长的,但总是4字节的整数倍。 对于IPv4,4位版本字段是4。4位首部长度的数值是以4字节为单位的,最小值为5,也就是说首部长度最小是4x520字节,也就是不带任何选项的IP首部…

Linux 开发路线

Linux 开发路线: 使用 linux—〉linxu 系统编程开发---〉驱动开发和分析 linux 内核 开始学 linux 内核:最好有三件宝物:《深入理解 linux 内核》《LINUX内核源代码情景分析》和源代码。 《深》是纲,《情》是目。最后深入代码 Linux 内核原理:比较浅显…

堆的应用(堆排序,TopK问题)

堆的应用 1)排序 堆排序 选择排序 既可以找到最大的放在最后 也可以找到最小的方最前 但是,堆排序不能找最小的放在最前 因为把最小数放在最前,会破坏掉堆的原来的顺序,除非重新建堆 1, 2,9&#xff0c…

有名管道和无名管道的区别

1)无名管道:管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。 单独构成一种独立的文件系统:管道…

网络基础4(TCP三次握手,四次握手,TCP流量控制,TCP状态转换 , TCP异常断开,设置TCP属性,端口复用)

TCP协议 TCP通信时序 下图是一次TCP通讯的时序图。TCP连接建立断开。包含大家熟知的三次握手和四次握手。 TCP通讯时序 在这个例子中,首先客户端主动发起连接、发送请求,然后服务器端响应请求,然后客户端主动关闭连接。 两条竖线表示通讯的…

linux编程手册读书笔记第一章(20140329)

(2)管道、FIFO、套接字、设备(比如终端、伪终端)都支持非阻塞模式。(因为无法通过open()来获取管道和套接字的文件描述符。所以要启用非阻塞标志,就必须使用fcntl(&#…

排序(基本概念及分类,直接插入排序和希尔排序)

排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序&a…

Linux编程手册读书笔记第二章(20140330)

内核:管理和分配计算机资源(即CPU、RAM和设备)的核心软件层Linux内核可执行文件采用/boot/vmlinuz或类似的路径名,“z”表明内核是经过压缩的可执行文件。内核主要任务: (1&#xff…

直接交换排序

直接交换排序 缺点:进行一些重复性比较,解决放法:堆排序 选择排序优化 //如果当前的数大于假定最大的数 //改变下标 //如果当前的数小于假定最小的数 //改变下标 //遍历数组跳到下一个元素 //如果最大的数没有在它的位置上 //交换 //交换…

Linux编程手册读书笔记第三章(20140407)

外壳函数执行一条中断机器指令(int 0x80),引发处理器从用户态切换到核心态,并执行系统中断0x80的中断矢量所指向的代码。(在2.6内核及glib 2.3.2之后的版本都支持sysenter指令,进入内核的速度更快&#xff…

Linux编程手册读书笔记第四章(20140407)

标准文件描述符定义在<unistd.h>中&#xff0c;STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO打开一个文件&#xff1a;open&#xff08;&#xff09; &#xff03;include<sys/stat.h> #include<fcntl.h> int open(const char *pathname, int flags, …/* …

快速排序概念及实现

快速排序 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c; 其基本思想为&#xff1a; 任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右子序列…

Linux编程手册读书笔记第五章(20140408)

改变已打开文件性质&#xff1a;fcntl&#xff08;&#xff09; #include<fcntl.h> int fcntl(int fd, int cmd, …); (1) 调用失败返回&#xff0d;1 &#xff08;2&#xff09;fcntl函数有5种功能&#xff1a; a. 复制一个现有的描述符&#xff08;cmd&#xff1d;F_D…

归并排序概念及其实现

基本思想&#xff1a; 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个…

##连接符和#符的使用

C语言中如何使用宏C&#xff08;和C&#xff09;中的宏&#xff08;Macro&#xff09;属于编译器预处理的范畴&#xff0c;属于编译期概念&#xff08;而非运行期概念&#xff09;。下面对常遇到的宏的使用问题做了简单总结。 关于#和## 在C语言的宏中&#xff0c;#的功能是将其…

计数排序和基数排序

适用于数据集中在某个范围中&#xff0c; //统计每个数据出现的次数 计数排序&#xff1a;鸽巢原理 1找范围 2给空间 3记次数 4回收 for(int i 0;i<size; i) {temp[array[i]]; }for(int i0;i<range;i&#xff09;{while(temp[i])array[index]i;}代码实现 时间复杂度&…

信号量sem_wait()的使用

闲来无事&#xff0c;我给大家讲下UNIX/Linux下信号量函数的使用。首先你得知道什么叫信号量&#xff0c;什么时候要用信号量。这个嘛&#xff0c;主要就是用来保护共享资源的&#xff0c;也就是说如果你想限制某个&#xff08;些&#xff09;资源在同一时刻只能有一&#xff0…

C++起始(关键字,命名空间,缺省参数,函数重载(c语言为什么不支持函数重载))

1. C关键字(C98) 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用 域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c;以避免命名冲突或名字污…