I have written a Makefile which works fine; I am just posting the part of it under investigation:
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
I would like to highlight the warnings and errors given by the compiler without using external tools (such as colorgcc or CMake); I thought that a good way to hack it was via "bash script tricks". Looking at the solution posted in How Can I highlight the warning and error lines in the make output? I have tried the following:
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
but it is not working. I get the following output
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
Thanks in advance!
Got it working.
First of all thanks @EtanReisner and @rici. Here's the code:
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
All the commands are invoked by only one echo
because I want all the outputs (command string and warnings/errors) coherently grouped for each file built when I launch a parallel build with make -j
.
$(BUILD_PRINT)
just prints out the path of the file currently being built.
$(COMPILE_cpp)
prints out the string of the compiler, so that I can see the command with all the flags/dependencies/etc...
$(COMPILE_cpp_OUT)
stores the output of the compiler and change some relevant word colour via sed
command.
In make context the following lines do not behave the way they would in the shell:
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
In the shell those would put the echoed output into those variables. In make that tries to run the echo
command, which doesn't exist, and ends up creating empty variables.
Those lines should either be
ccred=$(shell echo -e "\033[0;31m")
to run the commands through the shell and store the output and then used as $(ccred)
in the bodyccred=\033[0;31m
to store the string in the variable and then used as $$(echo -e '$(ccred)')
in the bodyccred=echo -e "\033[0;31m"
to store the command in the variable and then used as $$($(ccred)
in the bodyEither of the first or second options is likely fine. (Use := instead of = in the first option to have make only run the echo command once, at make parse time, instead of every time ccred
is used.)
make and shell variables share a prefix sigil $. As such to use shell variables in make contexts requires escaping the $ in shell contexts by doubling it to $$. As such s%$pathpat%$ccred&$ccend%g
needs to be s%$$pathpat%$$ccred&$$ccend%g
, etc.
Each line of a make rule body is executed as a distinct shell command, as such the commands cannot interact with each other. In order to use constructs like echo "${PIPESTATUS[0]}"
meaningfully therefore requires that they be on the same command line in make. As such the compile line in that pattern rule would need to be $(COMPILE_cpp) 2>&1 | sed ...; echo "${PIPESTATUS[0]}"
.
However, even that isn't going to do what you want since you don't need to echo the exit status from the compilation you need to exit with it, so you probably want ; exit "${PIPESTATUS[0]}"
there instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With