This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: g++4.4 - managed to compile but can't run g++


Simon Hill wrote:

> DISCLAIMER: I'm not sure if this is the right forum/place to post
> this. If there is a more appropriate forum then sorry, but please
> direct me to it. END.

This is the proper mailing list.

> "cd /make/gcc-4.4-20080808"
> "mkdir target"
> "cd target"
> "../configure --disable-multilib"
> "make" (left overnight - takes many hours)
> "cd gcc"
> "g++ --version" reports 4.4 as above.
> "g++ /make/test/test.cpp" reports the error posted above.

You've built gcc but not installed it.  gcc is not meant to be used from
the build tree without being installed, except by the testsuite which
has specific infrastructure for doing this.

To install gcc, run "make install".  This will install gcc in the
--prefix that you configured with, which defaults to /usr/local since
you didn't supply a --prefix.  That's usually a fine default, as that is
the common place for non-distro-provided self-compiled things.  On most
distros normal users don't have write access to /usr/local so you'll
probably have to change to root first (or use sudo) or else configure
with a prefix where you do have write access.

After "make install" finishes you will need to add /usr/local/bin to
your PATH.  Most distros already add this to PATH by default in one of
the shell startup rc files, so you probably don't have to do anything. 
Note also that since you didn't use --program-prefix or --program-suffix
(or anything fancy like that) the new gcc will simply be named 'gcc',
'g++' etc.  Since you also have a system compiler of the same name in
/usr/bin, this means the order of PATH will determine which gets used
when you invoke 'gcc'.  You can change this by explicitly naming the
compiler, e.g. '/usr/local/bin/gcc', or reordering PATH, or you can
configure your gcc to have a different name.  For example if you used
--program-suffix=-4.4 then after "make install" you would have gcc-4.4,
g++-4.4 and so on.

Finally, there is the matter of notifying the dynamic linker of the new
shared libraries you just installed.  This is a more complicated subject
and there are multiple ways of solving it, some which require action at
run-time and some at link-time.

Firstly, you need to determine the location where the shared libraries
were installed.  This defaults to something resembling
$prefix/lib/gcc/$target, possibly with lib64 or lib32 instead of lib
(although not in your case since you disabled multilibbing.)  There
could be a version number in there on the end if you used
--enable-version-specific-runtime-libs which is useful if you want to
install multiple versions of gcc into the same prefix.  You can have gcc
tell you the name of the location with something like:

dirname $(gcc -print-libgcc-file-name)

This should be the directory that contains the shared libraries (*.so)
for libgcc_s, libstdc++, libgfortran, and so on.  Once you have this
directory (call it FOO) you need to decide how you want to tell the
dynamic linker to search there:

- add FOO to /etc/ld.so.conf and rerun ldconfig
- add FOO to the environment variable LD_LIBRARY_PATH at run-time (which
is a colon separated list like PATH)
- hard-code the path when linking your program, e.g. -Wl,-rpath,FOO
- hard-code a rpath, but by adding FOO to LD_RUN_PATH at link-time
instead of changing the link command

There are all sorts of various philosophies about the best way to handle
this topic.  Adding the path to the dynamic linker's global search list
(ld.so.conf) is probably the most direct and simple, but it requires
root.  Sometimes you don't have that, such as if you are a mere user of
the system and want to install gcc under your home directory.

Adding it to LD_LIBRARY_PATH is the next most simple, but the problem
here is that this environment variable must contain the location every
time the app is run, not just when it was linked.  This means adding it
to your shell startup scripts somewhere or otherwise having it always
set.  This can get complicated if you start to accumulate multiple paths
that need to be added, or if you have two dirs with similar but
incompatible SONAMEs and so requiring different settings of the variable
for the different apps.  Sometimes people write wrapper scripts that set
LD_LIBRARY_PATH and then invoke their app to simulate the need for it
not to be set.

Using an rpath -- either by giving it directly on the link command or
setting LD_RUN_PATH at link-time -- has the desirable quality that it
only need be set once, at link-time.  The value is hard coded into the
linked executable and that file forever knows where to search for its
shared libraries.  The problem is evident: if you need to later move or
upgrade those shared libraries you need to relink everything.

You don't have to worry about any of this with the system provided
compiler because the packages from your distro put shared libraries in
the standard locations that the dynamic linker already knows to search
for, such as /lib and /usr/lib.  If you really know what you are doing,
you can do this too.  However, this is extremely dangerous because your
package manager expects to be in control of those dirs and it might
overwrite your copies when you upgrade packages later.  This is in
addition to the very real problem of ABI versioning that can be rather
complex.  It's much safer and more direct to just to keep your
self-compiled things sequestered in their own place under /usr/local (or
whereever you prefer, such as under $HOME) away from the package
manager, and deal with telling the dynamic linker about them using one
of the above methods.

If you don't address the issue at all, i.e. do none of the above, then
your program *may* work or it *may* fail.  The problem is that there
will be a version difference between the shared libraries that the
program was linked with and what is found by the dynamic linker at
runtime -- keep in mind these are two different linkers!  At runtime the
dynamic linker will find the system copy in /lib or /usr/lib (because
you didn't tell it to search elsewhere), but at link time the version
used will correspond to the version associated with the gcc used to
link.  On GNU/Linux systems most important shared libraries like
libgcc_s and libstdc++ use symbol versioning, the purpose of which is to
gracefully allow such a difference.  However this concept can only work
in one direction -- a newer version found at runtime than at linktime. 
It can't work in the other direction.  This generally means that the
distro can upgrade the system copy to a newer version without breaking
backwards compatibility and having to relink everything, but if you
built a newer gcc than the system gcc you're in for trouble if the
dynamic linker finds the older version in the system location at
runtime.  But maybe you just get lucky and the interfaces you happened
to use were compatible between the versions.  It's kind of a version of
russian roulette though, so you can't in good faith ignore this issue
and hope everything will just work out.

Brian


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]