Reputation: 1555
I have a C++ library that relies heavily on boost that I am trying to compile for iOS8. I used Daniel Rosser's script to compile boost-1.57.0 for iOS: https://github.com/danoli3/ofxiOSBoost
I modified the script so that it also builds boost's serialization
library and everything seems fine.
But, when I compile my library in XCode I get:
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)
It seems to be sticking on the shared_ptr_helper() function in the boost::archive library. I am a little confused, because I thought this part of boost doesn't compile, that it is all headers, so I'm not sure what is causing the 'wrong architecture' error. Is there another boost library that actually defines this method that I'm not compiling?
Later ... here is the eos::portable_iarchive constructor code (which seems to be what originates the errors --the oarchive code is almost identical)
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);
}
etc.
These lines are of particular interest:
#if BOOST_VERSION >= 103500
// mix-in helper class for serializing shared_ptr
, public boost::archive::detail::shared_ptr_helper
#endif
Commenting them out made my build succeed, but I am still not happy about not being able to use shared_ptr_helper().
Upvotes: 2
Views: 703
Reputation: 3233
Firstly make sure:
Under Apple LLVM 6.0 - Language - C++ make the following changes
C++ Language Dialect to C++11 [-std=c++11] C++ Standard Library to libc++ (LLVM C++ standard library with C++11 support)
Else I believe this may be related to the following linked EOS - Boost Bug (Boost >= 1.56.0)
Issue: https://epa.codeplex.com/workitem/2456
I also did a quick review of the Build script to make sure it would definitely adding in the Boost Serialization library to the lipo boost archive for each architecture, and yeah it is all definitely there.
Upvotes: 1