例如,我在我的Makefile是这样的:如何在makefile中写入'cd'命令?
all:
cd some_directory
但是,当我输入make
我看到的只是“CD some_directory”,像在echo
命令。
例如,我在我的Makefile是这样的:如何在makefile中写入'cd'命令?
all:
cd some_directory
但是,当我输入make
我看到的只是“CD some_directory”,像在echo
命令。
它实际上正在执行命令,将目录更改为some_directory
,但是,这是在子进程shell中执行的,并且不影响make和您正在使用的shell。
如果您要在some_directory
范围内执行更多任务,则需要添加一个分号并附加其他命令。请注意,您不能使用换行符,因为它们被make解释为规则的结尾,因此为清晰起见使用的任何换行符都需要使用反斜杠进行转义。
例如:
all:
cd some_dir; echo "I'm in some_dir"; \
gcc -Wall -o myTest myTest.c
还要注意分号是每一个命令之间必要的,即使你加一个反斜杠和一个换行符。这是由于整个字符串被shell解析为一行。正如评论中指出的那样,您应该使用'& &'来加入命令,这意味着只有在前面的命令成功时才会执行它们。
all:
cd some_dir && echo "I'm in some_dir" && \
gcc -Wall -o myTest myTest.c
做破坏性的工作,如清理时,你会否则将会破坏错了东西,应cd
失败不管出于什么原因,这一点尤为重要。
虽然常用的方法是在子目录中调用make,但您可能需要查看该子目录。有此一命令行选项,这样你就不用调用cd
自己,所以你的规则是这样的
all:
$(MAKE) -C some_dir all
这将改变成some_dir
,并在那里与目标“的所有”执行Makefile
。作为最佳实践,使用$(MAKE)
而不是直接调用make
,因为它会小心地调用正确的make实例(例如,如果您为构建环境使用特殊的make版本),并提供稍微不同的行为运行时使用某些开关,如-t
。
对于记录,使总是回声它执行的命令(除非明确禁止),即使它没有输出,这就是你所看到的。
那么,不*总是*。为了抑制回声,只需在该行的开头添加@。 – Beta
@Beta:好的,并且破折号前缀也会忽略错误状态。也许我有点失落了,我想指出这样一个事实,即无论命令是什么,命令都会回应命令。在这种情况下,这是一个没有输出的命令,这让不熟悉make的人看起来更加陌生。 – falstro
两个nits:1.这些命令应该真的被'&&'连接,因为用';'如果目录不存在并且'cd'失败,shell将继续运行当前目录中的其余命令,这可能会导致诸如编译时发现神秘的“文件未找到”消息,调用make时出现无限循环,或者像'clean :: cd dir; rm -rf *'。 2.调用子make时,调用'$(MAKE)'而不是'make',以便[选项将正确传递](http://www.gnu.org/software/make/manual/make.html #MAKE-变量)。 – andrewdotn
一旦到达那里,你想要它做什么?每个命令都在子shell中执行,因此子shell会更改目录,但最终结果是下一个命令仍在当前目录中。
用GNU做,你可以这样做:
BIN=/bin
foo:
$(shell cd $(BIN); ls)
为什么'$(shell ...)'时出现cd $(BIN); ls'或'cd $(BIN)&& ls'(就像@andrewdotn指出的)就足够了。 – vapace
这里有一个可爱的把戏对付目录而作。而不是使用多行字符串,或“cd;”每个命令,定义了一个简单的chdir函数像这样:
CHDIR_SHELL := $(SHELL)
define chdir
$(eval _D=$(firstword $(1) $(@D)))
$(info $(MAKE): cd $(_D)) $(eval SHELL = cd $(_D); $(CHDIR_SHELL))
endef
然后,所有你需要做的就是把它在你的规则,像这样:
all:
$(call chdir,some_dir)
echo "I'm now always in some_dir"
gcc -Wall -o myTest myTest.c
你甚至可以做到以下几点:
some_dir/myTest:
$(call chdir)
echo "I'm now always in some_dir"
gcc -Wall -o myTest myTest.c
“可爱”?更像是有足够的绳子在脚下射击自己。 – tripleee
这个当前目录是为那些只在该规则中的命令设置的,还是为所有后来执行的规则设置的?此外,将在Windows下这项工作的一些变化? – user117529
这当然会破坏并行执行('-jn'),这是_make_的全部重点。 – bobbogo
从GNU make 3.82
开始,您可以使用.ONESHELL
特殊目标在外壳的单实例运行所有食谱线:
- 新的特殊目标:
.ONESHELL
指示作出调用单个实例的外壳 并提供其与整个配方,不管它有多少 线包含的内容。 [...]
例子:
.ONESHELL:
all:
cd ~/some_dir
pwd # this line is correctly run in ~/some_dir if cd succeeded
像这样:
target:
$(shell cd ....); \
# ... commands execution in this directory
# ... no need to go back (using "cd -" or so)
# ... next target will be automatically in prev dir
祝你好运!
目前还不清楚你想做什么,但是,根据我对'make'的经验,我从来不想改变这个目录。也许你应该尝试另一种解决方案? –
相信你的目录很重要,这是一个常见的新手错误。对于大多数情况来说,它不是; 'cd dir; cmd文件几乎总是可以用'cmd dir/file'来表示。 – tripleee
这是一个常见的新手错误,相信你目前的工作目录是无足轻重的。许多程序,特别是shell脚本,都是以“。”为特定的值写入的。 的确,大多数工具都是这样设计的,你不需要为它改变你的密码。但这并非总是如此,我认为将其称为“错误”以相信您的目录可能很重要是个好主意。 –