提升iOS链接错误

时间:2015-02-17 19:13:54

标签: c++ ios xcode boost linker

我有一个C ++库,它很大程度上依赖于我试图为iOS8编译的boost。我使用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_helper()函数。我有点困惑,因为我认为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_helper()。

1 个答案:

答案 0 :(得分:1)

首先确保:

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

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

     

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

否则我相信这可能与以下链接的EOS有关 - Boost Bug(Boost&gt; = 1.56.0)

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

我还快速回顾了Build脚本,以确保它肯定会将Boost Serialization库添加到每个架构的lipo boost存档中,是的,它确实存在。