如何使用Makefile中的shell内置函数? [英] How to use shell builtin function from a Makefile?

查看:85
本文介绍了如何使用Makefile中的shell内置函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I just stumbled on this problem. I tried to write a very basic Makefile target:

core: myprogram
        ulimit -c 10000
        ./myprogram
        ulimit -c 0

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

The idea is to set up the core size limit to a proper value, make the program crash and then reset the core size limit back to zero. When I am calling this rule, I get the following error message:

$ make core
cc -Wall -Wextra -m32 -g  -o example example.c 
ulimit -c 100000
make: ulimit: Command not found
make: *** [core] Error 127

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

First, I have been a bit surprised, but I think that the problem is coming from the fact that ulimit is a shell builtin. And, suprisingly (at least for me), these builtin functions cannot be called from a Makefile.

此外,ulimit只能是内置函数(在我的Debian中就是这种情况)只能是二进制程序(/usr/bin/ulimit).

Moreover, ulimit can be both a builtin function only (it is the case on my Debian) or a binary program only (/usr/bin/ulimit).

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

So, my question is simple, how to workaround this problem, if possible in an elegant and portable manner, and call the builtin function from the inside of a Makefile ?

推荐答案

出现此错误的原因是make(尤其是GNU make)尝试执行许多优化.其中之一是,如果命令出现是不需要shell的简单命令,那么make会直接通过fork/exec直接调用它,而不运行shell.如果该命令仅作为内置的Shell存在,则此命令将无效.您的命令行ulimit -c 10000是一个简单的命令,而ulimit并不是仅定义为make知道的shell内置命令,因此make会尝试直接fork/exec ulimit.因此,解决当前问题的一种方法是,简单地在shell中添加一个特殊字符(最明显的是;),这暗示着该命令需要发送到shell.

The reason you're getting this error is that make (GNU make in particular) tries to perform a number of optimizations. One of those is that if the command appears to be a simple command that does not require the shell, then make will simply invoke it directly via fork/exec and not run a shell. If the command only exists as a shell built-in, then this will not work. Your command line ulimit -c 10000 is a simple command and ulimit is not defined as only a shell-builtin that make knows about, so make will try to fork/exec ulimit directly. So a way to get around your immediate issue is to simply add a character that's special to the shell (the most obvious one is ;), which will hint to make that this command needs to be sent to the shell.

但是,这对您不起作用.

However, this will not work for you.

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

Exactly contrary to H2CO3's comment above: How possibly could it be [a shell builtin], given the functionality it provides? the real question you have to ask yourself is the opposite: how possibly could it NOT be one, given the functionality it provides? The man page for ulimit clearly states: The ulimit utility shall set or report the file-size writing limit imposed on files written by the shell and its child processes, and further: Since ulimit affects the current shell execution environment, it is always provided as a shell regular built-in.

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

You have to remember that it's virtually impossible for a process in UNIX to modify ANY aspect of its parent process. It can only modify itself, or any child processes that it invokes. This includes the environment variables, working directory, and it also includes ulimit settings.

那么,很好,这如何适用于您的情况?您必须记住,make配方中的每个逻辑行都是在单独的shell 中调用的.因此,对于像这样的命令:

So, good, how does this apply to your situation? You have to remember that each logical line in a make recipe is invokes in a separate shell. So for a command like:

core: myprogram
        ulimit -c 10000 ;
        ./myprogram
        ulimit -c 0 ;

(添加分号强制使用shell)make基本上调用的是这样的:

(adding the semicolons to force a shell) what make basically invokes is this:

core: myprogram
        /bin/sh -c 'ulimit -c 10000 ;'
        /bin/sh -c './myprogram'
        /bin/sh -c 'ulimit -c 0 ;'

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

As you can see, each ulimit is invoked in its own shell, so it's effectively useless. It will modify the core file size limit for that shell, then the shell exits and the change is lost, then your program is invoked in a new shell with the original ulimit, then a third shell is invoked and ulimit for cores is set to 0 (also useless).

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

What you need to do is put all of these commands on a single logical line, like this:

core: myprogram
        ulimit -c 10000; ./myprogram

(您无需重新设置限制,因为shell仍然会退出).

(you don't need to set the limit back, because the shell will exit anyway).

作为附带说明,是为什么make不必过多担心这些shell内置函数的原因.在您不需要需要使用一些特殊的shell字符(例如分号)的情况下,基本上无法使用这样的内置函数.

As a side note, this is why make doesn't worry too much about these shell builtins. A builtin like this is basically impossible to use to any effect in a context where you don't need to use some special shell character like a semicolon.

这篇关于如何使用Makefile中的shell内置函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆