例如,我的makefile中有这样的东西:
all:
cd some_directory
但是当我输入make
时,我只看到了'cd some_directory',就像echo
命令一样。
答案 0 :(得分:519)
它实际上正在执行命令,将目录更改为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
并在其中执行目标为“all”的Makefile
。作为最佳做法,请使用$(MAKE)
而不是直接调用make
,因为它会注意调用正确的make实例(例如,如果您为构建环境使用特殊的make版本) ,以及在使用某些开关(例如-t
。
对于记录,让总是回显它执行的命令(除非明确禁止),即使它没有输出,这就是你所看到的。
答案 1 :(得分:70)
从GNU make 3.82
开始,您可以使用.ONESHELL
特殊目标在shell的单个实例中运行所有配方行(粗体强调我的):
- 新的特殊目标:
.ONESHELL
指示 make 调用 shell的单个实例,并为其提供整个配方,无论它有多少行包含的内容。 [...]
.ONESHELL:
all:
cd ~/some_dir
pwd # Prints ~/some_dir if cd succeeded
答案 2 :(得分:20)
这是一个处理目录和制作的可爱技巧。而不是使用多行字符串,或“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
答案 3 :(得分:7)
一旦它到达那里你想要它做什么?每个命令都在子shell中执行,因此subshell更改目录,但最终结果是下一个命令仍在当前目录中。
使用GNU make,您可以执行以下操作:
BIN=/bin
foo:
$(shell cd $(BIN); ls)
答案 4 :(得分:0)
更改目录
foo:
$(MAKE) -C mydir
multi:
$(MAKE) -C / -C my-custom-dir ## Equivalent to /my-custom-dir
答案 5 :(得分:0)
这是我使用过的模式:
.PHONY: test_py_utils
PY_UTILS_DIR = py_utils
test_py_utils:
cd $(PY_UTILS_DIR) && black .
cd $(PY_UTILS_DIR) && isort .
cd $(PY_UTILS_DIR) && mypy .
cd $(PY_UTILS_DIR) && pytest -sl .
cd $(PY_UTILS_DIR) && flake8 .
我采用这种模式的动机是:
$(MAKE) -C some_dir all
&&
标点),因为它的可读性较差,而且我担心在编辑 make 配方时会打错字。.ONESHELL
特殊目标,因为:
.ONESHELL
会导致执行配方的所有行,即使较早的行之一因非零退出状态而失败。调用 set -e
等变通方法是可能的,但必须为 makefile 中的每个配方实施此类变通方法。答案 6 :(得分:-3)
像这样:
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
祝你好运!