hel*_*_23 16 linux bash makefile sed colors
我写了一个工作正常的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
Run Code Online (Sandbox Code Playgroud)
我想强调编译器给出的警告和错误,而不使用外部工具(如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
Run Code Online (Sandbox Code Playgroud)
但它不起作用.我得到以下输出
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
Run Code Online (Sandbox Code Playgroud)
提前致谢!
Eta*_*ner 12
在make上下文中,以下行的行为与它们在shell中的行为不同:
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
Run Code Online (Sandbox Code Playgroud)
在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]}"那样做.
搞定了.
首先感谢@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
Run Code Online (Sandbox Code Playgroud)
所有命令仅由一个调用,echo因为我希望所有输出(命令字符串和警告/错误)针对我启动并行构建时构建的每个文件进行相关分组make -j.
$(BUILD_PRINT) 只打印出当前正在构建的文件的路径.
$(COMPILE_cpp) 打印出编译器的字符串,这样我就可以看到带有所有flags/dependencies/etc的命令......
$(COMPILE_cpp_OUT)存储编译器的输出并通过sed命令更改一些相关的字颜色.