Подтвердить что ты не робот

Есть ли разумный способ узнать имя библиотеки для ссылки во время компиляции? (Linux/Kubuntu)

Пожалуйста, несите меня. Я действительно хочу знать, как мне любопытно ответить:

Есть ли разумный способ узнать имя библиотеки для ссылки во время компиляции?

Позвольте мне привести вам пример, который прекрасно иллюстрирует причину моего вопроса.

Я новичок в С++. Я изучаю компиляцию, компоновку и библиотеки, например boost. Я только что открыл boost/filesystem и хотел попробовать. После компиляции проблем я использовал следующий минималистский код:


// file boost_example.cpp
 #include "boost/filesystem.hpp"
#include <iostream>

int main() { std::cout<<"Hello"; return 0; }

Я попытался скомпилировать его, но, будучи новичком, я совершил ошибку новичков: я забыл связать с соответствующей библиотекой!

     g++ boost_example.cpp -o run

Чтобы быть точным, я столкнулся с проблемой, описанной в этой главе этой прекрасной книги.
Я знал, что у меня установлен boost (мне сказали установить его, чтобы скомпилировать другой проект). Я попытался скопировать из Makefile этого другого проекта, но следующее не получилось:
     g++ boost_example.cpp -o run -lbooster
     g++ boost_example.cpp -o run -lboost
Попытка сделать обоснованное предположение из строки #include в коде, я пробовал следующее безрезультатно:
     g++ boost_example.cpp -o run -lboost_filesystem
К тому времени я начал искать в Интернете отчаянно. Я ненавижу поисковые системы, потому что большую часть времени вы не находите того, что ищете. Я нашел следующее, но они не помогли, но тратили свое время:
Устранить проблему с библиотечной связью при kubuntu
Ошибки компоновщика С++/Boost

Поскольку я являюсь участником RTFM, я фактически проверил официальную документацию для библиотеки, которую я хотел использовать: http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm но я не нашел компиляционной информации.

На каком-то этапе мне пришло в голову проверить, что я действительно установил в своей системе:


$ locate boost_file
/usr/lib/libboost_filesystem-mt.a
/usr/lib/libboost_filesystem-mt.so
/usr/lib/libboost_filesystem-mt.so.1.38.0
Таким образом, я нашел правильное имя библиотеки для ссылки. Следующие работали:
     g++ boost_example.cpp -o run -lboost_filesystem-mt

Теперь, помимо использования (возможно) умной угадывающей работы и поиска в Интернете, есть ли более интеллектуальный способ найти имя библиотеки для ссылки? Я бы никогда не догадался имя библиотеки boost_filesystem-mt, учитывая заголовок "boost/filesystem.hpp".

Что еще хуже: boost_filesystem-mt нигде не упоминается на официальном сайте! (Я предполагаю, что это зависит от дистрибутива/упаковки).

Снова, я всегда делаю точку RTFM, прежде чем задавать вопрос, и нашел эту главу вышеупомянутой книги, поэтому я проверил что я мог найти в своей системе в /usr/lib/:


$ ls /usr/lib/boost
/usr/lib/libboost_date_time-mt.a           /usr/lib/libboost_prg_exec_monitor-mt.so.1.38.0
/usr/lib/libboost_date_time-mt.so          /usr/lib/libboost_program_options-mt.a
/usr/lib/libboost_date_time-mt.so.1.38.0   /usr/lib/libboost_program_options-mt.so
/usr/lib/libbooster.a                      /usr/lib/libboost_program_options-mt.so.1.38.0
/usr/lib/libbooster.so                     /usr/lib/libboost_python-mt.a
/usr/lib/libbooster.so.0                   /usr/lib/libboost_python-mt-py25.a
/usr/lib/libbooster.so.0.0.0               /usr/lib/libboost_python-mt-py25.so
/usr/lib/libboost_filesystem-mt.a          /usr/lib/libboost_python-mt-py25.so.1.38.0
/usr/lib/libboost_filesystem-mt.so         /usr/lib/libboost_python-mt-py26.a
/usr/lib/libboost_filesystem-mt.so.1.38.0  /usr/lib/libboost_python-mt-py26.so
/usr/lib/libboost_graph-mt.a               /usr/lib/libboost_python-mt-py26.so.1.38.0
/usr/lib/libboost_graph-mt.so              /usr/lib/libboost_python-mt.so
/usr/lib/libboost_graph-mt.so.1.38.0       /usr/lib/libboost_regex-mt.a
/usr/lib/libboost_iostreams-mt.a           /usr/lib/libboost_regex-mt.so
/usr/lib/libboost_iostreams-mt.so          /usr/lib/libboost_regex-mt.so.1.38.0
/usr/lib/libboost_iostreams-mt.so.1.38.0   /usr/lib/libboost_serialization-mt.a
/usr/lib/libboost_math_c99f-mt.a           /usr/lib/libboost_serialization-mt.so
/usr/lib/libboost_math_c99f-mt.so          /usr/lib/libboost_serialization-mt.so.1.38.0
/usr/lib/libboost_math_c99f-mt.so.1.38.0   /usr/lib/libboost_signals-mt.a
/usr/lib/libboost_math_c99l-mt.a           /usr/lib/libboost_signals-mt.so
/usr/lib/libboost_math_c99l-mt.so          /usr/lib/libboost_signals-mt.so.1.38.0
/usr/lib/libboost_math_c99l-mt.so.1.38.0   /usr/lib/libboost_system-mt.a
/usr/lib/libboost_math_c99-mt.a            /usr/lib/libboost_system-mt.so
/usr/lib/libboost_math_c99-mt.so           /usr/lib/libboost_system-mt.so.1.38.0
/usr/lib/libboost_math_c99-mt.so.1.38.0    /usr/lib/libboost_thread-mt.a
/usr/lib/libboost_math_tr1f-mt.a           /usr/lib/libboost_thread-mt.so
/usr/lib/libboost_math_tr1f-mt.so          /usr/lib/libboost_thread-mt.so.1.38.0
/usr/lib/libboost_math_tr1f-mt.so.1.38.0   /usr/lib/libboost_unit_test_framework-mt.a
/usr/lib/libboost_math_tr1l-mt.a           /usr/lib/libboost_unit_test_framework-mt.so
/usr/lib/libboost_math_tr1l-mt.so          /usr/lib/libboost_unit_test_framework-mt.so.1.38.0
/usr/lib/libboost_math_tr1l-mt.so.1.38.0   /usr/lib/libboost_wave-mt.a
/usr/lib/libboost_math_tr1-mt.a            /usr/lib/libboost_wave-mt.so
/usr/lib/libboost_math_tr1-mt.so           /usr/lib/libboost_wave-mt.so.1.38.0
/usr/lib/libboost_math_tr1-mt.so.1.38.0    /usr/lib/libboost_wserialization-mt.a
/usr/lib/libboost_prg_exec_monitor-mt.a    /usr/lib/libboost_wserialization-mt.so
/usr/lib/libboost_prg_exec_monitor-mt.so   /usr/lib/libboost_wserialization-mt.so.1.38.0

И теперь я очень сильно царапаю себе голову, потому что я действительно не знаю, как соотнести вышеперечисленное с список ускорительных библиотек.

Я прошу прощения за этот длинный пример, но он отлично иллюстрирует мою проблему:

Помимо догадок, поиска в Интернете, запроса других людей, проб и ошибок и т.д.... есть ли более интеллектуальный способ найти имя библиотеки, на которую нужно ссылаться? такие вещи должны быть где-то задокументированы?

Я, конечно, заинтересован в том, чтобы знать ответ в том, что касается повышения, но мой вопрос более общий и применим к любой библиотеке.

Кстати, у меня очень похожий вопрос относительно имени пакетов linux (будь то .deb или. rpm). Если мне говорят, что для компиляции такого или такого программного обеспечения мне нужно, скажем, PRCE или FooBar, как я точно знаю имя пакета для установки? Я знаю, как использовать apt-cache для пользователей (для Kubuntu debs), но некоторые имена пакетов не интуитивно понятны, и я часто заканчиваю установку пакетов, которые мне действительно не нужны...

4b9b3361

Ответ 1

Существует метод грубой силы, который я иногда использую, но вам нужно знать, какие каталоги искать в необходимой вам библиотеке (/lib,/usr/lib и /usr/local/lib являются обычными подозреваемыми), Я создал оболочку script, я называю "gnm" (сокращение от "grep nm", две используемые ею утилиты) с приведенным ниже содержимым. Если вы создаете такой текстовый файл, не забудьте сделать его исполняемым (chmod + x gnm).

#!/bin/sh
if [ $# -lt 2 ] ; then
  echo Usage: $0 pattern file[s]
  exit
fi
pattern=$1
shift
while [ $# -gt 0 ] ; do
  nm $1 | grep $pattern > /dev/null
  if [ $? -eq 0 ] ; then
    echo $1
  fi
  shift
done

Когда я ищу библиотеку, которая определяет конкретный символ, я выдаю команду что-то вроде:

gnm symbol /usr/lib/*.a 

Например, источник, который вы упомянули, дает мне следующие ошибки связи:

boost_example.cpp:(.text+0x38): undefined reference to `boost::system::get_system_category()'
boost_example.cpp:(.text+0x44): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x50): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x5c): undefined reference to `boost::system::get_generic_category()'
boost_example.cpp:(.text+0x68): undefined reference to `boost::system::get_system_category()'

поэтому я использую команду:

gnm get_system_category /usr/lib/*.a

который сообщает:

/usr/lib/libboost_filesystem.a
/usr/lib/libboost_system.a

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

g++ boost_example.cpp -lboost_system -o run

Я не знаю, зачем мне нужна системная библиотека, где вам нужна файловая система; возможно, разные версии Boost.

Ответ 2

Я только нашел самый умный и самый официальный способ (в моей системе) выяснить флаг ссылки. Следующее следует только для повышения в дистрибутиве Debian или Debian (например, Kubuntu в моем случае). Другие ответы могут быть более универсальными для любой библиотеки в любой системе.

В зависимости от установленной версии boost вы можете иметь следующий файл в своем дистрибутиве, подобном Debian:
/usr/share/doc/libboost1.38-doc/README.Debian
часть которого гласит:

--------

The following table shows which components use a library (shared or
static) and the corresponding "-l" flag.  Note that only the
multithreaded version of the libraries is shipped.

  Component              Link Flag                    Library Type
  ---------              ---------                    ------------
  Boost.Date_Time        -lboost_date_time-mt           static  shared
  Boost.Filesystem       -lboost_filesystem-mt          static  shared
  Boost.Graph            -lboost_graph-mt               static  shared
  Boost.IOStreams        -lboost_iostreams-mt           static  shared
  Boost.Math             -lboost_math_c99-mt            static  shared
                         -lboost_math_c99f-mt           static  shared
                         -lboost_math_c99l-mt           static  shared
  Boost.MPI              -lboost_mpi-mt                 static  shared
  Boost.Program_options  -lboost_program_options-mt     static  shared
  Boost.Python           -lboost_python-mt-py24         static  shared
                         -lboost_python-mt-py25         static  shared
  Boost.Regex            -lboost_regex-mt               static  shared
  Boost.Serialization    -lboost_serialization-mt       static  shared
                         -lboost_wserialization-mt      static  shared
  Boost.Signals          -lboost_signals-mt             static  shared
  Boost.System           -lboost_system-mt              static  shared
  Boost.Test             -lboost_prg_exec_monitor-mt    static  shared
                         -lboost_unit_test_framework-mt static  shared
  Boost.Thread           -lboost_thread-mt              static  shared
  Boost.Wave             -lboost_wave-mt                static  shared


Нужно было найти подходящее место для документации!

Ответ 4

  • Одна из возможностей - проверить список файлов пакета rpm/deb. В системе Ubuntu это можно сделать, выпустив следующую команду:

dpkg -L libboost-filesystem-dev

  • Другая возможность - использовать pkg-config. Это программа, которая помогает определять флаги компиляции для определенных библиотек (хотя это не поддерживает boost на Ubuntu)

  • Вы можете использовать Autoconf - макрос, который проверяет повышение, можно найти здесь. Использование Autoconf помогает поддерживать независимую платформу/дистрибутив источников.