如何写入“cd”? makefile 中的命令?
例如,我的 makefile 中有类似这样的内容:
all:
cd some_directory
但是当我输入 make
时,我只看到“cd some_directory”,就像在 echo
命令中一样。
For example, I have something like this in my makefile:
all:
cd some_directory
But when I typed make
I saw only 'cd some_directory', like in the echo
command.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
它实际上是在执行命令,将目录更改为
some_directory
,但是,这是在子进程 shell 中执行的,不会影响 make 或您正在使用的 shell。如果您希望在
some_directory
中执行更多任务,您需要添加分号并附加其他命令。请注意,您不能使用新行,因为它们被 make 解释为规则的结尾,因此为了清晰起见,您使用的任何新行都需要用反斜杠转义。例如:
另请注意,即使添加反斜杠和换行符,每个命令之间也必须使用分号。这是因为整个字符串被 shell 解析为一行。正如评论中所述,您应该使用“&&”连接命令,这意味着只有前面的命令成功时才会执行它们。
这在进行破坏性工作(例如清理)时尤其重要,因为如果
cd
由于任何原因失败,您就会破坏错误的东西。不过,常见的用法是在您可能想要查看的子目录中调用 make。为此有一个命令行选项,因此您不必自己调用
cd
,因此您的规则将如下所示,它将更改为
some_dir
并执行 < code>Makefile 在该目录中,目标为“all”。最佳实践是使用$(MAKE)
而不是直接调用make
,因为它会小心地调用正确的 make 实例(例如,如果您使用适合您的构建环境的特殊 make 版本),并在使用某些开关(例如-t
)运行时提供略有不同的行为。作为记录,make总是回显它执行的命令(除非明确禁止),即使它没有输出,这就是您所看到的。
It is actually executing the command, changing the directory to
some_directory
, however, this is performed in a sub-process shell, and affects neither make nor the shell you're working from.If you're looking to perform more tasks within
some_directory
, you need to add a semi-colon and append the other commands as well. Note that you cannot use new lines as they are interpreted by make as the end of the rule, so any new lines you use for clarity need to be escaped by a backslash.For example:
Note also that the semicolon is necessary between every command even though you add a backslash and a newline. This is due to the fact that the entire string is parsed as a single line by the shell. As noted in the comments, you should use '&&' to join commands, which means they only get executed if the preceding command was successful.
This is especially crucial when doing destructive work, such as clean-up, as you'll otherwise destroy the wrong stuff, should the
cd
fail for whatever reason.A common usage, though, is to call make in the subdirectory, which you might want to look into. There's a command-line option for this, so you don't have to call
cd
yourself, so your rule would look like thiswhich will change into
some_dir
and execute theMakefile
in that directory, with the target "all". As a best practice, use$(MAKE)
instead of callingmake
directly, as it'll take care to call the right make instance (if you, for example, use a special make version for your build environment), as well as provide slightly different behavior when running using certain switches, such as-t
.For the record, make always echos the command it executes (unless explicitly suppressed), even if it has no output, which is what you're seeing.
从 GNU make 3.82(2010 年 7 月)开始,您可以使用
.ONESHELL
< /a> 在 shell 的单个实例化中运行所有配方的特殊目标(粗体强调是我的):请注意,这相当于手动运行
命令不与
&&
链接,因此如果您想在第一个失败的地方停止,您还应该添加-e 标记到您的
.SHELLFLAGS
:还有
-o pipelinefail
标志可能令人感兴趣:Starting from GNU make 3.82 (July 2010), you can use the
.ONESHELL
special target to run all recipes in a single instantiation of the shell (bold emphasis mine):Note that this will be equivalent to manually running
Commands are not linked with
&&
so if you want to stop at the first one that fails, you should also add the-e
flag to your.SHELLFLAGS
:Also the
-o pipefail
flag might be of interest:这是一个处理目录和 make 的可爱技巧。而不是使用多行字符串或“cd ;”在每个命令上,定义一个简单的 chdir 函数,如下所示:
然后您所要做的就是在规则中调用它,如下所示:
您甚至可以执行以下操作:
Here's a cute trick to deal with directories and make. Instead of using multiline strings, or "cd ;" on each command, define a simple chdir function as so:
Then all you have to do is call it in your rule as so:
You can even do the following:
一旦它到达那里,你希望它做什么?每个命令都是在子shell中执行的,因此子shell会改变目录,但最终结果是下一个命令仍然在当前目录中。
使用 GNU make,您可以执行以下操作:
What do you want it to do once it gets there? Each command is executed in a subshell, so the subshell changes directory, but the end result is that the next command is still in the current directory.
With GNU make, you can do something like:
这是我使用的模式:
我使用此模式的动机是:
$(MAKE) -C some_dir all
&&
标点),因为它的可读性较差,而且我担心我会犯错编辑制作配方时。.ONESHELL
特殊目标,因为:.ONESHELL
会导致执行配方的所有行,即使较早的行之一因非零退出状态而失败也是如此。可以使用诸如调用set -e
之类的解决方法,但必须为 makefile 中的每个配方实现此类解决方法。Here is the pattern I've used:
My motivations for this pattern are:
$(MAKE) -C some_dir all
&&
) because it is less readable, and I fear that I will make a typo when editing the make recipe..ONESHELL
special target because:.ONESHELL
causes all lines of the recipe to be executed even if one of the earlier lines has failed with a nonzero exit status. Workarounds like callingset -e
are possible, but such workarounds would have to be implemented for every recipe in the makefile.更改目录
To change dir
PYTHON = python3
测试:
cd src/mainscripts; ${PYTHON} -m pytest
#将make文件保存在根目录中并从上面的源根目录运行测试#对我有用。
PYTHON = python3
test:
cd src/mainscripts; ${PYTHON} -m pytest
#to keep make file in root directory and run test from source root above #worked for me.
就像这样:
祝你好运!
Like this:
Good luck!