我写了一个工作正常的Makefile; 我只是将其中一部分发布到调查中:
BUILD_PRINT = @echo -e "\e[1;34mBuilding $<\e[0m" COMPILE_cpp = $(CXX) $(CFLAGS) -o $@ -c $< $(MAKEDEP) $(INCLUDES) %.o : %.cpp $(BUILD_PRINT) $(COMPILE_cpp) .SUFFIXES: .o .cpp
我想强调编译器给出的警告和错误,而不使用外部工具(如colorgcc或CMake); 我认为破解它的一个好方法是通过" bash脚本技巧 ".查看在" 如何突出显示输出中的警告和错误行"中发布的解决方案?我尝试过以下方法:
pathpat="(/[^/]*)+:[0-9]+" ccred=$(echo -e "\033[0;31m") ccyellow=$(echo -e "\033[0;33m") ccend=$(echo -e "\033[0m") BUILD_PRINT = @echo -e "\e[1;34mBuilding $<\e[0m" COMPILE_cpp = $(CXX) $(CFLAGS) -o $@ -c $< $(MAKEDEP) $(INCLUDES) %.o : %.cpp $(BUILD_PRINT) $(COMPILE_cpp) 2>&1 | sed -e "/[Ee]rror[: ]/ s%$pathpat%$ccred&$ccend%g" -e "/[Ww]arning[: ]/ s%$pathpat%$ccyellow&$ccend%g" echo "${PIPESTATUS[0]}" .SUFFIXES: .o .cpp
但它不起作用.我得到以下输出
Building main.cpp g++ -o main.o -c main.cpp 2>&1 | sed -e "/[Ee]rror[: ]/ s%athpat%cred&cend%g" -e "/[Ww]arning[: ]/ s%athpat%cyellow&cend%g" echo "" sed: can't read echo: No such file or directory sed: can't read : No such file or directory
提前致谢!
搞定了.
首先感谢@EtanReisner和@rici.这是代码:
BUILD_PRINT = \e[1;34mBuilding $<\e[0m COMPILE_cpp = $(CXX) $(CFLAGS) -o $@ -c $< $(MAKEDEP) $(INCLUDES) COMPILE_cpp_OUT=$$($(COMPILE_cpp) 2>&1 | sed -e 's/error/\\\e[1;31merror\\\e[0m/g' -e s/warning/\\\e[1;33mwarning\\\e[0m/g') %.o : %.cpp @echo -e "$(BUILD_PRINT)\n$(COMPILE_cpp)\n$(COMPILE_cpp_OUT)" .SUFFIXES: .o .cpp
所有命令仅由一个调用,echo
因为我希望所有输出(命令字符串和警告/错误)针对我启动并行构建时构建的每个文件进行相关分组make -j
.
$(BUILD_PRINT)
只打印出当前正在构建的文件的路径.
$(COMPILE_cpp)
打印出编译器的字符串,这样我就可以看到带有所有flags/dependencies/etc的命令......
$(COMPILE_cpp_OUT)
存储编译器的输出并通过sed
命令更改一些相关的字颜色.
在make上下文中,以下行的行为与它们在shell中的行为不同:
ccred=$(echo -e "\033[0;31m") ccyellow=$(echo -e "\033[0;33m") ccend=$(echo -e "\033[0m")
在shell中,那些将回显的输出放入那些变量中.在make中尝试运行echo
不存在的命令,最终创建空变量.
这些行应该是
ccred=$(shell echo -e "\033[0;31m")
通过shell运行命令并存储输出,然后$(ccred)
在正文中使用
ccred=\033[0;31m
将字符串存储在变量中,然后$$(echo -e '$(ccred)')
在主体中使用
ccred=echo -e "\033[0;31m"
将命令存储在变量中,然后$$($(ccred)
在主体中使用
第一个或第二个选项中的任何一个都可能没问题.(:=而不是=在第一个选项中使make只运行一次echo命令,在make parse time,而不是每次ccred
都使用.)
make和shell变量共享前缀sigil $.因此,在make上下文中使用shell变量需要$通过将其加倍来转义in shell上下文$$.因此s%$pathpat%$ccred&$ccend%g
需要s%$$pathpat%$$ccred&$$ccend%g
等等
make规则体的每一行都作为不同的shell命令执行,因此这些命令不能相互交互.为了echo "${PIPESTATUS[0]}"
有意义地使用构造,因此要求它们在make中位于同一命令行中.因此,该模式规则中的编译行需要$(COMPILE_cpp) 2>&1 | sed ...; echo "${PIPESTATUS[0]}"
.
但是,即使这样做也不会做你想要的,因为你不需要从你需要退出的编译中回显退出状态,所以你可能想要; exit "${PIPESTATUS[0]}"
那样做.