23

Trying to combine ccache and colorgcc. Following link text:

  • my g++ is soft link to colorgcc
  • ~/.colorgccrc contains line: "g++: ccache /usr/bin/g++"

When running g++ --version receive:

Can't exec "ccache  /usr/bin/gcc": No such file or directory at /usr/lib/perl5/5.8.8/IPC/Open3.pm line 246.
open3: exec of ccache  /usr/bin/gcc --version failed at /usr/local/bin/colorgcc/gcc line 208

Any ideas how to solve it?

dimba
  • 26,717
  • 34
  • 141
  • 196
  • 1
    that page says "Note: colorgcc version 1.3.2-5 (Debian) had problems with the described setup. colorgcc version 1.3.2-6 (Debian) fixed these problems.", which version are you using? – Hasturkun Jan 03 '10 at 16:37
  • I dowloaded the "official" colorgcc from http://schlueters.de/colorgcc.html and it doesn't supports configuration of type ""g++: ccache /usr/bin/g++"". I tried to look at colorgcc distributed by debian and it's working. – dimba Jan 03 '10 at 18:33

7 Answers7

24

Just came across this same issue. For me, the problem could be solved by carefully setting environment variables:

# Make "g++" command call colorgcc
export PATH="/usr/lib/colorgcc/bin:$PATH"

# Tell ccache to invoke compilers in /usr/bin
export CCACHE_PATH="/usr/bin"

Then all I had to do was edit colorgcc's config file (/etc/colorgcc/colorgcc or ~/.colorgcc) and tell it to call ccache instead:

g++: /usr/lib/ccache/bin/g++
gcc: /usr/lib/ccache/bin/gcc
c++: /usr/lib/ccache/bin/g++
cc:  /usr/lib/ccache/bin/gcc
g77: /usr/lib/ccache/bin/g77
f77: /usr/lib/ccache/bin/g77
gcj: /usr/lib/ccache/bin/gcj

This of course only works if you have colorgcc's symlinks installed in /usr/lib/colorgcc/bin and ccache's symlinks in /usr/lib/ccache/bin - adjust accordingly.

Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • 2
    I've solved it already indeed in same way as you - colorgcc calls ccache, which calls gcc. This way colorgcc colorizes output of ccache. My mistake was that ccache was calling colorgcc, which is conceptually incorrect. – dimba May 02 '11 at 13:57
  • 3
    The configuration files for `colorgcc` are called `/etc/colorgcc/colorgccrc` and `~/.colorgccrc` (at least in my distro). Works great otherwise, thanks. – drrlvn Aug 25 '11 at 12:39
  • Excellent work. The first time I tried this, it failed to work, but that was only because I had failed to follow your instructions to the letter! :-) – chriv Oct 01 '12 at 16:16
  • One last thing (and I really don't want to start a whole new question for something so minor): Does anyone know if it is possible to preserve the colors from colorgcc when redirecting stdout and stderr into a file or when piping into a pager (like "less")? – chriv Oct 01 '12 at 16:17
  • @chriv: From reading the source, it looks like you can set the environment variable `CGCC_FORCE_COLOR` to some value to make it always colourise the output. – Malvineous Oct 01 '12 at 22:05
17

The Short Answer

Without patching colorgcc.pl itself, the easiest way to fix this is to write yourself a simple wrapper script for each command, calling ccache with the appropriate arguments for that command, and passing along the arguments the script received (effectively currying the call to ccache.)

E.g., for gcc:

  • /usr/local/bin/ccache-gcc.sh:

    #!/bin/bash
    ccache /usr/bin/gcc "$@"
    
  • ~/.colorgcc:

    gcc: /usr/local/bin/ccache-gcc.sh
    

and for g++:

  • /usr/local/bin/ccache-g++.sh:

    #!/bin/bash
    ccache /usr/bin/g++ "$@"
    
  • ~/.colorgcc:

    gcc: /usr/local/bin/ccache-g++.sh
    

There are ways to clean this up so that you only use a single script, with symlinks for each variant, but those are beyond the scope of this answer, and I leave them to you as an excercise :-)

The Long Answer

The problem is that the script treats everything to the right of the colon in the prefs file as the "command" passed to exec, not as the "command" and extra "arguments". I.e., in your case, the script ends up trying to do this:

  • Incorrect:

    exec "ccache /usr/bin/g++" "--version"
    

    (i.e., "ccache /usr/bin/g++" is a single argument.)

But it should be doing this:

  • Correct:

    exec "ccache" "/usr/bin/g++" "--version"
    

    (i.e., "ccache" and "/usr/bin/g++" are two separate arguments.)

Perl's exec ultimately calls execvp, after possibly applying some "do what I mean" logic to its arguments. execvp then does some DWIM of its own. Perl's exec pre-processing, which splits up a single argument string into the multiple arguments execvp expects, only kicks in when exec receives a single argument. In colorgcc.pl, the call to exec looks like this (roughly):

exec "${program}" @ARGV

where ${program} comes from your configuration (or the defaults), and @ARGV is the list of arguments you passed when you (indirectly) invoked colorgcc.pl. In your case, ${program} is, literally, ccache /usr/bin/g++ (a single string, as noted above,) when it ought to be just ccache, with /usr/bin/g++ being prepended to @ARGV.


(Some of you may wonder why I've gone to all the trouble of explaining this, when it's a one-line fix to colorgcc.pl. That's true, but if I just did that, the world would lose another opportunity to learn about this class of errors. Plus, I wouldn't get as many votes.)

Tripp Lilley
  • 1,653
  • 16
  • 21
1

As others have already said, it is a matter of setting up paths and symbolic links.

Follow the invaluable Arch guide on this.

I do this so many times and is such a tricky setup that I ended up setting up a docker wrapper with the right configuration.

You can check it out here

In short, use this alias

alias mmake='docker run --rm -v "$(pwd):/src" -t ownyourbits/mmake'

and do mmake instead of make

nachoparker
  • 1,678
  • 18
  • 14
0

The Quick Answer

Better not to modify any system files. here is some variables & a simple colorgcc shell function to pipe the output of your compilation. You loose the return code but you can handle that differently if you really need it.

n=$(tput setaf 0)
r=$(tput setaf 1)
g=$(tput setaf 2)
y=$(tput setaf 3)
b=$(tput setaf 4)
m=$(tput setaf 5)
c=$(tput setaf 6)
w=$(tput setaf 7)
N=$(tput setaf 8)
R=$(tput setaf 9)
G=$(tput setaf 10)
Y=$(tput setaf 11)
B=$(tput setaf 12)
M=$(tput setaf 13)
C=$(tput setaf 14)
W=$(tput setaf 15)
END=$(tput sgr0)

colorgcc()
    {
    perl -wln -M'Term::ANSIColor' -e '
    m/not found$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
    or
    m/found$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
    or
    m/yes$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
    or
    m/no$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
    or
    m/undefined reference to/i and print "$ENV{r}", "$_", "$ENV{END}"
    or
    m/ Error |error:/i and print "$ENV{r}", "$_", "$ENV{END}"
    or
    m/ Warning |warning:/i and print "$ENV{y}", "$_", "$ENV{END}"
    or
    m/nsinstall / and print "$ENV{c}", "$_", "$ENV{END}"
    or
    m/Linking |\.a\b/ and print "$ENV{C}", "$_", "$ENV{END}"
    or
    m/Building|gcc|g\+\+|\bCC\b|\bcc\b/ and print "$ENV{N}", "$_", "$ENV{END}"
    or
    print; '
    }

use it like that :

./configure | tee -a yourlog.configure.log | colorgcc
make | tee -a yourlog.make.log | colorgcc
make install | tee -a yourlog.install.log | colorgcc
scavenger
  • 11
  • 1
0

Here is how to patch colorgcc. The problem is with

exec $compiler, @ARGV

and

$compiler_pid = open3('<&STDIN', \*GCCOUT, '', $compiler, @ARGV);

$compiler is in your case "ccache /usr/bin/g++". We need to change it so that $compiler is ccache and /usr/bin/g++ is prepended to @ARGV

After the line

$progName = $1 || $0;

do following modifications:

$shell_command = $compilerPaths{$progName} || $compilerPaths{"gcc"};
@shell_array = split(' ',$shell_command);
$compiler = shift @shell_array;
if ( scalar (@shell_array) > 0 ) {
  unshift (@ARGV, @shell_array);
}

replacing the line

$compiler = $compilerPaths{$progName} || $compilerPaths{"gcc"};

Jirka

Jirka
  • 365
  • 2
  • 8
0

For me the best solution is this one. After installing ccache on Fedora I have following in my PATH:

PATH=/usr/lib64/ccache:/usr/local/bin:/usr/bin:/bin

and gcc command will call ccache binary:

which gcc

/usr/lib64/ccache/gcc

To create a call chain gcc -> color-gcc -> ccache -> gcc

I need just to create following aliases:

alias gcc="color-gcc"
alias g++="color-gcc"

Put these two lines at the end of ~/.bashrc and you are done! No need to create the symlinks or fix the color-gcc source.

(In case you are using other shell than BASH you will need to put the aliases into the appropriate shell settings file)

Jirka

Jirka
  • 365
  • 2
  • 8
0

there is another way to colorize GCC that I think it is much easier to install because you don't have to edit any system files such as .bash Moreover it is based on Ruby which allows wide customization using Ruby gems. For example GilCC shows # of warnings, # of errors and compile time, very handy when you want to cleanup or improve build time.

here is the link to stackoverflow that talks about GilCC:

Improving g++ output

Community
  • 1
  • 1
Gilson
  • 1,708
  • 3
  • 16
  • 21