GCC & binutils build - C compiler cannot create executables - c++

I'm trying to build gcc-5.3 and binutils-2.26. I've done it like this:
mkdir gcc; cd gcc
wget http://path/to/gcc-5.3.0.tar.bz2
wget http://path/to/binutils-2.26.tar.bz2
tar xf gcc-5.3.0.tar.bz2
tar xf binutils-2.26.tar.bz2
cd gcc-5.3.0
contrib/download_prerequisites
for file in ../binutils-2.26/*; do ln -s "${file}"; done
cd ..
mkdir build
mkdir dist
cd build
../gcc-5.3.0/configure --prefix=/home/teamcity/gcc/dist --disable-multilib --with-system-zlib --enable-languages=c,c++,fortran --program-suffix=-mine
make
This appears to build the first stage executables okay; prev-gas, prev-gcc, prev-ld are all present with plausible-looking executables in them. But the next stage fails:
Configuring stage 2 in ./intl
configure: loading cache ./config.cache
checking whether make sets $(MAKE)... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking whether NLS is requested... yes
checking for msgfmt... /usr/bin/msgfmt
checking for gmsgfmt... /usr/bin/msgfmt
checking for xgettext... /usr/bin/xgettext
checking for msgmerge... /usr/bin/msgmerge
checking for x86_64-unknown-linux-gnu-gcc... /home/teamcity/gcc/build/./prev-gcc/xgcc -B/home/teamcity/gcc/build/./prev-gcc/ -B/home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/bin/ -B/home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/bin/ -B/home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/lib/ -isystem /home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/include -isystem /home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/sys-include -L/home/teamcity/gcc/build/./ld
checking for C compiler default output file name...
configure: error: in `/home/teamcity/gcc/build/intl':
configure: error: C compiler cannot create executables
See `config.log' for more details.
The relevant bit of config.log appears to be this:
configure:2978: checking for C compiler default output file name
configure:3000: /home/teamcity/gcc/build/./prev-gcc/xgcc -B/home/teamcity/gcc/build/./prev-gcc/ -B/home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/bin/ -B/home/teamcity/gcc/dist/x86_64-unkn
own-linux-gnu/bin/ -B/home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/lib/ -isystem /home/teamcity/gcc/dist/x86_64-unknown-linux-gnu/include -isystem /home/teamcity/gcc/dist/x86_64-unknown-l
inux-gnu/sys-include -L/home/teamcity/gcc/build/./ld -g -O2 -gtoggle -static-libstdc++ -static-libgcc conftest.c >&5
/home/teamcity/gcc/build/./prev-gcc/as: 106: exec: /home/teamcity/gcc/build/./gas/as-new: not found
This looks like prev-gcc's as is expecting to find gas/as-new, when actually it's prev-gas/as-new.
Is there some workaround for this? Is it safe to just ln -s prev-gas gas? I'd sort of expect that to cause problems later on. Is it not possible to build these two versions of gcc and binutils together?

This is my edited answer after trying it on my own on an Ubuntu 14.04 Azure VM.
The following approach worked for me:
Build and install binutils 2.26; for the purposes of this discussion,
let's say it's installed in /opt/gcc-5.3.0.
Configure gcc-5.3.0 in a build directory using /root/objdir/../gcc-5.3.0/configure --prefix=/opt/gcc-5.3.0
--enable-languages=c,c++ --disable-multilib --with-ld=/opt/gcc-5.3.0/bin/ld --with-as=/opt/gcc-5.3.0/bin/as assuming gcc-5.3.0 and the build directory, objdir, are at the same
level.
Do make followed by make install in the objdir build directory.
To verify that the ld used by the newly-built gcc is the one from the new binutils:
/opt/gcc-5.3.0/bin/gcc -print-prog-name=ld
The output should be, in this example:
/opt/gcc-5.3.0/bin/ld
Another test: rename the system ld, in my case /usr/bin/ld; the newly-built gcc should still work.
Of course, this applies to both ld and as.
Setting AS and LD environment variables to point to the newly-built binaries from the binutils package did not work: the -print-prog-name=... still showed default tools, and removing/renaming the default tools caused gcc to fail.
Thus the best way of accomplishing this is to build binutils first and then use the --with-ld and --with-as options to configure. If you also want to ensure that the newly-built binutils are used to build GCC, you may want to put them in the PATH before the system-provided tools, or you can even rename the system-provided tools to keep them out of the picture.
Thank you for checking with another mailing list to verify that building GCC and binutils together doesn't work unless they are pulled from the source control, I guess that option is not applicable when using downloaded tarballs. Overall this was an interesting exercise.

Related

Cross-compile and link libstdc++ for i686-elf (using g++ on Ubuntu 16.04)

Believe me I've spent quite some time Googling without much of an outcome.
I'm writing a very basic OS as a fun project. It, for obvious reasons, needs to be compiled into a standalone form (i686-elf in my case). However I've decided that pure C isn't enough for me and that I'd love to use C++. So I've written a bit of code and it seemed to work, so I went on and all of sudden I kept getting the same error despite no obvious problem with the code.
./sh/../obj/class_string.o:(.eh_frame+0x4f): undefined reference to __gxx_personality_v0'
./sh/../obj/kernel.o:(.eh_frame+0x13): undefined reference to __gxx_personality_v0'
/home/natiiix/crosscompiler/out/path/bin/../lib/gcc/i686-elf/6.1.0/libgcc.a(unwind-dw2.o): In function read_encoded_value_with_base':
/home/natiiix/crosscompiler/out/src/build-gcc/i686-elf/libgcc/../../../gcc-6.1.0/libgcc/unwind-pe.h:257: undefined reference to abort'
After a bit of Googling I've figured out the problem must be that my g++ cross-compiler lacks c++ libs, which turned out to be true. It indeed contains just libgcc and libgcov. So I've figured out I'd get them somehow, but it turned out to be quite a difficult task to do. It's virtually impossible to find the already compiled libstdc++.a. So I had to compile it myself and as I'm not particularly familiar with makefile it definitely wasn't easy to figure out.
Finally I've found a bash script that somewhat allowed me to do what I needed. It downloads gcc 6.1.0, binutils, configures both and runs make, make install. That would be really nice if it actually worked. The compiler itself works like a charm as far as I can tell at least, but the library won't work no matter what I do since, at least I suspect, it is being built for a different target platform for some reason. It appears that libstdc++ simply cannot be built for i686-elf or something along the lines.
gccbuild.sh:
#!/bin/bash
set -e
if [ "$#" -ne 1 ]; then
echo "Supply one parameter: the target to use!!"
exit 1
fi
sudo apt install libgmp3-dev libmpfr-dev libisl-dev libcloog-isl-dev libmpc-dev texinfo -y
cd "$(dirname "$0")"
rm -rfv out/
mkdir out/
cd out/
rm -rfv path/
mkdir path/
rm -rfv src/
mkdir src/
cd src/
wget ftp://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz
wget ftp://ftp.gnu.org/gnu/gcc/gcc-6.1.0/gcc-6.1.0.tar.gz
tar -xvzf binutils-2.26.tar.gz
tar -xvzf gcc-6.1.0.tar.gz
export PREFIX="$(pwd)/../path/"
export TARGET=$1
export PATH="$PREFIX/bin:$PATH"
rm -rfv build-binutils/
mkdir build-binutils/
cd build-binutils/
../binutils-2.26/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-werror
make
make install
cd ..
rm -rfv build-gcc/
mkdir build-gcc/
cd build-gcc/
../gcc-6.1.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc
../gcc-6.1.0/libstdc++-v3/configure --host=$TARGET --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --disable-libstdcxx-threads
make
make install
My compile / link script (so that you can see the g++ arguments):
${BASH_SOURCE%/*}/../../crosscompiler/out/path/bin/i686-elf-g++ -c ${BASH_SOURCE%/*}/../src/*.cpp --std=c++11 -ffreestanding -O2 -Wall -Wextra
echo moving object files from active directory to obj/
mv *.o ${BASH_SOURCE%/*}/../obj/
${BASH_SOURCE%/*}/../../crosscompiler/out/path/bin/i686-elf-g++ -T ${BASH_SOURCE%/*}/../src/linker.ld -o ${BASH_SOURCE%/*}/../bin/kokos.bin -ffreestanding -O2 -nostdlib ${BASH_SOURCE%/*}/../obj/*.o -lgcc -lstdc++ -lsupc++
When I try to link those libraries (versions of libstdc++ and libsupc++ that appear to be elf32-i386, which is as close as they get to the i686-elf) I stop getting the undefined reference to __gxx_personality_v0, but I still get a handful of undefined references to what appear to be C functions. (abort, strlen, malloc, free)
The whole problem can be avoided by not using templates, class destructors and some more c++ specific stuff (ironically classes alone seem to work just fine for the most part), but it doesn't seem like a very good solution to me. I'd rather have access to such things.
Could someone please explain to me what have I done wrong?
It is not clear from your post what exact result you want to get. Below there are few observations that may help you to figure out what your real problems are.
First, if you need 32-bit code to be compiled on your (I guess) 64-bit Ubuntu host, you do not need a cross toolchain, just compile it with -m32.
If you want your code to be optimized for specific CPU variant, just use appropriate -march=, -mcpu= and -mtune= options.
If you need your 32-bit program to be statically linked with C++ libraries, then on Ubuntu you just need to install a package libstdc++-6-dev:i386. Run sudo apt-get install libstdc++-6-dev:i386, it will also install all necessary dependencies. Then just compile your program with gcc -m32 -static.
If you need to use standard libraries optimized for specific CPU, rather than for generic i386 then you need to build them manually. This is true not only for libstdc++, but also for libc (IIRC, Ubuntu 16.04 still uses generic -march=i386 option to build libc, Ubuntu 16.10 uses -march=i686).
You got the undefined references from your link output because you are using -nostdlib and -lstdc++ but not -lc. libstdc++ uses the functions from standard C library,so you need it.
As you develop an OS kernel and you need a freestanding environment, I suppose that you really do not need standard libraries. In that case refer to C++ standard, clause 17.6.1.3, to find which standard headers you may use in your application. You have to use -lsupc++ -lgcc on your compiler command line and additionally you need -lgcc_eh if you use exception handling (and libgcc_eh.a is where __gxx_personality_v0 comes from). Do not use -lstdc++ in a freestanding environment!
Hope this helps a bit and have a good luck!

How to force clang to use some library by default?

I build clang by clang against libc++, libc++abi, compiler-rt in the following steps:
To download (and update) llvm and sub-projects I use the following script:
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk clang/tools/extra
svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
svn co http://llvm.org/svn/llvm-project/lld/trunk lld
svn co http://llvm.org/svn/llvm-project/polly/trunk polly
cd ../projects/
svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind
svn co http://llvm.org/svn/llvm-project/openmp/trunk openmp
svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi
svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx
First of all I build llvm, clang, libunwind against libgcc and libstdc++ using gcc and install them in /usr/local. In all the following steps except the last one I use this fresh clang/clang++.
Then I separately build libunwind, both the 32-bit and 64-bit versions (they are essential, as will be further, because asan needs the 32-bit versions of some libraries during the final compilation of the whole project tree) and install it in /usr/local/lib and /usr/local/lib32 correspondingly (also I update LD_LIBRARY_PATH respectively).
Build libcxxrt ABI library both 32-bit and 64-bit versions and install them properly.
Build libcxx against libcxxrt both 32-bit and 64-bit versions and install them properly.
Then build libc++abi against libc++ both 32-bit and 64-bit versions and install them properly.
Then build libc++ against libc++abi both 32-bit and 64-bit versions and install them properly over the previous version linked to libcxxrt.
After all I build the whole project tree against libc++, libc++abi, libunwind, compiler-rt and install it over old clang in /usr/local.
(I am almost sure that no step is redundant here.)
At the final step I have a problem: I have to add extra parameters to the linker (I add them to CMAKE_EXE_LINKER_FLAGS and CMAKE_SHARED_LINKER_FLAGS) -lunwind and -lc++abi. Moreover, every time I use the resulting clang++ with -stdlib=libc++ and compiler-rt (or, equally, CLANG_DEFAULT_CXX_STDLIB=libc++ and CLANG_DEFAULT_RTLIB=compiler-rt) in my projects I have to do it over and over. It annoying. Say Qt Creator generated project's CMakeLists.txt should be corrected by hand or by cmake-gui.
How to make clang driver to automatically specify these options to ld at runtime? Is there something similar to RPATH mechanism? Or is there some specific CMake variable (specified before llvm building process) to achieve desired behaviour?
Can I use RPATH for my purposes?
Surely I don't want to make some bash-script like wrappers (similar to clang++-libc++) to specify additional parameters. I want the libraries to be hardcoded somewhere in the clang binary itself.
There are a couple of workarounds have been suggested. I ended up with the following workaround:
mkdir build
cd build
# backup:
cp -vaf /usr/local/lib/libc++.{a,so.1.0} /usr/local/lib/libc++abi.{a,so.1.0} /usr/local/lib/libunwind.{a,so.1.0} .
clang -shared -fPIC -pthread -o fuse.so -Wl,--whole-archive libc++.a libc++abi.a libunwind.a -Wl,--no-whole-archive -ldl -lm
ar x libc++.a
ar x libc++abi.a
ar x libunwind.a
ar rc fuse.a *.o
sudo chown root:root fuse.*
sudo cp -vaf fuse.so /usr/local/lib/
sudo ln -svf /usr/local/lib/libc++.so.1 /usr/local/lib/fuse.so
sudo cp -vaf fuse.a /usr/local/lib/
sudo mv -vf /usr/local/lib/libc++.a /usr/local/lib/libc++.a.bak
sudo ln -svf /usr/local/lib/libc++.a /usr/local/lib/fuse.a
It merges all the libraries used (libc++, libc++abi and libunwind) into the one single *.a or *.so file. Then libc++.a and libc++.so are replaced with (links to) resulting assemblied files, saving a previous versions for possible backup.
It works perfectly for me.
But this is not the answer. Maybe someday clang will not have such a problem right from the box.

How to build coreutils with LLVM 3.4

I am trying to build GNU Coreutils 8.23 using the LLVM 3.4 tool-chain. One very important aspect is that I also need the LLVM bytecode for all the coreutils. Therefore, I need to include -emit-llvm in the CFLAGS. Therefore, I removed the $(CFLAGS) from the LINK variable of the coreutils Makefile. Afterwards, I run the following command:
make CC=/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang
CCLD=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link
IGNORE_UNUSED_LIBRARIES_CFLAGS= CFLAGS="-emit-llvm -S"
VERBOSE=1 AM_CFLAGS= AM_LDFLAGS=
AR=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-ar
RANLIB=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-ranlib
and I get the following error:
/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link: src/libver.a:1:2: error: expected integer
!<arch>
^
/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link: error loading file 'src/libver.a'
Any ideas of how to get this to work?
Try this.
export CC="/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang"
export CXX="/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang++"
Make sure this is where your compiler toolchain is present.
Then in the the coreutils directory, run ./configure (before this run ./bootstrap if you havent already run it). Running ./configure checks if your clang can compile properly and creates a Makefile with the correct configuration.
Then do a make and make install as instructed.
Lib file '.a' here is not readable by llvm-link.
A possible informal hack to this probably is to find out the Makefile generating this lib, and let
AR = llvm-link, ar option = -o(i.e. change ar rv to llvm-link -o),
and disable ranlib command while compling(you don't need ranlib if using llvm-link).
Then the '.a' file generated is a stitched bc file, and this '.a' file should be accpetable by llvm-link command you are calling

Linking g++ 4.8 to libstdc++

I downloaded and built gcc 4.8.1 on my desktop, running 64-bit Ubuntu 12.04. I built it out of source, like the docs recommend, and with the commands
../../gcc-4.8.1/configure --prefix=$HOME --program-suffix=-4.8
make
make -k check
make install
It seemed to pass all the tests, and I installed everything into my home directory w/ the suffix -4.8 to distinguish from the system gcc, which is version 4.6.3.
Unfortunately when I compile c++ programs using g++-4.8 it links to the system libc and libstdc++ rather than the newer ones compiled from gcc-4.8.1. I downloaded and built gcc 4.8 because I wanted to play around with the new C++11 features in the standard library, so this behaviour is definitely not what I wanted. What can I do to get gcc-4.8 to automatically link to the standard libraries that came with it rather than the system standard libraries?
When you link with your own gcc you need to add an extra run-time linker search path(s) with -Wl,-rpath,$(PREFIX)/lib64 so that at run-time it finds the shared libraries corresponding to your gcc.
I normally create a wrapper named gcc and g++ in the same directory as gcc-4.8 and g++-4.8 which I invoke instead of gcc-4.8 and g++-4.8, as prescribed in Dynamic linker is unable to find GCC libraries:
#!/bin/bash
exec ${0}SUFFIX -Wl,-rpath,PREFIX/lib64 "$#"
When installing SUFFIX and PREFIX should be replaced with what was passed to configure:
cd ${PREFIX}/bin && rm -f gcc g++ c++ gfortran
sed -e 's#PREFIX#${PREFIX}#g' -e 's#SUFFIX#${SUFFIX}#g' gcc-wrapper.sh > ${PREFIX}/bin/gcc
chmod +x ${PREFIX}/bin/gcc
cd ${PREFIX}/bin && ln gcc g++ && ln gcc c++ && ln gcc gfortran
(gcc-wrapper.sh is that bash snippet).
The above solution does not work with some versions of libtool because g++ -Wl,... -v assumes linking mode and fails with an error.
A better solution is to use specs file. Once gcc/g++ is built, invoke the following command to make gcc/g++ add -rpath to the linker command line (replace ${PREFIX}/lib64 as necessary):
g++ -dumpspecs | awk '/^\*link:/ { print; getline; print "-rpath=${PREFIX}/lib64", $0; next } { print }' > $(dirname $(g++ -print-libgcc-file-name))/specs
I just had the same problem when building gcc-4.8.2. I don't have root access on that machine and therefore need to install to my home directory. It took several attempts before I figured out the magic required to get this to work so I will reproduce it here so other people will have an easier time. These are the commands that I used to configure gcc:
prefix=/user/grc/packages
export LDFLAGS=-Wl,-rpath,$prefix/lib
export LD_RUN_PATH=$prefix/lib
export LD_LIBRARY_PATH=$prefix/lib
../../src/gmp-4.3.2/configure --prefix=$prefix
../../src/mpfr-2.4.2/configure --prefix=$prefix
../../src/mpc-0.8.1/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix
../../src/gcc-4.8.2/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix --with-mpc=$prefix --enable-languages=c,c++
That got me a working binary but any program I built with that version of g++ wouldn't run correctly unless I built it with the -Wl,-rpath,$prefix/lib64 option. It is possible to get g++ to automatically add that option by providing a specs file. If you run
strace g++ 2>&1 | grep specs
you can see which directories it checks for a specs file. In my case it was $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/specs so I ran g++ -dumpspecs to create a new specs file:
cd $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2
$prefix/bin/g++ -dumpspecs > xx
mv xx specs
and then edited that file to provide the -rpath option. Search for the lines like this:
*link_libgcc:
%D
and edit to add the rpath option:
*link_libgcc:
%D -rpath /user/grc/packages/lib/%M
The %M expands to either ../lib or ../lib64 depending on whether you are building a 32-bit or a 64-bit executable.
Note that when I tried this same trick on an older gcc-4.7 build it didn't work because it didn't expand the %M. For older versions you can remove the %M and just hardcode lib or lib64 but that is only a viable solution if you only ever build 32-bit executables (with lib) or only ever build 64-bit executables (with lib64).
gcc -print-search-dirs will tell you where your compiler is looking for runtime libraries, etc. You can override this with the -B<prefix> option.

How can I set rpath on gcc binaries during bootstrap?

I am trying to build gcc 4.7.2 using a custom prefix $PREFIX
I have built and installed all the prerequisites into my prefix location, and then successfully configured, built and installed gcc.
The problem that I now have is that $PREFIX is not in the library search path, and therefore the shared libraries cannot be found.
$PREFIX/bin $ ./g++ ~/main.cpp
$PREFIX/libexec/gcc/x86_64-suse-linux/4.7.2/cc1plus: \
error while loading shared libraries: \
libcloog-isl.so.1: \
cannot open shared object file: No such file or directory
What works, but isn't ideal
If I export LD_LIBRARY_PATH=$PREFIX/lib then it works, but I'm looking for something which works without having to set environment variables.
If I use patchelf to set the RPATH on all the gcc binaries then it also works; however this involves searching out all elf binaries and iterating over them calling patchelf, I would rather have something more permanent.
What I think would be ideal for my purposes
So I'm hoping there is a way to have -Wl,-rpath,$PREFIX/lib passed to make during the build process.
Since I know the paths won't need to be changed this seems like the most robust solution, and can be also be used for when we build the next gcc version.
Is configuring the build process to hard code the RPATH possible?
What I have tried, but doesn't work
Setting LDFLAGS_FOR_TARGET prior to calling configure:
All of these fail:
export LDFLAGS_FOR_TARGET="-L$PREFIX/lib -R$PREFIX/lib"
export LDFLAGS_FOR_TARGET="-L$PREFIX/lib"
export LDFLAGS_FOR_TARGET="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib"
Setting LDFLAGS prior to calling configure:
export LDFLAGS="-L$PREFIX/lib -Wl,-rpath,$PREFIX/lib"
In any event I worry that these will override any of the LDFLAGS gcc would have had, so I'm not sure these are a viable option even if they could be made to work?
My configure line
For completeness here is the line I pass to configure:
./configure \
--prefix=$PREFIX \
--build=x86_64-suse-linux \
--with-pkgversion='SIG build 12/10/2012' \
--disable-multilib \
--enable-cloog-backend=isl \
--with-mpc=$PREFIX \
--with-mpfr=$PREFIX \
--with-gmp=$PREFIX \
--with-cloog=$PREFIX \
--with-ppl=$PREFIX \
--with-gxx-include-dir=$PREFIX/include/c++/4.7.2
I've found that copying the source directories for gmp, mpfr, mpc, isl, cloog, etc. into the top level gcc source directory (or using symbolic links with the same name) works everywhere. This is in fact the preferred way.
You need to copy (or link) to those source directory names without the version numbers for this to work.
The compilers do not need LD_LIBRARY_PATH (although running applications built with the compilers will need an LD_LIBRARY_PATH to the $PREFIX/lib64 or something like that - but that's different)
Start in a source directory where you'll keep all your sources.
In this source directory you have your gcc directory either by unpacking a tarball or svn...
I use subversion.
Also in this top level directory you have, say, the following source tarballs:
gmp-5.1.0.tar.bz2
mpfr-3.1.1.tar.bz2
mpc-1.0.1.tar.gz
isl-0.11.1.tar.bz2
cloog-0.18.0.tar.gz
I just download these and update to the latest tarballs periodically.
In script form:
# Either:
svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc_work
# Or:
bunzip -c gcc-4.8.0.tar.bz2 | tar -xvf -
mv gcc-4.8.0 gcc_work
# Uncompress sources.. (This will produce version numbered directories).
bunzip -c gmp-5.1.0.tar.bz2 | tar -xvf -
bunzip -c mpfr-3.1.1.tar.bz2 | tar -xvf -
gunzip -c mpc-1.0.1.tar.gz | tar -xvf -
bunzip -c isl-0.11.1.tar.bz2 | tar -xvf -
gunzip -c cloog-0.18.0.tar.gz | tar -xvf -
# Link outside source directories into the top level gcc directory.
cd gcc_work
ln -s ../gmp-5.1.0 gmp
ln -s ../mpfr-3.1.1 mpfr
ln -s ../mpc-1.0.1 mpc
ln -s ../isl-0.11.1 isl
ln -s ../cloog-0.18.0 cloog
# Get out of the gcc working directory and create a build directory. I call mine obj_work.
# I configure the gcc binary and other outputs to be bin_work in the top level directory. Your choice. But I have this:
# home/ed/projects
# home/ed/projects/gcc_work
# home/ed/projects/obj_work
# home/ed/projects/bin_work
# home/ed/projects/gmp-5.1.0
# home/ed/projects/mpfr-3.1.1
# home/ed/projects/mpc-1.0.1
# home/ed/projects/isl-0.11.1
# home/ed/projects/cloog-0.18.0
mkdir obj_work
cd obj_work
../gcc_work/configure --prefix=../bin_work <other options>
# Your <other options> shouldn't need to involve anything about gmp, mpfr, mpc, isl, cloog.
# The gcc build system will find the directories you linked,
# then configure and compile the needed libraries with the necessary flags and such.
# Good luck.
I've been using this configure option with gcc-4.8.0, on FreeBSD, after building and installing gmp, isl and cloog:
LD_LIBRARY_PATH=/path/to/isl/lib ./configure (lots of other options) \
--with-stage1-ldflags="-rpath /path/to/isl/lib -rpath /path/to/cloog/lib -rpath /path/to/gmp/lib"
and the resulting gcc binary does not need any LD_LIBRARY_PATH. The LD_LIBRARY_PATH for configure is needed because it compiles a test program to check for the ISL version, which would fail if it didn't find the ISL shared lib.
I tried it on Linux (Ubuntu) where it failed during configuring because the -rpath args were passed to gcc instead of ld. I could fix this by using
--with-stage1-ldflags="-Wl,-rpath,/path/to/isl/lib,-rpath,/path/to/cloog/lib,-rpath,/path/to/gmp/lib"
instead.
Just using configure --with-stage1-ldflags="-Wl,-rpath,/path/to/lib" was not enough for me to build gcc 4.9.2, bootstrap failed in stage 2. What works is to pass he flags directly to make via
make BOOT_LDFLAGS="-Wl,-rpath,/path/to/lib"
I got this from https://gcc.gnu.org/ml/gcc/2008-09/msg00214.html
While it still involves setting environment variables, what I do is that I define LD_RUN_PATH, which sets the rpath. That way the rest of the system can keep using the system provided libraries instead of using the ones that your gcc build generates.
I am going to make a suggestion that I believe solves your problem, although it definitely does not answer your question. Let's see how many downvotes I get.
Writing a generic wrapper script to set LD_LIBRARY_PATH and then to run the executable is easy; see https://stackoverflow.com/a/7101577/768469.
The idea is to pass something like --prefix=$PREFIX/install to configure, building an install tree that looks like this:
$PREFIX/
install/
lib/
libcloogXX.so
libgmpYY.so
...
bin/
gcc
emacs
...
bin/
.wrapper
gcc -> .wrapper
emacs -> .wrapper
.wrapper is a simple shell script:
#!/bin/sh
here="${0%/*}" # or use $(dirname "$0")
base="${0##*/}" # or use $(basename "$0")
libdir="$here"/../install/lib
if [ "$LD_LIBRARY_PATH"x = x ] ; then
LD_LIBRARY_PATH="$libdir"
else
LD_LIBRARY_PATH="$libdir":"$LD_LIBRARY_PATH"
fi
export LD_LIBRARY_PATH
exec "$here"/../install/bin/"$base" "$#"
This will forward all arguments correctly, handle spaces in arguments or directory names, and so forth. For practical purposes, it is indistinguishable from setting the rpath like you want.
Also, you can use this approach not only for gcc, but for your entire my-personal-$PREFIX tree. I do this all the time in environments where I want an up-to-date suite of GNU tools, but I do not have (or want to admit to have) root access.
Try to add your $PREFIX to /etc/ld.so.conf and then run ldconfig:
# echo $PREFIX >> /etc/ld.so.conf
# ldconfig
This will recreate cache that is used by runtime linker and it will pick up your libraries.
WARNING: This operation will cause ALL applications to use your newly compiled libraries in $PREFIX instead of default location