Makefile调用shell应该注意的地方

转载:http://blog.csdn.net/ninlei0115/article/details/9732191

1、在Makefile中只能在target中调用Shell脚本,其他地方是不能输出的。比如如下代码就是没有任何输出:

VAR="Hello"
echo "$VAR"

all:
   .....

以上代码任何时候都不会输出,没有在target内,如果上述代码改为如下:

VAR="Hello"

all:
    echo "$VAR"
    .....

以上代码,在make all的时候将会执行echo命令。

2、在Makefile中执行shell命令,一行创建一个进程来执行。这也是为什么很多Makefile中有很多行的末尾都是“;  \”,以此来保证代码是一行而不是多行,这样Makefile可以在一个进程中执行,例如:

SUBDIR=src example
all:
    @for subdir in $(SUBDIR);     do        echo "building ";     done

上述可以看出for循环中每行都是以”; \”结尾的。

3、Makefile中所有以$打头的单词都会被解释成Makefile中的变量。如果你需要调用shell中的变量(或者正则表达式中锚定句位$),都需要加两个$符号($$)。实例如下:

PATH="/data/"

all:
    echo ${PATH}
    echo $$PATH

例子中的第一个${PATH}引用的是Makefile中的变量,而不是shell中的PATH环境变量,后者引用的事Shell中的PATH环境变量。

以上三点的是Makefile调用shell应该注意的地方,写Makefile一定要注意。

在Makefile中使用$$

落鹤生 发布于 2012-12-16 17:15 点击:323次 

来自:CSDN博客 原文

不要认为在makefile的规则的命令行中使用$var就是将makefile的变量和shell共享了, 这里仅仅是读取makefile的变量然后扩展开,将其值作为参数传给了一个shell命令。而$$var是在访问一个shell命令内定义的变量,而非 makefile的变量。

TAG: Shell  Makefile

在makefile中,会经常使用shell命令,也经常见到$var 和
$$var的情况,有什么区别呢,区别大了。不要认为在makefile的规则的命令行中使用$var就是将makefile的变量和shell共享了,

这里仅仅是读取makefile的变量然后扩展开,将其值作为参数传给了一个shell命令。而$$var是在访问一个shell命令内定义的变量,而非

makefile的变量。此外,如果某规则有n个shell命令行构成,而相互之间没有用‘;‘和‘\‘连接起来的话,就是相互之间没有关联的shell
命令,相互之间也不能变量共享。看如下例子:

makefile代码段1:
VAR=3   
target: prerequsite1 prerequsite2
    echo $VAR      (1)
    VAR=4           (2)
    echo $VAR         (3)
    echo $$VAR         (4)

在代码段1中,(1)的结果是3,显然makefile利用自己的变量将$VAR扩展成3之后传递给这个echo这个shell命令。
    (2)中,是一个独立的shell命令自己第一了一个shell变量,名字也叫VAR,且其值为4,不会影响到makefile中的VAR。
    (3)中,同(1),makefile中的变量VAR的值依然是3
    (4)makefile将$$VAR先执行一次扩展得到如下shell命令:
    echo $VAR然后交给shell去解释执行,可是对于这个shell命令来说VAR是一个为定义的变量,因此输出的结果就是个空行。

makefile代码段2:
VAR=3   
target: prerequsite1 prerequsite2
    echo $VAR;\      (1‘)
    VAR=4;\           (2‘)
    echo $VAR;\         (3‘)
    echo $$VAR         (4‘)
    
    在代码段2中,所有的shell命令都被连接起来了,那么执行的结果就有变化了:
    (1‘)结果同(1),$VAR被替换成了3
    (2‘)结果同(2)
    (3‘)输出3,因为虽然shell中有VAR变量,可是makefile先要进行扩展,扩展的结果就是echo 3。
    (4‘)输出4,因为makefile扩展结果为echo $VAR,而shell中已经有了变量VAR,且其值为4.

类似的例子还有如下:
    makefile代码片断3:
    SUBDIRS=tools examples src
    target: prerequsite1 prerequsite2
       for dir in $SUBDIRS; do $(MAKE) -C $$dir;done
    
    make首先将这个命令扩展成:
    for dir in tools examples src; do make -C $dir; done
  然后交给shell解释执行,可见dir就是一个shell中的变量。

总之,在makefile的shell命令中,党要引用shell变量的时候,要使用$$VAR格式。

此外注意一点,在makefile中,$$还被用来做SECONDEXPANSION,即二次扩展,一般是作为prerequsites.
    如:
    .SECONDEXPANSION (要使用这个feature就的加上这一行)
    main_objs := main.o try.o test.o
    lib_objs := lib.o api.o
    main lib:   $$([email protected]_objs)

$$([email protected]_objs)第一阶段的扩展结果为$([email protected]_objs),第2阶段的扩展结果为:[email protected]被替换为main
lib,与_objs连接成main_objs lib_objs。加上外面$的扩展,就是$main_objs
$lib_objs,最终结果为main.o try.o test.o lib.o api.o

(ace_fei)

Makefile调用shell应该注意的地方,布布扣,bubuko.com

时间: 2024-10-06 00:59:59

Makefile调用shell应该注意的地方的相关文章

[转] Makefile中调用Shell

1.在Makefile中只能在target中调用Shell脚本,其他地方是不能输出的.比如如下代码就是没有任何输出: VAR="Hello" echo "$(VAR)" all: ..... 以上代码任何时候都不会输出,没有在target内,如果上述代码改为如下: VAR="Hello" all: echo "$(VAR)" ..... 以上代码,在make all的时候将会执行echo命令. 最后打印结果是: echo &q

JAVA调用Shell脚本

在实际项目中,Java有时候需要调用C写出来的东西,除了JNI以外,我认为一种比较好的方法是JAVA调用Shell.先把C写出来的make成可执行文件,然后再写一个shell脚本执行该可执行文件,最后是JAVA调用该shell脚本. JAVA调用很简单,例子如下: 首先是shell脚本 [plain] view plain copy print? #!/bin/sh echo Begin word cluster /home/felven/word2vec/word2vec -train /ho

Python 调用 shell 命令的模块总结

os.system('cat /proc/cpuinfo') 阻塞,返回shell执行参数命令的状态,即成功返回0 os.popen('cat /proc/cpuinfo') 阻塞,返回file read的对象,对该对象进行 read() 可以获取shell执行参数命令的结果,即标准输出 commands.getstatus('/proc/cputinfo') 阻塞,返回参数指定的系统文件的详细属性 commands.getoutput('cat /proc/cpuinfo') 阻塞,返回she

java调用shell脚本,并获得结果集的例子

/** * 运行shell脚本 * @param shell 需要运行的shell脚本 */ public static void execShell(String shell){ try { Runtime rt = Runtime.getRuntime(); rt.exec(shell); } catch (Exception e) { e.printStackTrace(); } } /** * 运行shell * * @param shStr * 需要执行的shell * @return

在android程序中调用shell命令与脚本

最近做android的一个功能就是调用shell命令来进行一些系统级别的操作,比如说是关机开机之类的,现在总结一下具体的用法以及遇到的坑(基于我所用到的,没用到的我就不说了) (1) Runtime.getRuntime().exec("ls"); 这是最简单的一种,你输入后就能就会执行ls命令,如果要获得输出的话可以这样写 Process p = Runtime.getRuntime().exec("ls"); String data = null; Buffer

Java代码调用Shell脚本并传入参数实现DB2数据库表导出到文件

本文通过Java代码调用Shell脚本并传入参数实现DB2数据库表导出到文件,代码如下: import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.HashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import

通过ant调用shell脚本执行adb命令

在Hudson或者Jenkins中利用ant的exec 来调用shell命令,通过shell脚本来执行adb shell命令,可以正常执行,不会出现在ant中直接调用adb shell出现的假死情况. 其中shell 脚本也很简单 #!/bin/sh adb root adb shell chmod 777 /system/data/lib adb shell ./system/data/lib/helloworld 可以执行手机端中的程序进行测试.

java连接ssh调用shell

首先在远程服务器上编写一个测试脚本test.sh,并赋予可执行权限:chmod +x test.sh #!/bin/bash   echo 'test22'   echo $1 $1是脚本传进来的第一个参数,我们控制台打印一下这个参数 新建maven项目,添加依赖: <dependency>       <groupId>org.jvnet.hudson</groupId>       <artifactId>ganymed-ssh2</artifac

Android调用shell命令时间系统时间的修改

============问题描述============ Android怎么调用shell命令来修改系统时间啊,用代码的 ============解决方案1============ Process process = Runtime.getRuntime().exec("su"); String datetime = "20131023.112800"; // 测试的设置的时间[时间格式 // yyyyMMdd.HHmmss] DataOutputStream os