从外部覆盖make的命令

时间:2018-07-07 12:46:54

标签: bash makefile override cat ar

我有几个带有文件stamp1.txt和stamp0.txt的目录,我想覆盖cat命令。例如,我需要它来禁止将“ stamp1”文件存档到库中。

所以我写了一个名为“ realname”的小过滤程序和bash脚本来覆盖原始的cat命令。

function cat() { 

    local e=""

    for s in $@
    do
        if realname $s; then
            e=$e" "$s;
        fi
    done

    command cat $e;
}

所以命令:

cat dir1/stamp1.txt dir2/stamp0.txt

将转换为

cat dir2/stamp0.txt

这个例子很好用

ar cruv some_lib.a `cat dir1/stamp1.txt dir2/stamp0.txt`

但是,当我运行一些makefile来构建某些软件时-在此过程中,使用的是原始cat也未覆盖。

如何在不更改makefile的情况下覆盖cat或任何其他命令以使其在制作过程中起作用(makefile是3rdparty软件,我不想在每次需要升级时对其进行修补) ?

2 个答案:

答案 0 :(得分:1)

简短版本:您不能(而且您可能不想要)。

长版本:您已经定义了一个shell函数。实际上,您甚至可以将该Shell函数导出到环境export -f cat中。但是除非Makefile在说bash -c cat ...而不是说cat(或其他引用相同的效果),否则它不会给您想要的行为。

如果您真的坚持……而Makefile没有使用硬编码路径(例如/bin/cat)。您可以编写自己的猫,将其放置在某个地方,并在cat的其他可能命中位置之前放置该猫(只需将它放在前面)。

也有机会(在make文件中查看)它使用变量(例如CAT)来知道要调用的内容,因此,您可以仅提供自己的定义。

尽管如此。我不鼓励您使用此类变通办法,因为这样做会混淆机器的实际行为。这里声明了一些东西……环境中的其他东西赋予了它不同的含义。这是错误的非常常见的来源,并最终导致非显而易见的(难以解决的)错误。


功能位示例/说明。我有一个Makefile:

all:
    @echo foo

并定义并导出函数“覆盖”回显。 echo() { /bin/echo "$@" bar; } ; export -f echo。我运行make and get:

$ make
foo

因为make只在echo中寻找PATH(尝试exec之后找到它,然后运行它)。如果我将其更改为介于bash之间,则导出的函数将启动,但是...这是在make中使用命令的常用方式,因此您必须编辑不需要的Makefile:

all:
    @bash -c 'echo foo'

这将为您提供所需的结果:

$ make
foo bar

我提到的另一个选项。我已将该功能的行为放入脚本/tmp/bin/echo中,内容为:

#!/bin/bash
/bin/echo "$@" bar

并且我已经修改了PATH环境变量export PATH=/tmp/bin:$PATH。现在,即使使用Makefile的第一种形式:

all:
    @echo foo

我得到:

$ make
foo bar

但是,如果给出的Makefile改为说/bin/echo,那么我就没有这种运气了。您仍然可以更改二进制文件...,也可以通过强制共享库预加载来更改其行为...但是听起来引人注目,并且充分揭示了为什么这实际上不是采用二进制文件的最佳方向。

答案 1 :(得分:1)

您不能使用shell函数来执行此操作,因为shell函数仅存在于本地shell中。它不会传递给make之类的程序。另外,GNU make总是默认调用/bin/sh而不是/bin/bash,并且您上面的shell函数是用bash语法编写的,因此将其放入~/.bashrc中不会有影响。

您可以运行:

$ make SHELL=/bin/bash

并将该shell函数添加到您的~/.bashrc中,这可能会起作用。

您唯一可以做的另一件事(假设您的第三方makefile直接调用cat而不使用$(CAT)之类的变量)是创建一个cat shell脚本(不是函数),并在调用make时将其放在PATH/bin之前的/usr/bin上。像这样:

$ mkdir tmp
$ vi tmp/cat
    ...add commands...
$ chmod 755 tmp/cat
$ PATH=$(pwd)/tmp:$PATH make ...

当然,执行此操作时,不能在脚本中使用command cat ...,而必须使用完全限定的路径,例如/bin/cat ...