5

Below is a minimal example to use the great Boost.Serialization library.

To compile the library I need to link with the boost_serialization precompiled library.

$ c++ -std=c++11 example.cpp -o example.x -lboost_serialization
                                          ^^^^^^^^^^^^^^^^^^^^^

The library is heavily templated an although complicated internally the actual code (function body) is quite simple. There are only a few references that need the linking, namely:

boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::text_oarchive_impl(std::ostream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_oarchive>::~text_oarchive_impl()
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::~text_iarchive_impl()
...
boost::archive::archive_exception::~archive_exception()'

Is there a chance that the library can be used without linking as a header-only library?

For example some undocumented trick or hack?

That would make it more simple to use in some supercomputer clusters and environments where it is not that simply to compile Boost.

#include<sstream>
#include<numeric>
#include<boost/archive/text_oarchive.hpp> // needs linking 
#include<boost/archive/text_iarchive.hpp>
#include<boost/serialization/vector.hpp>

int main(){

    std::vector<double> v(10); std::iota(v.begin(), v.end(), 0);
    std::stringstream ss;
    {
        boost::archive::text_oarchive toa(ss);
        toa << v;
    }
    std::vector<double> v2;
    boost::archive::text_iarchive tia(ss);
    tia >> v2;
    assert(v == v2);
}

EDIT: I would be very cool if the library gave the option to be header only, like Boost.Asio does (https://stackoverflow.com/a/40729439/225186.)


EDIT2: The author and maintainer of Boost.Serialization rejected the idea of making it header only. https://github.com/boostorg/serialization/issues/71

alfC
  • 14,261
  • 4
  • 67
  • 118
  • 1
    > environments where it is not that simply to compile Boost. - you have to compile your program somewhere.. why not compile boost there too? Anyhow, you can always just try #include'ing the cpp files and see what happens. but isn't that an awful lot like compiling boost? – xaxxon Jun 07 '17 at 06:19
  • I tried `#include`ing `.cpp` files. I was able to make it work in some simple cases but not for the example above. I start getting `error: redefinition of ‘class boost::archive::detail::extra_detail::map’` (as expect, including cpps becomes a mess very quickly) – alfC Jun 07 '17 at 08:18
  • 3
    This is something I have wanted for years. If any Boost library ought to be header-only, `serialization` is it. But it's not, so I wound up rolling my own – Nemo Oct 27 '17 at 20:41
  • @Nemo, your own serialization library? Or your own patches to Boost serialization? – alfC Oct 27 '17 at 20:50
  • 1
    My own serialization library. It was partly an exercise to teach myself template meta-programming and partly because I needed it. – Nemo Oct 27 '17 at 22:38
  • @Nemo, yes, it is not that hard to implement. The hard part, if one wants it, is to the automatic tracking of pointers (and smart pointers) and versioning. – alfC Oct 28 '17 at 01:25

1 Answers1

0

I ended up including the cpp sources from a certain version of Boost Serialization. I chose the cpp files by trial and error.

https://gitlab.com/correaa/boost-mpi3/-/tree/master/include/mpi3/serialization_hack

serialiation_hack

Basically, I include these cpp files from the same place I would include the Serialization hpp files.

#include <boost/archive/detail/common_iarchive.hpp>
#include <boost/archive/detail/common_oarchive.hpp>

#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
//#include <boost/archive/detail/abi_prefix.hpp> // must be the last header

#include <boost/serialization/array.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/string.hpp>

#include <boost/mpl/placeholders.hpp>

#include <any>
#include <optional>

// use this to avoid need for linking -lserialization
#ifdef _MAKE_BOOST_SERIALIZATION_HEADER_ONLY
//#include <boost/archive/detail/decl.hpp>
#if BOOST_VERSION > 106000 && BOOST_VERSION < 106600
#include "../mpi3/serialization_hack/singleton.cpp"
#endif
#if BOOST_VERSION < 105900
#define BOOST_ARCHIVE_DECL
#define BOOST_SERIALIZATION_DECL
#endif
// NOLINTBEGIN(hicpp-use-auto,modernize-use-auto)  external code
#include "../mpi3/serialization_hack/archive_exception.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_archive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iarchive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iserializer.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oarchive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oserializer.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info_typeid.cpp"  // NOLINT(bugprone-suspicious-include) hack
// NOLINTEND(hicpp-use-auto,modernize-use-auto)

A problem with this approach is that I had to modify the sources to accommodate different versions of Boost.Serialization and also had to do some modification to appease compiler warnings and static analyzers.

alfC
  • 14,261
  • 4
  • 67
  • 118