Связывание g++ 4.8 с libstdC++
Я скачал и собрал gcc 4.8.1 на своем рабочем столе под управлением 64-битной Ubuntu 12.04. Я создал его из исходного кода, как рекомендуют документы, и с помощью команд
../../gcc-4.8.1/configure --prefix=$HOME --program-suffix=-4.8
make
make -k check
make install
Казалось, что все тесты пройдены, и я установил все в свой домашний каталог с суффиксом -4.8, чтобы отличить его от системы gcc, которая является версией 4.6.3.
К сожалению, когда я компилирую программы на C++ с использованием g ++ - 4.8, он ссылается на системные libc и libstdC++, а не на новые, скомпилированные из gcc-4.8.1. Я скачал и собрал gcc 4.8, потому что хотел поэкспериментировать с новыми функциями C++11 в стандартной библиотеке, поэтому такое поведение определенно не то, что я хотел. Что я могу сделать, чтобы gcc-4.8 автоматически связывался со стандартными библиотеками, которые поставлялись вместе с ним, а не со стандартными библиотеками системы?
3 ответа
Когда вы связываете с вашим собственным GCC, вам нужно добавить дополнительные пути поиска компоновщика во время выполнения с -Wl,-rpath,$(PREFIX)/lib64
так что во время выполнения он находит разделяемые библиотеки, соответствующие вашему gcc.
Я обычно создаю оболочку с именем gcc
а также g++
в том же каталоге, что и gcc-4.8
а также g++-4.8
который я призываю вместо gcc-4.8
а также g++-4.8
, как предписано в динамическом компоновщике не удается найти библиотеки GCC:
#!/bin/bash
exec ${0}SUFFIX -Wl,-rpath,PREFIX/lib64 "$@"
При установке SUFFIX
а также PREFIX
следует заменить на то, что было передано 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
это тот фрагмент bash)
Приведенное выше решение не работает с некоторыми версиями libtool
так как g++ -Wl,... -v
предполагает режим связывания и завершается с ошибкой.
Лучшее решение - использовать файл спецификаций. Как только gcc/g++ собран, вызовите следующую команду, чтобы добавить gcc/g++ -rpath
в командной строке компоновщика (заменить ${PREFIX}/lib64
как необходимо):
g++ -dumpspecs | awk '/^\*link:/ { print; getline; print "-rpath=${PREFIX}/lib64", $0; next } { print }' > $(dirname $(g++ -print-libgcc-file-name))/specs
У меня просто была такая же проблема при сборке gcc-4.8.2. У меня нет root-доступа на этом компьютере, поэтому мне нужно установить его в свой домашний каталог. Потребовалось несколько попыток, прежде чем я понял магию, необходимую для того, чтобы заставить это работать, поэтому я воспроизведу это здесь, чтобы другим людям было легче. Это команды, которые я использовал для настройки 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++
Это дало мне работающий двоичный файл, но любая программа, которую я собрал с этой версией g++, не будет работать правильно, если я не соберу ее с опцией -Wl,-rpath,$prefix/lib64. Можно заставить g++ автоматически добавить эту опцию, предоставив файл спецификации. Если вы бежите
strace g++ 2>&1 | grep specs
Вы можете увидеть, какие каталоги он проверяет для спецификации файла. В моем случае это был $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/specs, поэтому я запустил g++ -dumpspecs для создания нового файла specs:
cd $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2
$prefix/bin/g++ -dumpspecs > xx
mv xx specs
а затем отредактировал этот файл для предоставления опции -rpath. Ищите строки как это:
*link_libgcc:
%D
и отредактируйте, чтобы добавить опцию rpath:
*link_libgcc:
%D -rpath /user/grc/packages/lib/%M
%M расширяется до../lib или../lib64 в зависимости от того, собираете ли вы 32-битный или 64-битный исполняемый файл.
Обратите внимание, что когда я попробовал этот же трюк на более старой сборке gcc-4.7, он не работал, потому что он не расширил%M. Для более старых версий вы можете удалить%M и просто жестко кодировать lib или lib64, но это жизнеспособное решение, если вы когда-либо собираете только 32-битные исполняемые файлы (с lib) или только когда-либо собираете 64-битные исполняемые файлы (с lib64).
gcc -print-search-dirs
скажет вам, где ваш компилятор ищет библиотеки времени выполнения и т. д. Вы можете переопределить это с помощью -B<prefix>
вариант.