【问题标题】:Color highlighting of Makefile warnings and errorsMakefile 警告和错误的颜色突出显示
【发布时间】:2014-07-31 10:04:12
【问题描述】:

我写了一个运行良好的 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 脚本技巧”。查看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

提前致谢!

【问题讨论】:

  • 该makefile到底发生了什么(或没有发生)?快速浏览一下,您可能只需要在主体规则中转义$,因此s%$pathpat%$ccred&amp;$ccend%g 需要为s%$$pathpat%$$ccred&amp;$$ccend%g,等等。此外,pipestatus echo 不会像它需要那样在自己的行上工作与编译行在同一命令行上以按照您想要的方式工作。
  • 我已经编辑了帖子,但出现了错误
  • 你的命令行基本上是sed -e "...1" -e "...2" echo ""。这告诉sed 对名称为echo 和空字符串的文件执行sed 命令...1...2。因此,错误消息是合乎逻辑的。此外,在 makefile 中,设置 make 变量的命令不能使用 bash 语法。所以ccred=$(echo -e "\033[0;31m") 并没有按照你的想法去做。最后,正如 Etan 指出的那样,makefile 中的 $ 替换是在命令行传递给 bash 之前处理的,因此您需要转义 $ 以进行 bash 替换,或者将 () 放在 make 变量的名称周围。跨度>
  • 您需要在echo 之前放置一个分号以将其分隔为第二个命令,而不仅仅是将其附加到 sed 命令。我最初误读了$(echo -e "\033[0;31m"),您要么想从该行中删除$() 并在规则正文中使用$$(echo "$$ccred"),要么使用$(shell echo ...) 来获取命令的输出。
  • 顺便说一句,除了了解更多关于bashmake 的价值之外,我看不出避免使用colorgcccolormake 等简单工具的理由。但可能最好的解决方案是使用 clang 编译,它会自行为错误消息和警告着色。

标签: linux bash colors sed makefile


【解决方案1】:

在 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 只在 make 解析时运行一次 echo 命令,而不是每次使用 ccred 时。 )

make 和 shell 变量共享前缀符号 $。因此,在 make 上下文中使用 shell 变量需要在 shell 上下文中转义 $,方法是将其加倍为 $$。因此s%$pathpat%$ccred&amp;$ccend%g 需要为s%$$pathpat%$$ccred&amp;$$ccend%g 等。

make 规则主体的每一行都作为不同的 shell 命令执行,因此这些命令不能相互交互。为了有意义地使用像echo "${PIPESTATUS[0]}" 这样的结构,因此要求它们在make 中位于同一命令行上。因此,该模式规则中的编译行需要为 $(COMPILE_cpp) 2&gt;&amp;1 | sed ...; echo "${PIPESTATUS[0]}"

但是,即使这样也不会做你想做的事,因为你不需要从编译中回显退出状态,你需要用它退出,所以你可能想要; exit "${PIPESTATUS[0]}" 代替。

【讨论】:

  • Etan Reisner 和 rici,感谢您的详细解释。我对这个话题很陌生,我知道我犯了一些小错误。现在我按照您的提示修改了我的 Makefile:$(COMPILE_cpp) 2&gt;&amp;1 | sed -e s/error/"\\\e[1;31merror\\\e[0m"/g 但是,结果,调用 make 目标,我得到整个编译器输出,而不是用红色粗体写的 error 字,而是用替换的 @987654338 @纯文本。我哪里错了?
  • @helmet_23 您需要使用 echo (或类似的)来评估这些转义字符。不只是将它们发送到输出。注意在我的变体中,回声总是存在于某个地方。
  • 如果你想要一些更具可读性的东西,你可以使用ccred=$(shell tput setaf 001),并使用unix.stackexchange.com/questions/269077/…来选择颜色
【解决方案2】:

搞定了。

首先感谢@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) 打印出编译器的字符串,这样我就可以看到带有所有标志/依赖项/等的命令...

$(COMPILE_cpp_OUT) 存储编译器的输出并通过sed 命令更改一些相关的单词颜色。

【讨论】:

  • 这对我不起作用,在 debian jessie 上。我必须包含完整的 echo 路径(例如 @/bin/echo)以避免 shell 内置命令。
猜你喜欢
  • 2012-08-10
  • 2018-04-10
  • 2015-10-03
  • 1970-01-01
  • 2017-05-11
  • 2018-01-06
  • 1970-01-01
  • 2011-09-20
  • 2021-06-18
相关资源
最近更新 更多