如何从Makefile中使用shell内置函数?

per*_*ror 7 shell makefile

我只是偶然发现了这个问题.我试着写一个非常基本的Makefile目标:

core: myprogram
        ulimit -c 10000
        ./myprogram
        ulimit -c 0
Run Code Online (Sandbox Code Playgroud)

我们的想法是将核心大小限制设置为适当的值,使程序崩溃,然后将核心大小限制重置为零.当我调用此规则时,我收到以下错误消息:

$ make core
cc -Wall -Wextra -m32 -g  -o example example.c 
ulimit -c 100000
make: ulimit: Command not found
make: *** [core] Error 127
Run Code Online (Sandbox Code Playgroud)

首先,我有点惊讶,但我认为这个问题来自于ulimit内置shell 的事实.而且,令人惊讶的是(至少对我而言),这些内置函数无法从a调用Makefile.

此外,ulimit既可以是仅一个内置函数(它是这种情况在我的Debian)仅一个二进制程序(/usr/bin/ulimit).

所以,我的问题很简单,如何以优雅和可移植的方式解决这个问题,并从Makefile内部调用内置函数?

Mad*_*ist 17

您收到此错误的原因是make(特别是GNU make)尝试执行许多优化.其中之一是,如果命令看起来是一个不需要shell的简单命令,那么make将直接通过fork/exec调用它而不运行shell.如果该命令仅作为内置shell存在,那么这将不起作用.你的命令行ulimit -c 10000是一个简单的命令,ulimit没有被定义为只有一个shell-builtin,所以make会ulimit直接尝试fork/exec .因此,解决您的直接问题的方法是简单地添加一个特殊于shell的字符(最明显的一个;),这将暗示需要将此命令发送到shell.

但是,这对您不起作用.

与H2CO3上面的评论完全相反:考虑到它提供的功能,它怎么可能是[内置shell]?你必须问自己的真正问题是相反的:考虑到它提供的功能,它怎么可能不是一个? ulimit的手册页明确指出:ulimit实用程序应设置或报告对shell及其子进程写入的文件施加的文件大小写入限制,并且:由于ulimit影响当前的shell执行环境,因此它始终以一个shell常规内置.

您必须记住,UNIX中的进程几乎不可能修改其父进程的任何方面.它只能修改自身或它调用的任何子进程.这包括环境变量,工作目录,还包括ulimit设置.

那么,好,这对您的情况有何影响?您必须记住,make配方中的每个逻辑行都在一个单独的shell中调用.所以对于像这样的命令:

core: myprogram
        ulimit -c 10000 ;
        ./myprogram
        ulimit -c 0 ;
Run Code Online (Sandbox Code Playgroud)

(添加分号以强制shell)基本上调用的是:

core: myprogram
        /bin/sh -c 'ulimit -c 10000 ;'
        /bin/sh -c './myprogram'
        /bin/sh -c 'ulimit -c 0 ;'
Run Code Online (Sandbox Code Playgroud)

如您所见,每个ulimit都在自己的shell中调用,因此它实际上没用.它将修改该shell的核心文件大小限制,然后shell退出并且更改丢失,然后在具有原始ulimit的新shell中调用您的程序,然后调用第三个shell并将core的ulimit设置为0 (也没用).

您需要做的是将所有这些命令放在一个逻辑行上,如下所示:

core: myprogram
        ulimit -c 10000; ./myprogram
Run Code Online (Sandbox Code Playgroud)

(您不需要设置限制,因为shell无论如何都会退出).

作为旁注,就是为什么make不太担心这些shell内置函数.像这样的内建基本上不可能使用任何影响的情况下,你并不需要使用一些特殊的shell字符像一个分号.