What is the difference between ar/nm and gcc-ar/gcc-nm?

Cherry Vanc picture Cherry Vanc · Feb 14, 2018 · Viewed 7.1k times · Source

ar, nm, and ranlib are provided by the binutils package. gcc-ar, gcc-nm, and gcc-ranlib are provided by the GCC package. I read somewhere that the gcc-ar, gcc-nm, and gcc-ranlib are "effectively wrappers" around the ar, nm, and ranlib binaries respectively.

What is the technical difference between the gcc-ar, gcc-nm, and gcc-ranlib vs. ar, nm, and ranlib? There must be a reason why GCC provides these binaries in its builds.

When should a build system of a userland package use one vs. the other? If the toolchain being used to build a userland package is GCC based, does it matter which one you use (e.g., ar vs gcc-ar, nm vs gcc-nm)?

Answer

Mike Kinghan picture Mike Kinghan · Feb 15, 2018

gcc-ar is a wrapper for GNU ar such that a command:

gcc-ar ...

is equivalent to:

ar --plugin=/path/to/liblto_plugin.so ...

On my present system, Ubuntu 17.10, GCC 7.2, that would be e.g:

ar --plugin=/usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so

There is just the same relationship between nm and gcc-nm.

The --plugin option of the binutils ar and nm enables them to dynamically load a recognizer/analyser for some non-default format of object file that they have to deal with.

The shared library liblto_plugin.so is one that enables them to deal with the IR (intermediate representation) object files produced and consumed in link-time-optimized builds.

So, if you would do your plain old build like this:

$ gcc -c main.c foo.c bar.c
$ ar cr libfoobar.a foo.o bar.o
$ gcc -o prog main.o -L. -lfoobar

then you'd do your link-time-optimized build like:

$ gcc -flto -c main.c foo.c bar.c
$ gcc-ar cr libfoobar.a foo.o bar.o
$ gcc -flto -o prog main.o -L. -lfoobar

In recent releases of binutils - I don't know which was the first; within the last 3 or 4 years - liblto_plugin.so has been loaded by default by ar and nm; so in fact:

$ gcc -flto -c main.c foo.c bar.c
$ ar cr libfoobar.a foo.o bar.o
$ gcc -flto -o prog main.o -L. -lfoobar

will work fine; and nm foo.o will work fine. But the gcc-* versions still serve a purpose in being independently shipped with GCC, since your regular ar and nm might not support that default, and if not then that last build, for instance, would fail in the linkage with undefined references, since ar would fail to insert in the archive a true symbol table for foo.o and bar.o.