boost iOS链接错误

boost iOS linking error

本文关键字:错误 链接 iOS boost      更新时间:2023-10-16

我有一个严重依赖boost的C++库,我正试图为iOS8编译它。我使用Daniel Rosser的脚本为iOS编译了boost-1.57.0:https://github.com/danoli3/ofxiOSBoost

我修改了脚本,这样它也构建了boost的serialization库,一切看起来都很好。

但是,当我用XCode编译我的库时,我得到:

Undefined symbols for architecture x86_64:
  "boost::archive::detail::shared_ptr_helper::shared_ptr_helper()", referenced from:
      eos::portable_iarchive::portable_iarchive(std::__1::basic_istream<char, std::__1::char_traits<char> >&, unsigned int) in data_receiver.o
      eos::portable_oarchive::portable_oarchive(std::__1::basic_streambuf<char, std::__1::char_traits<char> >&, unsigned int) in tcp_server.o
  "boost::archive::detail::shared_ptr_helper::~shared_ptr_helper()", referenced from:
      eos::portable_iarchive::portable_iarchive(std::__1::basic_istream<char, std::__1::char_traits<char> >&, unsigned int) in data_receiver.o
      eos::portable_iarchive::~portable_iarchive() in data_receiver.o
      eos::portable_oarchive::portable_oarchive(std::__1::basic_streambuf<char, std::__1::char_traits<char> >&, unsigned int) in tcp_server.o
      eos::portable_oarchive::~portable_oarchive() in tcp_server.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

它似乎坚持使用boost::archive库中的shared_ptr_help()函数。我有点困惑,因为我认为boost的这一部分没有编译,它都是头,所以我不确定是什么导致了"错误的体系结构"错误。有没有另一个boost库真正定义了我没有编译的这个方法?

稍后。。。这是eos::portable_iarchive构造函数代码(这似乎是导致错误的原因——oarchive代码几乎相同)

namespace eos {
    // forward declaration
    class portable_iarchive;
    typedef boost::archive::basic_binary_iprimitive<
            portable_iarchive
    #if BOOST_VERSION < 103400
            , std::istream
    #else
            , std::istream::char_type
            , std::istream::traits_type
    #endif
    > portable_iprimitive;
    /**
     * brief Portable binary input archive using little endian format.
     *
     * This archive addresses integer size, endianness and floating point types so
     * that data can be transferred across different systems. There may still be
     * constraints as to what systems are compatible and the user will have to take
     * care that e.g. a very large int being saved on a 64 bit machine will result
     * in a portable_archive_exception if loaded into an int on a 32 bit system.
     * A possible workaround to this would be to use fixed types like
     * boost::uint64_t in your serialization structures.
     *
     * note The class is based on the portable binary example by Robert Ramey and
     *           uses Beman Dawes endian library plus fp_utilities by Johan Rade.
     */
    class portable_iarchive : public portable_iprimitive
            // the example derives from common_oarchive but that lacks the
            // load_override functions so we chose to stay one level higher
            , public boost::archive::basic_binary_iarchive<portable_iarchive>
    #if BOOST_VERSION >= 103500
            // mix-in helper class for serializing shared_ptr
            , public boost::archive::detail::shared_ptr_helper
    #endif
    {
            // only needed for Robert's hack in basic_binary_iarchive::init
            friend class boost::archive::basic_binary_iarchive<portable_iarchive>;
            // workaround for gcc: use a dummy struct
            // as additional argument type for overloading
            template <int> struct dummy { dummy(int) {}};
            // loads directly from stream
            inline signed char load_signed_char()
            {
                    signed char c;
                    portable_iprimitive::load(c);
                    return c;
            }
            // archive initialization
            void init(unsigned flags)
            {
                    using namespace boost::archive;
                    archive_version_type input_library_version(3);
                    // it is vital to have version information!
                    // if we don't have any we assume boost 1.33
                    if (flags & no_header)
                            set_library_version(input_library_version);
                    // extract and check the magic eos byte
                    else if (load_signed_char() != magic_byte)
                            throw archive_exception(archive_exception::invalid_signature);
                    else
                    {
                            // extract version information
                            operator>>(input_library_version);
                            // throw if file version is newer than we are
                            if (input_library_version > archive_version)
                                    throw archive_exception(archive_exception::unsupported_version);
                            // else set the library version accordingly
                            else set_library_version(input_library_version);
                    }
            }
public:
        /**
         * brief Constructor on a stream using ios::binary mode!
         *
         * We cannot call basic_binary_iprimitive::init which tries to detect
         * if the binary archive stems from a different platform by examining
         * type sizes.
         *
         * We could have called basic_binary_iarchive::init which would create
         * the boost::serialization standard archive header containing also the
         * library version. Due to efficiency we stick with our own.
         */
        portable_iarchive(std::istream& is, unsigned flags = 0)
        #if BOOST_VERSION < 103400
                : portable_iprimitive(is, flags & boost::archive::no_codecvt)
        #else
                : portable_iprimitive(*is.rdbuf(), flags & boost::archive::no_codecvt)
        #endif
                , boost::archive::basic_binary_iarchive<portable_iarchive>(flags)
        {
                init(flags);
        }
#if BOOST_VERSION >= 103400
        portable_iarchive(std::streambuf& sb, unsigned flags = 0)
                : portable_iprimitive(sb, flags & boost::archive::no_codecvt)
                , boost::archive::basic_binary_iarchive<portable_iarchive>(flags)
        {
                init(flags);
        }
#endif
        //! Load narrow strings.
        void load(std::string& s)
        {
                portable_iprimitive::load(s);
        }
#ifndef BOOST_NO_STD_WSTRING
        /**
         * brief Load wide strings.
         *
         * This is rather tricky to get right for true portability as there
         * are so many different character encodings around. However, wide
         * strings that are encoded in one of the Unicode schemes only need
         * to be _transcoded_ which is a lot easier actually.
         *
         * We generate the output string to be encoded in the system's native
         * format, ie. UTF-16 on Windows and UTF-32 on Linux machines. Don't
         * know about Mac here so I can't really say about that.
         */
        void load(std::wstring& s)
        {
                std::string utf8;
                load(utf8);
                s = boost::from_utf8(utf8);
        }

等等。

这些线路特别令人感兴趣:

#if BOOST_VERSION >= 103500
        // mix-in helper class for serializing shared_ptr
        , public boost::archive::detail::shared_ptr_helper
#endif

评论它们使我的构建成功了,但我仍然对不能使用shared_ptr_help()感到不高兴。

首先确保:

  • 您必须将项目或目标构建设置更改为c++11

在Apple LLVM 6.0-Language-C++下进行以下更改

C++语言方言到C++11[-std=C++11]C++标准库到libc++(支持C++11的LLVM C++标准库)

否则,我认为这可能与以下链接的EOS-Boost Bug(Boost>=1.56.0)有关

问题:https://epa.codeplex.com/workitem/2456

我还对Build脚本进行了快速审查,以确保它肯定会将Boost序列化库添加到每个架构的lipo-Boost存档中,是的,它肯定都在那里。

相关文章: