我写了一个工作正常的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);我认为破解它的好方法是通过&#34; bash脚本技巧&#34;。查看How Can I highlight the warning and error lines in the make output?中发布的解决方案,我尝试了以下内容:
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
提前致谢!
答案 0 :(得分:11)
在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时间,而不是每次ccred
是使用。)
make和shell变量共享前缀sigil $ 。因此,在make上下文中使用shell变量需要通过将它加倍到 $$ 来转义shell上下文中的 $ 。因此s%$pathpat%$ccred&$ccend%g
需要s%$$pathpat%$$ccred&$$ccend%g
等等。
make rule body的每一行都作为一个独特的shell命令执行,因此这些命令不能相互交互。为了有意义地使用像echo "${PIPESTATUS[0]}"
这样的结构,因此要求它们位于make的同一命令行中。因此,该模式规则中的编译行需要为$(COMPILE_cpp) 2>&1 | sed ...; echo "${PIPESTATUS[0]}"
。
然而,即使这样做也不会做你想要的,因为你不需要从编辑中退出你需要退出的退出状态,所以你可能想要; exit "${PIPESTATUS[0]}"
。< / p>
答案 1 :(得分:8)
搞定了。
首先感谢@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
启动并行构建时构建的每个文件进行连贯分组。 / p>
$(BUILD_PRINT)
只打印出当前正在构建的文件的路径。
$(COMPILE_cpp)
打印出编译器的字符串,这样我就可以看到带有所有flags / dependencies / etc的命令......
$(COMPILE_cpp_OUT)
存储编译器的输出,并通过sed
命令更改一些相关的字颜色。