Makefile警告和错误的颜色突出显示

时间:2014-06-10 15:05:08

标签: linux bash colors sed makefile

我写了一个工作正常的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

提前致谢!

2 个答案:

答案 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命令更改一些相关的字颜色。