2013-12-10 4 views
3

Я пытаюсь создать простой исполняемый файл, который использует boost_serialization и boost_iostreams.Убедившись, что gcc игнорирует системные библиотеки в пользу локально установленных библиотек

#include <fstream> 
#include <iostream> 
#include <boost/archive/xml_iarchive.hpp> 
#include <boost/archive/xml_oarchive.hpp> 
#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/filter/gzip.hpp> 
#include <boost/iostreams/device/file.hpp> 

int main() 
{ 
    using namespace boost::iostreams; 
    filtering_ostream os; 
    os.push(boost::iostreams::gzip_compressor()); 
    os.push(boost::iostreams::file_sink("emptyGzipBug.txt.gz")); 
} 

К сожалению, система Я работаю с имеет очень устаревшую версию boost_serialization в/USR/Lib /, и у меня нет никакого способа изменить это.

Я довольно уверен, когда я строю пример использования

g++ -o main main.cpp -lboost_serialization -lboost_iostreams 

, что ошибки компоновщика результат, потому что GCC использует системную версию boost_serialization, а не мой локально установленной версии. Установка LIBRARY_PATH и LD_LIBRARY_PATH в/home/andrew/install/lib не работает. Когда я строю с использованием

g++ -o main main.cpp -L/home/andrew/install/lib -lboost_serialization -lboost_iostreams 

затем все работает.

Мои вопросы:

  1. Как я могу получить GCC сказать мне имена файлов библиотек его использованием?

  2. Возможно ли установить среду, чтобы мне не пришлось указывать абсолютный путь к моему локальному усилению в командной строке gcc.

+1

Вы можете пропустить некоторые опции '-I' для' g ++ 'для ваших версий« системных »библиотек (и вы должны сначала передать' -Wall -g' на 'g ++'). Вы должны использовать построитель, такой как [GNU make] (http://www.gnu.org/software/make/). –

+1

'-v' должен предоставить некоторую информацию о путях к папкам, на которые он смотрит, для включенных файлов. – splrs

+0

'-v' говорит, что его поиск включает в себя нужное место, но не говорит мне о путях библиотеки – andrew

ответ

2

PS После ввода ниже информации, я думал, что быть добрым и добавить то, что вам нужно для вашего конкретного случая:

самого
g++ -Wl,-rpath,/home/andrew/install/lib -o main main.cpp -I/home/andrew/install/include -L/home/andrew/install/lib -lboost_serialization -lboost_iostreams 

НКУ не заботятся о библиотеках , Компилятор делает;). Несмотря на то, что компоновщик должен найти общие библиотеки, чтобы он мог разрешать символы , он не сохраняет путь к этим библиотекам в исполняемом файле в обычном режиме.

Итак, для начала, позволяет выяснить, что на самом деле в двоичном после связали его:

$ readelf -d main | grep 'libboost' 
0x0000000000000001 (NEEDED)    Shared library: [libboost_serialization.so.1.54.0] 
0x0000000000000001 (NEEDED)    Shared library: [libboost_iostreams.so.1.54.0] 

только имена таким образом.

библиотеки, которые фактически используемые detemined по /lib/ld-linux.so.* во время выполнения:

$ ldd main | grep libboost 
     libboost_serialization.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.54.0 (0x00007fd8fa920000) 
     libboost_iostreams.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.54.0 (0x00007fd8fa700000) 

путь найден, глядя в /etc/ld.so.cache (обычно это , скомпилированный при запуске ldconfig). Вы можете распечатать его содержимое:

ldconfig -p | grep libboost_iostreams 
    libboost_iostreams.so.1.54.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so.1.54.0 
    libboost_iostreams.so.1.49.0 (libc6,x86-64) => /usr/lib/libboost_iostreams.so.1.49.0 
    libboost_iostreams.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libboost_iostreams.so 

, но так как это только кэшировать результат предыдущего взгляда вверх, вы больше заинтересованы в выходе:

$ ldconfig -v 2>/dev/null | egrep '^[^[:space:]]|libboost_iostreams' 
/lib/i386-linux-gnu: 
/usr/lib/i386-linux-gnu: 
/usr/local/lib: 
/lib/x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu: 
    libboost_iostreams.so.1.54.0 -> libboost_iostreams.so.1.54.0 
/lib32: 
/usr/lib32: 
/lib: 
/usr/lib: 
    libboost_iostreams.so.1.49.0 -> libboost_iostreams.so.1.49.0 

, которая показывает пути, он заглянул, прежде чем найти результат. Обратите внимание, что если вы связываете 64-битную программу, она сначала найдет 32-битную библиотеку (или наоборот), которая будет пропущена как несовместимой. В противном случае используется первый найденный.

Путь, используемый для поиска указаны в /etc/ld.so.conf, который чтение (обычно во время загрузки или после установки что-то новое) при запуске LDCONFIG как корень.

Тем не менее, приоритет принимает пути, указанные как список, разделенный двоеточиями путей в переменной окружения LD_LIBRARY_PATH. Например, если я хотел бы сделать:

$ export LD_LIBRARY_PATH=/tmp 
$ cp /usr/lib/libboost_iostreams.so.1.49.0 /tmp/libboost_iostreams.so.1.54.0 
$ ldd main | grep libboost_iostreams 
    libboost_iostreams.so.1.54.0 => /tmp/libboost_iostreams.so.1.54.0 (0x00007f621add8000) 

тогда он находит «libboost_iostreams.so.1.54.0» в/TMP (даже если он был libboost_iostreams.so.1.49.0).

Обратите внимание, что вы можете жёстко путь в ваш исполняемый файл, передавая -rpath к линкер:

$ unset LD_LIBRARY_PATH 
$ g++ -Wl,-rpath,/tmp -o main main.cpp -lboost_serialization -lboost_iostreams 
$ ldd main | grep libboost_iostreams 
    libboost_iostreams.so.1.54.0 => /tmp/libboost_iostreams.so.1.54.0 (0x00007fbd8bcd8000) 

, которые могут быть сделаны видимыми с

$ readelf -d main | grep RPATH 
0x000000000000000f (RPATH)    Library rpath: [/tmp] 

Вы можете показать, что пути поиска gcc использует во время компиляции (link) время с опцией командной строки -print-search-dirs:

$ g++ -print-search-dirs | grep libraries 
libraries: =/usr/lib/gcc/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/:/lib/x86_64-linux-gnu/4.7/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/4.7/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../:/lib/:/usr/lib/ 

На это может повлиять добавление параметров командной строки -L. Если библиотека не может быть найдена в пути, указанном в параметре -L, тогда он ищет пути, найденные через переменную среды GCC_EXEC_PREFIX (см. Справочную страницу для этого), и если это не удается, она использует переменную среды LIBRARY_PATH.

Когда вы запустите g ++ с опцией -v, он напечатает используемую LIBRARY_PATH.

LIBRARY_PATH=/tmp/lib g++ -v -o main main.cpp -lboost_serialization -lboost_iostreams 2>&1 | grep LIBRARY_PATH 
LIBRARY_PATH=/tmp/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/tmp/lib/:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../:/lib/:/usr/lib/ 

Наконец, следует отметить, что специально для повышения (но в целом) вы должны файлы использование заголовков, которые соответствуют правильной версии! Итак, если в библиотеке, с которой вы связываетесь со временем во время выполнения, является версия xyz, вы должны использовать опцию командной строки -I, чтобы получить g ++, чтобы найти соответствующие файлы заголовков, или вещи могут не связываться или быть хуже, приводят к необъяснимым сбоям.

+0

Обратите внимание, что компоновщик времени компиляции не ищет SO_NAME (который отображается readelf). Используя -lfoo, он ищет libfoo.so. Поэтому ** в пути LIBRARY_PATH много будет libfoo.so **, который указывает на реальную библиотеку, в которой она SO_NAME жестко закодирована внутри нее. Если SO_NAME (используется во время компоновки во время выполнения) отличается от этого имени файла, вам понадобится еще одна символическая ссылка, чтобы заставить компоновщик времени выполнения найти его!). Т.е., если SO_NAME - это libfoo.so.1, а имя файла - libfoo.so.1.4, то вам нужно использовать символическую ссылку из libfoo.so.1 для libfoo.so.1.4 для работы во время выполнения;). –

Смежные вопросы