Makefile Conditionals erroneous equality - if-statement

So, I'm kind of new to makefiles, but I have this rule in mine:
$(rc)/%.class: $(r)/%.java
echo $(strip $(findstring $*,"Robot RoboController"))
ifneq (,$(strip $(findstring $*,"Robot RoboController")))
echo "Robot or RoboController"
else
echo "other";
endif
My goal, is that if the matched text is Robot or RoboController, then it compiles in one way, otherwise, it compiles in a different way, unforunately, when I run makes I get the following output:
$ make Classes/RobotSuite/robot/Robot.class
echo Robot
Robot
echo "other";
other
$ make Classes/RobotSuite/robot/RoboComm.class
echo
echo "other";
other
It seems like no matter what I put into the ifneq, it will erroneously evaluate it as equal to the null string. Can anyone explain why?
I am using the GNU Make v3.81, built for i686-pc-linux-gnu.

If you're using GNU Make, don't use ifneq to solve this problem, use Target specific variable values.

Related

How can I make the GCC error messages more readable (e.g., with color)? [duplicate]

For some long errors, the gcc output is dense and has lots of line-wrapping etc. Especially when errors are subtle, it can take me 10-30 seconds of squinting to parse it with my eyes.
I've taken to pasting this in an open code-editor window to get some basic syntax highlighting and enable reformatting with regex's.
Has anyone invented a more automated method?
I use this script, called colorize:
#!/bin/bash
while read x ; do echo $x ; done \
| sed -e "s/.*error:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/.*warning:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/^\(.*\)\(required from\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In instantiation of\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In member\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
| sed -e "s/error:/\x1b[1;31m&\x1b[1;36m/" \
-e "s/warning:/\x1b[1;35m&\x1b[1;36m/" \
-e "s/note:/\x1b[1;30m&\x1b[0m/"
Then I just call it like this(using make or whatever build system):
make |& colorize
And I get color output similar to clang.
I've found colorgcc to be invaluable. By introducing coloring, it becomes much easier to mentally parse the text of gcc error messages, especially when templates are involved.
If your errors are template related, take a look at STLfilt:
http://www.bdsoft.com/tools/stlfilt.html
gccfilter does coloring & simplification of messages.
http://www.mixtion.org/gccfilter/
If you use GCC 4.9, you can add -fdiagnostics-color=auto as an additonal compilation flag. At some later version, the color has been enabled by default.
check diagcc out, you can get something like this:
If your gcc ≥ 4.9, you can use argument -fdiagnostics-color=always.
To answer your question 4 years later, clang should be mentioned here.
Here's my current hack, which mostly inserts newlines and indentation in strategic locations along with a little extra annotation, but does nothing to address STL verbosity.
Note that as currently implemented, this script does not return an error if the compiler returned one, so doing something like this will not work properly: (make && ./runApplication). This could surely be remedied by someone with better bash-fu.
#!/bin/bash
# SUBSTITUTION RULES:
# Note: All substitution rules must end in a semi-colon, inside of the closing quote
subColonSpace='s/: /:\n /g;'
subSrc='s/^src/\nsrc/;'
subError='s/error:/error:\n\n======================================\nERROR:/;'
subWarning='s/ *error: *\n/ERROR: /;'
subWarning='s/ *warning: *\n/WARNING: /;'
subNote='s/note:/\n NOTE:/g;'
subOpenTic='s/‘/\n ‘/g;'
subOpenParen='s/(/(\n /g; s/(\n *)/()/g;'
subCommaSpace='s/, /,\n /g;'
# Note: The order of these may matter
sedExpr="$subColonSpace $subSrc $subError $subWarning $subNote $subOpenTic
$subOpenParen $subCommaSpace"
makelogFile=makelog.tmp
make "$#" 2>&1 | sed "$sedExpr" | tee $makelogFile
if you like Ruby there is GilCC! GilCC is very easy to install (just copy it to the bin folder) and easy to use (just type GilCC instead of "gcc" or "make") and it works with GCC version. Unlike Perl based scripts GilCC has statistics such as # of warnings and error and compile time. You don't have to mess with .bash files and it is cross platform as long as you can run Ruby on your machine. Since it has the power of Ruby; you can make GilCC do different things such as trigger test automation, unit test or program external hardware after a successful build.
Here is the link to the download page: http://www.onlysolutionssoftware.com/gilcc/

/bin/sh: 1: Syntax error: "(" unexpected after running Makefile [duplicate]

I often find Bash syntax very helpful, e.g. process substitution like in diff <(sort file1) <(sort file2).
Is it possible to use such Bash commands in a Makefile? I'm thinking of something like this:
file-differences:
diff <(sort file1) <(sort file2) > $#
In my GNU Make 3.80 this will give an error since it uses the shell instead of bash to execute the commands.
From the GNU Make documentation,
5.3.2 Choosing the Shell
------------------------
The program used as the shell is taken from the variable `SHELL'. If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.
So put SHELL := /bin/bash at the top of your makefile, and you should be good to go.
BTW: You can also do this for one target, at least for GNU Make. Each target can have its own variable assignments, like this:
all: a b
a:
#echo "a is $$0"
b: SHELL:=/bin/bash # HERE: this is setting the shell for b only
b:
#echo "b is $$0"
That'll print:
a is /bin/sh
b is /bin/bash
See "Target-specific Variable Values" in the documentation for more details. That line can go anywhere in the Makefile, it doesn't have to be immediately before the target.
You can call bash directly, use the -c flag:
bash -c "diff <(sort file1) <(sort file2) > $#"
Of course, you may not be able to redirect to the variable $#, but when I tried to do this, I got -bash: $#: ambiguous redirect as an error message, so you may want to look into that before you get too into this (though I'm using bash 3.2.something, so maybe yours works differently).
One way that also works is putting it this way in the first line of the your target:
your-target: $(eval SHELL:=/bin/bash)
#echo "here shell is $$0"
If portability is important you may not want to depend on a specific shell in your Makefile. Not all environments have bash available.
You can call bash directly within your Makefile instead of using the default shell:
bash -c "ls -al"
instead of:
ls -al
There is a way to do this without explicitly setting your SHELL variable to point to bash. This can be useful if you have many makefiles since SHELL isn't inherited by subsequent makefiles or taken from the environment. You also need to be sure that anyone who compiles your code configures their system this way.
If you run sudo dpkg-reconfigure dash and answer 'no' to the prompt, your system will not use dash as the default shell. It will then point to bash (at least in Ubuntu). Note that using dash as your system shell is a bit more efficient though.
It's not a direct answer to the question, makeit is limited Makefile replacement with bash syntax and it can be useful in some cases (I'm the author)
rules can be defined as bash-functions
auto-completion feature
Basic idea is to have while loop in the end of the script:
while [ $# != 0 ]; do
if [ "$(type -t $1)" == 'function' ]; then
$1
else
exit 1
fi
shift
done
https://asciinema.org/a/435159

sclite (SCTK) `make check` faliure, C++/perl/Cygwin, Safe to use Perl4 stuff?

I am currently trying to install NIST's sclite, which is part of SCTK 2.4.0 (github or newer version). I am attempting the install on Cygwin in bash. The installation is done using make.
I have gotten past the make configure and make all parts of the installation. This didn't come without some effort (See the SO posts on the first (file not recognized) and second (template/scoping) problems). When I get to the make check part of the install, a lot of the checks/tests pass, but then I get the following error.
Testing acomp.pl
No tests defined for acomp.pl
make[2]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/acomp'
(cd def_art; make check)
make[2]: Entering directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/def_art'
Testing def_art.pl
def_art.pl passed without tests
make[2]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/def_art'
(cd hubscr; make check)
make[2]: Entering directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/hubscr'
Testing hubscr.pl
./RunTests.pl
Running test 'test1-sastt', operation 'test', options '-G -f rttm -F rttm -a', directory 'test1-sastt.test'
Executing command
Error: unable to get the version for program def_art.pl with the command 'def_art.pl' at ../hubscr.pl line 419.
Error: Execution failed at ./RunTests.pl line 30.
make[2]: *** [makefile:20: check] Error 2
make[2]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/hubscr'
make[1]: *** [makefile:68: checkFast] Error 2
make[1]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src'
make: *** [makefile:52: check] Error 2
I've done some research (described below), and I've been able to get past this problem. However, this involved including some outdated perl modules (Perl4).
My first question was how to fix this error or how to skip that part of the test. I've been able to fix the error, and if people think that it's safe, I'll put it as an answer. Note that there is one more problem with make check after this problem is fixed, but I mention how to get past that at the end.
I'm wondering if using the old Perl (Perl4::CoreLibs) is safe and/or good programming practice. Would it be better to change the source code to use Perl5 stuff?
Is there a better way altogether?
One thing I want to be sure of is that there are no critical tests further down the make check line which might fail.
System Details
$ uname -a
CYGWIN_NT-6.1 CAP-D-ENG-INT3 2.10.0(0.325/5/3) 2018-02-02 15:16 x86_64 Cygwin
$ bash --version
GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin) ...
$ gcc --version
gcc (GCC) 6.4.0 ...
$ g++ --version
g++ (GCC) 6.4.0 ...
$ make --version
GNU Make 4.2.1
Built for x86_64-unknown-cygwin ...
$ systeminfo | sed -n 's/^OS\ *//p'
Name: Microsoft Windows 7 Enterprise
Version: 6.1.7601 Service Pack 1 Build 7601
Manufacturer: Microsoft Corporation
Configuration: Member Workstation
Build Type: Multiprocessor Free
My Attempts/Research
From the output above, we have def_art.pl passing the check because there are no checks - "def_art.pl passed without tests". However, the next thing checked, hubscr.pl, failed. The error comes from def_art.pl.
The obvious thing to do seemed to be to run def_art.pl, which I did.
$ ./src/def_art/def_art.pl
Can't locate getopts.pl in #INC
(#INC contains: /usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads /usr/local/share/perl5/site_perl/5.26 /usr/lib/perl5/vendor_perl/5.26/x86_64-cygwin-threads /usr/share/perl5/vendor_perl/5.26 /usr/lib/perl5/5.26/x86_64-cygwin-threads /usr/share/perl5/5.26)
at ./src/def_art/def_art.pl line 40.
So it seems to me that this is a deprecated perl file (or module, or whatever).
I dug a little further and found this discussion on a kaldi discussion from 2014. (kaldi is a speech-recognition toolkit that uses the SCTK scoring system). There are 3 sections of the discussion that I think are especially relevant, which I will link (first, second, third). I'll insert parts here:
def_art.pl is looking for getopts.pl which I coudn't find on my machine!
... [T]hese are legacy packages that are no longer supported in recent versions
of Perl 5. I don't think we should accept a dependency on them. They have
been deprecated since the beginning of Perl 5.
Instead of 'require "getopt.pl"', we should be doing
use Getopt::Std
(note: modern perl code should not call "require" for system packages).
There is a similar issue with "flush.pl" in the Perl scripts. I don't know
what the Perl 5 package name is.
... There are several places where this occurs.
I finally found that both getopts.pl and flush.pl are available from Perl4::CoreLibs. The URL that I use for wget was referenced at this site. Apparently, in other *NIX distros, the package manager can be used, e.g.
apt-get install libperl4-corelibs-perl
or
yum install perl-Perl4-CoreLibs
but I could not find an install via apt-cyg. I was able to install them from a tarball, as described in the What I'm Doing section.
One again, I'll state my main question: Is this safe/good programming practice? Is there a better solution?
If there is a better solution (using Perl 5), it seems that this link might lead the way to it.
Some other links that are possibly related: link_{n} and link{n+1} about flush.pl, link_{n+2} & link_{n+3} about getopts.pl and Perl4::CoreLibs.
What I'm Doing
$ mkdir perl_added
$ cd perl_added
$ wget http://search.cpan.org/CPAN/authors/id/Z/ZE/ZEFRAM/Perl4-CoreLibs-0.004.tar.gz
$ tar -xzf Perl4-CoreLibs-0.004.tar.gz
$ cd Perl4-CoreLibs-0.004
Rather than adding this directory's lib subdirectory to the PERLLIB environment variable with a one-time command-line, environment-variable-addition thing, I did the following.
Make a new directory in the /usr/lib directory, move the files there
$ stat /usr/lib/libperl4-corelibs-perl
stat: cannot stat '/usr/lib/libperl4-corelibs-perl': No such file or directory
# Checked that the directory didn't already exist. It didn't exist.
$ mkdir /usr/lib/libperl4-corelibs-perl
# Make each file executable, then move it into the new directory
# I'd like to come back and explain this.
$ find ./lib -type f -name "*.pl" -print0 | xargs -I'{}' -0 \
bash -c 'new_dir=/usr/lib/libperl4-corelibs-perl/; chmod +x {}; \
mv {} ${new_dir}'
Finally, I made it so that this directory will become part of the perl search path every time I use a terminal by adding the following line to my ~/.bashrc
This command adds the path to the PERLLIB environment variable. Different flavors of Linux have different syntax for adding to environment variables, make sure to find out what yours is!
export PERLLIB="/usr/bin/libperl4-corelibs-perl:$PERLLIB"
The commands I ran for this were
$ echo -e "\n\n## Allow Perl to use the files in Perl4::CoreLibs" >> $HOME/.bashrc
$ echo -e "export PERLLIB=\"/usr/lib/libperl4_corelibs_perl:$PERLLIB\"" >> $HOME/.bashrc
$ source $HOME/.bashrc
(Thanks to #melpomene for noting that the current version is 0.004, not 0.003.)
After that, I went back to the base folder of the install and ran make clean, make config, make all, and make check.
That did get me farther in the make check but not by far.
I'm wondering if using the old Perl (Perl4::CoreLibs) is safe and/or good programming practice. Would it be better to change the source code to use Perl5 stuff?
P.S. After all this, you probably want to go back and delete the folder where you untarred everything. In my case:
rm -rf /path/to/where/I/started/perl_added
The Result/Next Steps
A bunch of tests that passed and then
(cd hubscr; make check)
make[2]: Entering directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/hubscr'
Testing hubscr.pl
./RunTests.pl
Running test 'test1-sastt', operation 'test', options '-G -f rttm -F rttm -a', directory 'test1-sastt.test'
Executing command
Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/{_recursive_/_recur_{ <-- HERE _sive_/_si_ve_}_}/ at ../../md-eval/md-eval.pl line 1099, <DATA> line 12.
Error: MDEVAL failed
Command: md-eval.pl -nafcs -c 0.25 -o -r sastt-case1.ref.rttm.filt -s sastt-case1.sys.rttm.filt -M sastt-case1.sys.rttm.filt.mdeval.spkrmap 1> sastt-case1.sys.rttm.filt.mdeval at ../hubscr.pl line 679.
Error: Execution failed at ./RunTests.pl line 30.
make[2]: *** [makefile:20: check] Error 255
make[2]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src/hubscr'
make[1]: *** [makefile:68: checkFast] Error 2
make[1]: Leaving directory '/cygdrive/c/David/programs/sctk2.4.0/sctk/src'
make: *** [makefile:52: check] Error 2
Maybe this will be helpful. I will post a separate question for this issue or, if the solution is quick, I will add the solution on this post.
A Better Way
(Actually, a couple of better ways. See my comment under the question for the kaldi solution.)
In talking with colleagues and friends, it seems that there isn't anything unsafe about the Perl4 stuff. I did find a better way to get them "installed", but I'll leave the notes in the question showing the "long way" with the tarball, PERLPATH, etc.
Check that you have CPAN
$ which cpan
If you see something starting with which: no cpan in (...), you most likely don't have it. Try installing perl. For me, on Cygwin, I used
$ apt-cyg install perl
(Install apt-cyg if necessary, cf. here for instructions.)
You probably won't have to install Perl. You will likely see something like /usr/bin/cpan as the output of which cpan. If so, you're good. Enter cpan at the command prompt.
$ cpan
If it's your first time, it will ask a bunch of questions about the configuration. I just pressed "Enter" to accept the default each time, I finally got a prompt like this:
cpan shell -- CPAN exploration and modules installation (v2.18)
Enter 'h' for help.
cpan[1]>
There, I entered
cpan[1]> install Perl4::CoreLibs
The install will proceed. When it will have finished, you will be able to type exit and press "Enter", which will take you back to the bash command prompt.
cpan[2]> exit
Lockfile removed.
$
At this point, make check will still choke, but the install will complete successfully. If you want the make check to get all the way through, go to the "Getting past make check" section below. At this point, though, you can do the last two steps in the process.
$ make install
At this point I added the install path to my PATH variable. Hopefully, I'll be able to put in a link about that process. Here is a one-time solution.
$ export PATH=/path/to/sctk/bin:$PATH
Here is a lasting solution.
Now, for the last step in the installation process:
$ make doc
After the make doc, I made sure that the man pages were available. I looked on my machine until I found the place where other man files went. (Sorry, I don't have a systematic way of doing it, I just looked in a lot of places.) For me, on Cygwin, the directory was /usr/man/man1
I went into the doc directory
cd doc
and copied all of the files into the directory I had found
cp -r ./* /usr/man/man1/
Note that there are also now html and htm files in the directory that also provide documentation.
Getting past `make check`
So, you really want to see it go through without errors. You need to change the following file: src/hubscr/RunTests.pl
Originally it has the following beginning, which I have used the head command to show.
$ head -n 15 src/hubscr/RunTests.pl
#!/usr/bin/perl -w
use strict;
my $operation = (defined($ARGV[0]) ? $ARGV[0] : "test");
sub runIt{
my ($op, $testId, $options, $glm, $hub, $lang, $ref, $systems) = #_;
my $baseDir = $testId.".base";
my $outDir = $testId.($op eq "setTests" ? ".base" : ".test");
print " Running test '$testId', operation '$op', options '$options',
directory '$outDir'\n";
system ("mkdir -p $outDir");
system ("rm -fr $outDir/test* $outDir/lvc*");
### Copy files
foreach my $file($glm, $ref, split(/\s+/,$systems)){
system("cp $file $outDir");
Change it so that, after the print command, you have new lines as follows. I again use the head command to show the beginning of the file
$ head -n 63 src/hubscr/RunTests.pl
#!/usr/bin/perl -w
use strict;
my $operation = (defined($ARGV[0]) ? $ARGV[0] : "test");
sub runIt{
my ($op, $testId, $options, $glm, $hub, $lang, $ref, $systems) = #_;
my $baseDir = $testId.".base";
my $outDir = $testId.($op eq "setTests" ? ".base" : ".test");
print " Running test '$testId', operation '$op', options '$options', directory '$outDir'\n";
####DWB, 2018-05-21 Getting `make check` to work####
if ( $testId eq "test1-sastt" &&
$operation eq "test" &&
$options eq "-G -f rttm -F rttm -a" &&
$outDir eq "test1-sastt.test" ) # <problem 1>
{
print "\n";
print "\n#### SKIPPING ####";
print "\nJust kidding. That breaks the make.";
print "\nIt said: \n\n";
print "\nUnescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/{_recursive_/_recur_{ <-- HERE _sive_/_si_ve_}_}/ at ../../md-eval/md-eval.pl line 1099, <DATA> line 12.";
print "\nrror: MDEVAL failed";
print "\nCommand: md-eval.pl -nafcs -c 0.25 -o -r sastt-case1.ref.rttm.filt -s sastt-case1.sys.rttm.filt -M sastt-case1.sys.rttm.filt.mdeval.spkrmap 1> sastt-case1.sys.rttm.filt.mdeval at ../hubscr.pl line 679.";
print "\nError: Execution failed at ./RunTests.pl line 30.\n\n";
print "\n"
print "\nThat's a perl legacy problem, see:"
print "\n[https://unix.stackexchange.com/a/375505/291375][1]"
print "\nI'm outta here.";
print "\n Sincerely, bballdave025";
print "\n";
print "\n";
return;
}#endof: if (<problem 1>)
if ( $testId eq "test2-sastt" &&
$operation eq "test" &&
$options eq "-G -f rttm -F rttm -a" &&
$outDir eq "test2-sastt.test" ) # <problem 2>
{
print "\n";
print "\n#### SKIPPING ####";
print "\nJust kidding. That breaks the make.";
print "\nIt said: \n\n";
print "\nError: Test test2-sastt has failed. Diff output is :";
print "\ndiff -i -x CVS -x .DS_Store -x log -x '*lur' -I '[cC]reation[ _]date' -I md-eval -r test2-sastt.test/sastt-case2.sys.rttm.filt.alignments/segmentgroup-116.html test2-sastt.base/sastt-case2.sys.rttm.filt.alignments/segmentgroup-116.html";
print "\n 45c45";
print "\n < jg.drawStringRect(\"SUB48\",0, 47, scale*656, \"left\");";
print "\n ---";
print "\n#### and a whole bunch of other draw stuff! ####";
print "\n1 at ./RunTests.pl line 61.\n\n";
print "\n"
print "\nThat looks like Java drawing code, and I don't"
print "\neven want to mess with it!"
print "\nI'm outta here.";
print "\n Sincerely, bballdave025";
print "\n";
print "\n";
return;
}#endof: if (<problem 2>)
system ("mkdir -p $outDir")
Now you should be able to get through. Try it:
make check

Improving g++ output

g++ sometimes produces pretty convoluted outputs. Specially when dealing with templates. Is there any tool that makes g++ output more readable? ... at least some color?
It may sound silly to ask this question here, but I've been unable to google my way out of this.
GCC as of 4.9 has colourized output ☺
Append the following to your bashrc/zshrc/whatever.
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
If you're free to switch compiler, try clang++. It's error outputs are most of the time very clear and sometimes it will even tell you what to do to fix your error. You can find a comparison of gcc vs clang error output here: http://clang.llvm.org/diagnostics.html.
Otherwise, as noted by Matteo Italia, look to STLFilt.
For the color aspect, Edwin Buck's solution (colorgcc) is very good. You can create symlinks to it named gcc, g++, etc so that it always gets used whenever you run a compiler command (provided you setup the paths in the colorgcc script correctly). I find this especially convenient when compiling some large project from a Makefile. Helps tremendously to detect where exactly something went wrong (especially when you do parallel compilations with make -j).
There's colorgcc, a perl script which wraps the gcc (g++) output with color for easier readability.
As far as the "output" of gcc (g++) I am guessing you're not complaining about the compiled binaries :)
I improve it by using sed to color the output with this script:
#!/bin/bash
while read x ; do echo $x ; done \
| sed -e "s/.*error:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/.*warning:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/^\(.*\)\(required from\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In instantiation of\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In member\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
| sed -e "s/error:/\x1b[1;31m&\x1b[1;36m/" \
-e "s/warning:/\x1b[1;35m&\x1b[1;36m/" \
-e "s/note:/\x1b[1;30m&\x1b[0m/"
If you use gcc 4.9 or higher there are a couple built-in options:
-fmessage-length=n, which optimizes the output for lines of n characters length.
-fdiagnostics-color=always, which applies some nice colors. (Works fine on linux, not so much on msys)
For more options and exact usage heres the documentation:
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html
When dealing with the STL1, STLFilt comes to the rescue.
On a related note, I also heard that the clang compiler produces by itself much better error messages in general.
Nitpickers' corner
Actually, not the SGI STL, but the parts of it that have been adopted in the C++ standard and are part of the standard library.
I can't answer your question directly, but note that in regards to templates if you look at the top message (the error caused by the templated) and the bottom "instantiated from here" message, it usually becomes much more clear. Ignore all the middle messages as they are probably not going to help.
There is colorgcc.
there is my personal function:
colorgcc()
{
perl -wln -M'Term::ANSIColor' -e '
m/not found$/ and print "\e[1;30m$`\e[0m", "$&", "\e[0m"
or
m/found$/ and print "\e[1;30m$`\e[0;32m", "$&", "\e[0m"
or
m/yes$/ and print "\e[1;30m$`\e[0;32m", "$&", "\e[0m"
or
m/no$/ and print "\e[1;30m$`\e[0m", "$&", "\e[0m"
or
m/ Error |error:/i and print "\e[1;91m", "$_", "\e[0m"
or
m/ Warning |warning:/i and print "\e[0;33m", "$_", "\e[0m"
or
m/nsinstall / and print "\e[0;36m", "$_", "\e[0m"
or
m/Linking |link: |\.a\b/ and print "\e[1;36m", "$_", "\e[0m"
or
m/Building|gcc|g++|\bCC\b|\bcc\b/ and print "\e[1;30m", "$_", "\e[0m"
or
print; '
}
you can use GilCC which is a Ruby tool that will convert GCC output to color in real-time. It is free and you can customize it to your preference. It is not intrusive as it does not change your gcc setup and you don't have to edit any system files such as .bash. You have to install Ruby and be able to invoke Ruby programs from the command line. Right now you have two options Perl script or GilCC and if you work with Ruby you will like GilCC.
Then whenever you call "GillCC" it will call "make" behind the scenes with your parameters such as "clean", "debug" or "release". for example if normally you call: "make debug" you should call "GilCC debug".
Almost forgot to mention that GilCC has some statistics such as # of warnings and error as well as build time. These things are handy when you are trying to improve your build.
The link to the download page is here.

Is there any way to get readable gcc error and warning output at the command line?

For some long errors, the gcc output is dense and has lots of line-wrapping etc. Especially when errors are subtle, it can take me 10-30 seconds of squinting to parse it with my eyes.
I've taken to pasting this in an open code-editor window to get some basic syntax highlighting and enable reformatting with regex's.
Has anyone invented a more automated method?
I use this script, called colorize:
#!/bin/bash
while read x ; do echo $x ; done \
| sed -e "s/.*error:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/.*warning:.*/\x1b[1;36m&\x1b[0m/" \
-e "s/^\(.*\)\(required from\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In instantiation of\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
-e "s/^\(.*\)\(In member\)/\x1b[1;36m\1\x1b[0mnote: \2/" \
| sed -e "s/error:/\x1b[1;31m&\x1b[1;36m/" \
-e "s/warning:/\x1b[1;35m&\x1b[1;36m/" \
-e "s/note:/\x1b[1;30m&\x1b[0m/"
Then I just call it like this(using make or whatever build system):
make |& colorize
And I get color output similar to clang.
I've found colorgcc to be invaluable. By introducing coloring, it becomes much easier to mentally parse the text of gcc error messages, especially when templates are involved.
If your errors are template related, take a look at STLfilt:
http://www.bdsoft.com/tools/stlfilt.html
gccfilter does coloring & simplification of messages.
http://www.mixtion.org/gccfilter/
If you use GCC 4.9, you can add -fdiagnostics-color=auto as an additonal compilation flag. At some later version, the color has been enabled by default.
check diagcc out, you can get something like this:
If your gcc ≥ 4.9, you can use argument -fdiagnostics-color=always.
To answer your question 4 years later, clang should be mentioned here.
Here's my current hack, which mostly inserts newlines and indentation in strategic locations along with a little extra annotation, but does nothing to address STL verbosity.
Note that as currently implemented, this script does not return an error if the compiler returned one, so doing something like this will not work properly: (make && ./runApplication). This could surely be remedied by someone with better bash-fu.
#!/bin/bash
# SUBSTITUTION RULES:
# Note: All substitution rules must end in a semi-colon, inside of the closing quote
subColonSpace='s/: /:\n /g;'
subSrc='s/^src/\nsrc/;'
subError='s/error:/error:\n\n======================================\nERROR:/;'
subWarning='s/ *error: *\n/ERROR: /;'
subWarning='s/ *warning: *\n/WARNING: /;'
subNote='s/note:/\n NOTE:/g;'
subOpenTic='s/‘/\n ‘/g;'
subOpenParen='s/(/(\n /g; s/(\n *)/()/g;'
subCommaSpace='s/, /,\n /g;'
# Note: The order of these may matter
sedExpr="$subColonSpace $subSrc $subError $subWarning $subNote $subOpenTic
$subOpenParen $subCommaSpace"
makelogFile=makelog.tmp
make "$#" 2>&1 | sed "$sedExpr" | tee $makelogFile
if you like Ruby there is GilCC! GilCC is very easy to install (just copy it to the bin folder) and easy to use (just type GilCC instead of "gcc" or "make") and it works with GCC version. Unlike Perl based scripts GilCC has statistics such as # of warnings and error and compile time. You don't have to mess with .bash files and it is cross platform as long as you can run Ruby on your machine. Since it has the power of Ruby; you can make GilCC do different things such as trigger test automation, unit test or program external hardware after a successful build.
Here is the link to the download page: http://www.onlysolutionssoftware.com/gilcc/