我有一个这样的makefile结构:
all :
compile executable
clean :
rm -f *.o $(EXEC)
Run Code Online (Sandbox Code Playgroud)
我意识到在运行"make all"之前,我一直在我的终端中运行"make clean"然后"clear".在尝试筛选令人讨厌的C++编译错误之前,我喜欢有一个干净的终端.所以我尝试添加第三个目标:
fresh :
rm -f *.o $(EXEC)
clear
make all
Run Code Online (Sandbox Code Playgroud)
这是有效的,但这会运行make的第二个实例(我相信).有没有正确的方法来获得相同的功能而不运行第二个make实例?
Dac*_*cav 147
实际上你是对的:它运行另一个make实例.一个可能的解决方案是:
.PHONY : clearscr fresh clean all
all :
compile executable
clean :
rm -f *.o $(EXEC)
fresh : clean clearscr all
clearscr:
clear
Run Code Online (Sandbox Code Playgroud)
通过调用make fresh你先获得clean目标,然后clearscreen运行clear,最后all完成工作.
编辑8月4日
使用make -j选项进行并行构建时会发生什么?有一种方法可以修复订单.从制作手册,第4.2节:
但是,有时您可能希望对要调用的规则强制执行特定排序,而不强制在执行其中一个规则时更新目标.在这种情况下,您希望定义仅订单的先决条件.可以通过在先决条件列表中放置管道符号(|)来指定仅订单的先决条件:管道符号左侧的任何先决条件都是正常的; 右边的任何先决条件都是仅限订单:目标:正常先决条件| 订单仅-先决条件
正常的先决条件部分当然可能是空的.此外,您仍可以为同一目标声明多行先决条件:它们会相应地附加.请注意,如果将同一文件声明为普通文件和仅限订单的先决条件,则通常的先决条件优先(因为它们是仅订单先决条件行为的严格超集).
因此makefile成为
.PHONY : clearscr fresh clean all
all :
compile executable
clean :
rm -f *.o $(EXEC)
fresh : | clean clearscr all
clearscr:
clear
Run Code Online (Sandbox Code Playgroud)
编辑12月5日
运行多个makefile实例并不是什么大问题,因为任务中的每个命令都是子shell.但是你可以使用call函数获得可重用的方法.
log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)
install:
@[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
command1 # this line will be a subshell
command2 # this line will be another subshell
@command3 # Use `@` to hide the command line
$(call log_error, "It works, yey!")
uninstall:
@[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
....
$(call log_error, "Nuked!")
Run Code Online (Sandbox Code Playgroud)
Pio*_*per 23
您已经有了一个顺序解决方案,可以将其重写为:
\nfresh:\n $(MAKE) clean\n clear\n $(MAKE) all\nRun Code Online (Sandbox Code Playgroud)\n这是正确的,也是非常安全的做法。
\n在 GNU make 中使用适当的依赖关系图可以顺序执行目标:
\nfresh: _all\n_all: _clear\n Recipe for all\n_clear: _clean\n Recipe for clear\n_clean:\n Recipe for clean\nRun Code Online (Sandbox Code Playgroud)\n上述规则定义了以下依赖图:fresh<- _all<- _clear<-_clean保证了以下配方执行顺序:Recipe for clean, Recipe for clear, Recipe for all。
可以使用以下方法与多个目标共享配方:
\ntarget1 target2 target\xe2\x80\xa6:\n recipe1\nRun Code Online (Sandbox Code Playgroud)\n将您的脚本与上述概念合并会产生:
\nall _all : \n compile executable\nclean _clean :\n rm -f *.o $(EXEC)\nclear _clear :\n clear\nfresh: _all\n_all: _clear\n_clear: _clean\nRun Code Online (Sandbox Code Playgroud)\n使用https://github.com/pkoper/mk/chains.mk中的语法糖,您可以编写:
all all@fresh :\n compile executable\nclean clean@fresh :\n rm -f *.o $(EXEC)\nclear clear@fresh :\n clear\n\n@fresh = clean clear all\ninclude chains.mk\n\nfresh: @fresh\nRun Code Online (Sandbox Code Playgroud)\n或更好:
\nall: compile\n\n@fresh = clean clear compile\ninclude chains.mk\n\nfresh: @fresh\n\ncompile compile@fresh:\n compile executable\nclear clear@fresh:\n clear\nclean clean@fresh:\n rm -f *.o $(EXEC)\nRun Code Online (Sandbox Code Playgroud)\n
如果您make all从"新鲜"目标中删除了该行:
fresh :
rm -f *.o $(EXEC)
clear
Run Code Online (Sandbox Code Playgroud)
您只需运行命令即可make fresh all执行make fresh; make all.
有些人可能会认为这是make的第二个实例,但它肯定不是make的一个子实例(make内部的make),这是你的尝试似乎导致的.