例如,我的makefile文件中包含以下内容:
all:
cd some_directory
但是当我键入命令时make
,仅看到“ cd some_directory”,如echo
命令中所示。
cd dir; cmd file
几乎总是可以更有用地表示为cmd dir/file
。
.
。的确,大多数工具的设计方式都不需要更改其密码。但这并非总是如此,我认为将其称为“错误”以认为您的目录可能很重要不是一个好主意。
例如,我的makefile文件中包含以下内容:
all:
cd some_directory
但是当我键入命令时make
,仅看到“ cd some_directory”,如echo
命令中所示。
cd dir; cmd file
几乎总是可以更有用地表示为cmd dir/file
。
.
。的确,大多数工具的设计方式都不需要更改其密码。但这并非总是如此,我认为将其称为“错误”以认为您的目录可能很重要不是一个好主意。
Answers:
它实际上是在执行命令,将目录更改为some_directory
,但是,这是在子进程外壳程序中执行的,不会影响make或您正在使用的外壳程序。
如果您希望在中执行更多任务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
它将更改为目标“ all” some_dir
并Makefile
在其中执行。最佳做法是使用$(MAKE)
而不是make
直接调用,因为它将注意调用正确的make实例(例如,如果您为构建环境使用特殊的make版本),并且在运行时提供略有不同的行为使用某些开关,例如-t
。
为了记录起见,make 总是回显它执行的命令(除非明确禁止),即使它没有输出,这也是您所看到的。
%-recursive:
body :(@T="$@";$(MAKE) -C some_dir $${T%-*}
我通常也有一个for循环,循环遍历子目录列表,这$${T%-*}
是一个bash扩展,它删除-recursive
了目标名称的一部分),然后定义明确的短手(和.PHONY)目标的每个,如all: all-recursive
,check: check-recursive
,clean: clean-recursive
。
从GNU make 3.82(2010年7月)开始,您可以使用.ONESHELL
特殊目标在shell的单个实例中运行所有配方行(加粗强调我的):
- 新的特殊目标:
.ONESHELL
指示make调用该shell的单个实例并向其提供整个配方,而不管其包含多少行。[...]
.ONESHELL: # Only applies to all target
all:
cd ~/some_dir
pwd # Prints ~/some_dir if cd succeeded
pwd
本身的工作原理,以及`pwd`
(与反引号),但$(shell pwd)
和$(PWD)
做之前仍然会返回目录cd
命令,所以你不能直接使用它们。
pwd
和`pwd`
是由shell本身执行的。
SHELLFLAGS
为-e -c
,shell将在第一个失败的命令退出。
这是处理目录和目录的一个可爱技巧。而不是使用多行字符串或“ 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
-jn
,这对于并行执行()来说是很困难的,这实际上是make的全部要点。
一旦到达目的地,您希望它做什么?每个命令都在子外壳程序中执行,因此该子外壳程序会更改目录,但最终结果是下一个命令仍在当前目录中。
使用GNU make,您可以执行以下操作:
BIN=/bin
foo:
$(shell cd $(BIN); ls)
$(shell ...)
when cd $(BIN); ls
或cd $(BIN) && ls
(如@andrewdotn指出的)就足够了。
更改目录
foo:
$(MAKE) -C mydir
multi:
$(MAKE) -C / -C my-custom-dir ## Equivalent to /my-custom-dir
像这样:
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
祝好运!
$(shell cd ....)
最初分析Makefile时执行,而不是在运行此特定配方时执行。
$(shell)
仅在make决定建立target时才扩展。如果make不需要配方,则不会扩展它。
make
,我从来没有想像这样更改目录。也许您应该尝试另一种解决方案?