Почему общая библиотека Folly ссылается на неправильный символ из Boost? (GCC на OS X)

я пытаюсь построить и запустить небольшой пример приложения, которое использует глупость на OS X Yosemite с помощью GCC 4.9.3. Вот исходный код:

#include <folly/AtomicHashMap.h>

int main() {
    folly::AtomicHashMap<int, int> map(256);
    map.insert(std::make_pair(1, 1));
    return 0;
}

я построил и установил как Boost (1.59.0), так и Folly (последняя голова GitHub) из источников, убедившись, что GCC был использован, и теперь их библиотеки и заголовки доступны в /usr/local. GCC и другие зависимости были установлены с помощью MacPorts. Я могу успешно построить приведенный выше образец, используя следующую команду строка:

$ g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib -lfolly -lglog

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

$ ./a.out
dyld: Symbol not found: __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
  Referenced from: /usr/local/lib/libfolly.57.dylib
  Expected in: flat namespace
 in /usr/local/lib/libfolly.57.dylib
Trace/BPT trap: 5

из того, что я понимаю, как это должно работать, это /usr/local/lib/libfolly.57.dylib автоматически тянет в libboost_program_options.dylib по ссылке во время загрузки. Я вижу, что он указан как зависимость, когда я запускаю otool -L:

$ otool -L /usr/local/lib/libfolly.57.dylib
/usr/local/lib/libfolly.57.dylib:
    /usr/local/lib/libfolly.57.dylib (compatibility version 58.0.0, current version 58.0.0)
    libboost_context.dylib (compatibility version 0.0.0, current version 0.0.0)
    libboost_program_options.dylib (compatibility version 0.0.0, current version 0.0.0)
    ...

libboost_program_options.dylib находится в /usr/local/lib, и если я переименую его во что-то другое, запустив ./a.out заставляет загрузчик жаловаться на то, что не может его найти вместо этого ("dyld: библиотека не загружена: libboost_program_options.dylib нужна"). Таким образом, кажется, что загрузчик может найти его, по крайней мере.

я проверил символы, экспортируемые этой библиотекой, используя nm -gU:

$ nm -gU /usr/local/lib/libboost_program_options.dylib | grep program_options
    ...
    0000000000023560 T __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
    ...

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

[ Edit: это не очень легко увидеть имена, если вы не прокрутите вправо, так что вот они опять:

  • nm говорит, что библиотека содержит __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
  • "отсутствующий символ" во время загрузки -__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs.]

я нашел соответствующую декларацию в /usr/local/include/boost/program_options/errors.hpp:

namespace boost { namespace program_options {
...
    class BOOST_PROGRAM_OPTIONS_DECL error_with_option_name : public error {
...
    protected:
...
        virtual void substitute_placeholders(const std::string& error_template) const;

я предполагаю, что это заголовочный файл, который Folly использовал, когда я его построил, потому что это единственное совпадение substitute_placeholders во всех /usr/include, /usr/local/include и /opt/local/include. (Обратите внимание, что Folly даже не вызывает эту функцию напрямую, но это так #include <boost/program_options.hpp> С folly/experimental/ProgramOptions.h и использовать другие члены boost::program_options.)

мне кажется, что более длинное искореженное имя -- единственное, которое фактически экспортируется из libboost_program_options.dylib -- является правильным, так как он включает в себя

1 ответов


использование C++filt (или http://demangler.com) чтобы деманглировать два символа, символ в библиотеке boost имеет std::__1::basic_string префикс, в то время как тот, который отсутствует в глупости std::string. Некоторые googling указывает, что __1 subnamespace используется libc++ (стандартная библиотека c++ clang), чтобы избежать конфликтов с libstdc++ (GNU). Это указывает на то, что boost был скомпилирован с помощью clang и libc++, который по умолчанию используется в OS X, а folly был скомпилирован с libstdc++ (либо с помощью g++ или указание разных флагов для clang).

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