]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Detect BOOST bug while configuring
authorDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Sun, 3 Dec 2017 22:32:21 +0000 (23:32 +0100)
committerDaniel Arndt <daniel.arndt@iwr.uni-heidelberg.de>
Sat, 9 Dec 2017 23:55:41 +0000 (00:55 +0100)
cmake/configure/TestBoostBug/CMakeLists.txt [new file with mode: 0644]
cmake/configure/TestBoostBug/polymorphic_base.hpp [new file with mode: 0644]
cmake/configure/TestBoostBug/polymorphic_derived2.cpp [new file with mode: 0644]
cmake/configure/TestBoostBug/polymorphic_derived2.hpp [new file with mode: 0644]
cmake/configure/TestBoostBug/test_dll_exported.cpp [new file with mode: 0644]
cmake/configure/TestBoostBug/text_archive.hpp [new file with mode: 0644]
cmake/configure/configure_boost.cmake

diff --git a/cmake/configure/TestBoostBug/CMakeLists.txt b/cmake/configure/TestBoostBug/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a57ad64
--- /dev/null
@@ -0,0 +1,22 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
+PROJECT(TestBoost)
+
+SET(BOOST_INCLUDE_DIRS CACHE STRING "The include paths for BOOST")
+SET(BOOST_LIBRARIES CACHE STRING "The BOOST libraries to use")
+
+# We assume the BOOST_LIBRARIES to be separated by '|'
+# This matches the change in the separator we do in
+# ../configure_boost.cmake
+STRING(REPLACE "|" ";" BOOST_LIBRARIES_SEPARATED ${BOOST_LIBRARIES})
+INCLUDE_DIRECTORIES(${BOOST_INCLUDE_DIRS})
+
+ADD_LIBRARY(derived SHARED polymorphic_derived2.cpp)
+ADD_EXECUTABLE(test_boost test_dll_exported.cpp)
+
+TARGET_LINK_LIBRARIES(derived ${BOOST_LIBRARIES_SEPARATED})
+TARGET_LINK_LIBRARIES(test_boost derived ${BOOST_LIBRARIES_SEPARATED})
+
+ADD_CUSTOM_TARGET(run
+                  COMMAND test_boost
+                  DEPENDS test_boost
+                  WORKING_DIRECTORY ${CMAKE_PROJECT_DIR})
diff --git a/cmake/configure/TestBoostBug/polymorphic_base.hpp b/cmake/configure/TestBoostBug/polymorphic_base.hpp
new file mode 100644 (file)
index 0000000..7da4d43
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef POLYMORPHIC_BASE_HPP
+#define POLYMORPHIC_BASE_HPP
+
+#include <boost/config.hpp>
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/assume_abstract.hpp>
+#include <boost/serialization/export.hpp>
+#include <boost/serialization/type_info_implementation.hpp>
+#include <boost/serialization/extended_type_info_no_rtti.hpp>
+
+class BOOST_SYMBOL_VISIBLE polymorphic_base
+{
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(
+        Archive & /* ar */, 
+        const unsigned int /* file_version */
+    ){}
+public:
+    // note that since this class uses the "no_rtti"
+    // extended_type_info implementation, it MUST
+    // implement this function
+    virtual const char * get_key() const = 0;
+    virtual ~polymorphic_base(){};
+};
+
+BOOST_SERIALIZATION_ASSUME_ABSTRACT(polymorphic_base)
+
+// the no_rtti system requires this !!!
+BOOST_CLASS_EXPORT_KEY(polymorphic_base)
+
+BOOST_CLASS_TYPE_INFO(
+    polymorphic_base,
+    boost::serialization::extended_type_info_no_rtti<polymorphic_base>
+)
+
+#endif // POLYMORPHIC_BASE_HPP
diff --git a/cmake/configure/TestBoostBug/polymorphic_derived2.cpp b/cmake/configure/TestBoostBug/polymorphic_derived2.cpp
new file mode 100644 (file)
index 0000000..2e445d4
--- /dev/null
@@ -0,0 +1,47 @@
+#include <boost/serialization/type_info_implementation.hpp>
+#include <boost/serialization/extended_type_info_no_rtti.hpp>
+#include <boost/serialization/export.hpp>
+
+#include "polymorphic_derived2.hpp"
+
+template<class Archive>
+void polymorphic_derived2::serialize(
+    Archive &ar, 
+    const unsigned int /* file_version */
+){
+    ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(polymorphic_base);
+}
+
+// instantiate code for text archives
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+template
+void polymorphic_derived2::serialize(
+    boost::archive::text_oarchive & ar,
+    const unsigned int version
+);
+template
+void polymorphic_derived2::serialize(
+    boost::archive::text_iarchive & ar,
+    const unsigned int version
+);
+
+// instantiate code for polymorphic archives
+#include <boost/archive/polymorphic_iarchive.hpp>
+#include <boost/archive/polymorphic_oarchive.hpp>
+
+template
+void polymorphic_derived2::serialize(
+    boost::archive::polymorphic_oarchive & ar,
+    const unsigned int version
+);
+template
+/*POLYMORPHIC_DERIVED2_DLL_DECL*/
+void polymorphic_derived2::serialize(
+    boost::archive::polymorphic_iarchive & ar,
+    const unsigned int version
+);
+
+// note: export has to be AFTER #includes for all archive classes
+BOOST_CLASS_EXPORT_IMPLEMENT(polymorphic_derived2)
\ No newline at end of file
diff --git a/cmake/configure/TestBoostBug/polymorphic_derived2.hpp b/cmake/configure/TestBoostBug/polymorphic_derived2.hpp
new file mode 100644 (file)
index 0000000..078c4fb
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef POLYMORPHIC_DERIVED2_HPP
+#define POLYMORPHIC_DERIVED2_HPP
+
+#include <boost/config.hpp>
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/type_info_implementation.hpp>
+#include <boost/serialization/extended_type_info_typeid.hpp>
+
+#include "polymorphic_base.hpp"
+
+class polymorphic_derived2 :
+    public polymorphic_base
+{
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(
+        Archive &ar, 
+        const unsigned int /* file_version */
+    );
+    virtual const char * get_key() const {
+        return "polymorphic_derived2";
+    }
+};
+
+// we use this because we want to assign a key to this type
+// but we don't want to explicitly instantiate code every time
+// we do so!!!.  If we don't do this, we end up with the same
+// code in BOTH the DLL which implements polymorphic_derived2
+// as well as the main program.
+BOOST_CLASS_EXPORT_KEY(polymorphic_derived2)
+
+// note the mixing of type_info systems is supported.
+BOOST_CLASS_TYPE_INFO(
+    polymorphic_derived2,
+    boost::serialization::extended_type_info_typeid<polymorphic_derived2>
+)
+
+#endif // POLYMORPHIC_DERIVED2_HPP
+
diff --git a/cmake/configure/TestBoostBug/test_dll_exported.cpp b/cmake/configure/TestBoostBug/test_dll_exported.cpp
new file mode 100644 (file)
index 0000000..91ff59a
--- /dev/null
@@ -0,0 +1,98 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// test_dll_exported.cpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// should pass compilation and execution
+
+// This is an overly complex test.  The purpose of this test is to
+// demostrate and test the ability to serialize a hiarchy of class
+// through a base class pointer even though those class might be
+// implemente in different dlls and use different extended type info
+// systems.
+//
+// polymorphic_ base is locally declared and defined.  It use the
+// "no_rtti" extended type info system.
+
+// polymorphic_derived1 is locally declared and defined.  It uses
+// the default "type_id" extended type info system
+
+// polymorphic_derived2 is declared in polymorphic_derived.hpp
+// and defined in dll_polymorphic_derived2.  It uses the typeid
+// system.
+
+#include <cstddef> // NULL
+#include <fstream>
+
+#include <boost/config.hpp>
+
+#include <boost/archive/archive_exception.hpp>
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/export.hpp>
+
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+#include "polymorphic_base.hpp"
+
+#include "polymorphic_derived2.hpp"
+
+// save exported polymorphic class
+void save_exported(const char *testfile)
+{
+    std::ofstream os(testfile);
+    boost::archive::text_oarchive oa(os);
+
+    polymorphic_base *rb2 = new polymorphic_derived2;
+    polymorphic_derived2 *rd21 = new polymorphic_derived2;
+
+    // export will permit correct serialization
+    // through a pointer to a base class
+    oa << BOOST_SERIALIZATION_NVP(rb2);
+    oa << BOOST_SERIALIZATION_NVP(rd21);
+
+    delete rb2;
+    delete rd21;
+}
+
+// save exported polymorphic class
+void load_exported(const char *testfile)
+{
+    std::ifstream is(testfile);
+    boost::archive::text_iarchive ia(is);
+
+    polymorphic_base *rb2 = NULL;
+    polymorphic_derived2 *rd21 = NULL;
+
+    // export will permit correct serialization
+    // through a pointer to a base class
+    ia >> BOOST_SERIALIZATION_NVP(rb2);
+    assert(
+        boost::serialization::type_info_implementation<polymorphic_derived2>
+            ::type::get_const_instance()
+        ==
+        * boost::serialization::type_info_implementation<polymorphic_base>
+            ::type::get_const_instance().get_derived_extended_type_info(*rb2));
+    ia >> BOOST_SERIALIZATION_NVP(rd21);
+    assert(
+        boost::serialization::type_info_implementation<polymorphic_derived2>
+            ::type::get_const_instance()
+        ==
+        * boost::serialization::type_info_implementation<polymorphic_derived2>
+            ::type::get_const_instance().get_derived_extended_type_info(*rd21));
+    delete rb2;
+    delete rd21;
+}
+
+int main( int /* argc */, char* /* argv */[] )
+{
+    save_exported("testfile");
+    load_exported("testfile");
+    return EXIT_SUCCESS;
+}
+
+// EOF
diff --git a/cmake/configure/TestBoostBug/text_archive.hpp b/cmake/configure/TestBoostBug/text_archive.hpp
new file mode 100644 (file)
index 0000000..65425ce
--- /dev/null
@@ -0,0 +1,13 @@
+// (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+// text_archive
+#include <boost/archive/text_oarchive.hpp>
+typedef boost::archive::text_oarchive test_oarchive;
+typedef std::ofstream test_ostream;
+#include <boost/archive/text_iarchive.hpp>
+typedef boost::archive::text_iarchive test_iarchive;
+typedef std::ifstream test_istream;
index 47b18cae816b55c641ba7bf56e41f81ff0a78e22..e44393031e6f3195678d3943e5897e3dae7256d6 100644 (file)
@@ -136,6 +136,54 @@ MACRO(FEATURE_BOOST_FIND_EXTERNAL var)
       RESET_CMAKE_REQUIRED()
     ENDIF()
 
+    IF(${var})
+      # We want to pass the libraries to the CMake project that tests for the
+      # BOOST Serialization bug. If we don't change the separator, only the
+      # first one is passed. This change in the separator is reverted in
+      # TestBoostBug/CMakeLists.txt
+      STRING (REPLACE ";" "|" BOOST_LIBRARIES_SEPARATED "${BOOST_LIBRARIES}")
+
+      FILE(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/cmake/configure/TestBoostBug)
+      FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake/configure/TestBoostBug)
+      EXECUTE_PROCESS(
+        COMMAND ${CMAKE_COMMAND}
+                  -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
+                  -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
+                  -DBOOST_INCLUDE_DIRS=${BOOST_INCLUDE_DIRS}
+                  -DBOOST_LIBRARIES=${BOOST_LIBRARIES_SEPARATED}
+                  ${CMAKE_CURRENT_SOURCE_DIR}/cmake/configure/TestBoostBug
+                  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake/configure/TestBoostBug
+        RESULT_VARIABLE _boost_serialization_usuable
+        OUTPUT_QUIET
+        ERROR_QUIET
+      )
+      IF(${_boost_serialization_usuable} EQUAL 0)
+        EXECUTE_PROCESS(
+          COMMAND ${CMAKE_COMMAND} --build . --target run
+          WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake/configure/TestBoostBug
+          RESULT_VARIABLE _boost_serialization_usuable
+          OUTPUT_QUIET
+          ERROR_QUIET
+        )
+      ENDIF()
+
+      IF(${_boost_serialization_usuable} EQUAL 0)
+        MESSAGE(STATUS "Boost.Serialization is usuable.")
+      ELSE()
+        MESSAGE(STATUS
+                "The externally provided Boost.Serialization library "
+                "failed to pass a crucial test. \n"
+                "Therefore, the bundled boost package is used. \n"
+                "The configured testing project can be found at "
+                "${CMAKE_CURRENT_BINARY_DIR}/cmake/configure/TestBoostBug"
+               )
+        SET(BOOST_ADDITIONAL_ERROR_STRING
+            "The externally provided Boost.Serialization library "
+            "failed to pass a crucial test."
+           )
+        SET(${var} FALSE)
+      ENDIF()
+    ENDIF()
   ENDIF()
 ENDMACRO()
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.