Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Build system: Option LIBSTDCXX_COMPAT for compatibility with an old l…

…ibstdc++

Jira: MADLIB-263

This commit follows ideas proposed here: http://glandium.org/blog/?p=1901
Unfortunately, MADlib seems to use libstdc++ to a greater extend than Firefox 4.0
did, so we need to do a bit more.

The declarations and definitions in this commit make it possible to build MADlib
with the following versions of gcc (please add to the list), while continuing to
only rely on, e.g., libstdc++.so.6.0.8 (which corresponds to gcc 4.1.2, and
labels GLIBCXX_3.4.8, CXXABI_1.3.1).

Tested with the following versions of gcc:

- gcc 4.4.2
- gcc 4.5.4
- gcc 4.6.2

It should most likely also work with other recent gcc versions.

To use, add the option "-DLIBSTDCXX_COMPAT=40102" when running cmake.
  • Loading branch information...
commit c3db418c0d34d6813608f2137fef1012ce03043d 1 parent aa1f657
Florian Schoppmann authored
View
15 ReadMe_Build.txt
@@ -134,6 +134,21 @@ root directory) for more options, after having run `cmake` the first time.
Note: If no `GREENPLUM<...>_PG_CONFIG` is specified, the build script will
look for `/usr/local/greenplum-db/bin/pg_config`.
+- `LIBSTDCXX_COMPAT` (default: *empty*)
+
+ If GNU gcc is used to build MADlib and link against the GNU libstdc++, this
+ option may be used to set the maximum version of libstdc++ acceptable as a
+ runtime dependency (not supported on Mac OS X). E.g., if MADlib should
+ require no more than the libstdc++ shipped with gcc 4.1.2, call
+ `./configure` with `-DLIBSTDCXX_COMPAT=40102`.
+
+ The current minimum value supported for option `LIBSTDCXX_COMPAT` is
+ `40102`, and the latest version of gcc supported when setting this option is
+ gcc 4.6.x.
+
+ Setting this option will enable workarounds in
+ `src/utils/libstdcxx-compatibility.cpp`.
+
- `BOOST_TAR_SOURCE` (default: *empty*)
If no recent version of Boost is found (>= 1.46), Boost is downloaded
View
20 license/third_party/_M_widen_init.txt
@@ -0,0 +1,20 @@
+std::ctype<char>::_M_widen_init() is a function authored by Jerry Quinn
+<jlquinn@optonline.net>, which was added to libstdc++ with revision 74662 on
+Dec 16, 2003 [1].
+
+With permission from Jerry (thankfully received on Oct 9, 2012), we include a
+copy of this function in the MADlib repository. The sole intention is to allow
+compiling MADlib with recent versions of gcc while still keeping the runtime
+dependencies limited to earlier versions of libstdc++. Technical details are
+given in src/utils/libstdcxx-compatibility.cpp.
+
+Revision 74662 of the libstdc++-v3 file include/bits/locale_facets.h, where
+std::ctype<char>::_M_widen_init() has been copied from, also included the
+following notice in the file header [2]:
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. [...]
+
+Links:
+[1] http://gcc.gnu.org/viewcvs?diff_format=h&view=revision&revision=74662
+[2] http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/bits/locale_facets.h?diff_format=h&view=markup&pathrev=74662
View
20 src/CMakeLists.txt
@@ -257,13 +257,29 @@ file(GLOB_RECURSE MAD_CPP_SOURCES
list(APPEND MAD_SOURCES
${MAD_CPP_SOURCES}
)
+if((NOT APPLE) AND LIBSTDCXX_COMPAT AND CMAKE_COMPILER_IS_GNUCXX)
+ if(GNUCXX_VERSION VERSION_GREATER 4.1.2)
+ math(EXPR LIBSTDCXX_COMPAT_MAJOR "${LIBSTDCXX_COMPAT} / 10000")
+ math(EXPR LIBSTDCXX_COMPAT_MINOR "(${LIBSTDCXX_COMPAT} / 100) % 100")
+ math(EXPR LIBSTDCXX_COMPAT_PATCH "${LIBSTDCXX_COMPAT} % 100")
+ set(LIBSTDCXX_COMPAT_VERSION "${LIBSTDCXX_COMPAT_MAJOR}.${LIBSTDCXX_COMPAT_MINOR}.${LIBSTDCXX_COMPAT_PATCH}")
+ message(STATUS "Compatibility with libstdc++ of g++ "
+ "${LIBSTDCXX_COMPAT_VERSION} requested (current g++ version is "
+ "${GNUCXX_VERSION}).")
+ message(STATUS "If this does not work, try option INCLUDE_LIBSTDCXX "
+ "instead, in order to redistribute the build-time libstdc++.")
+ list(APPEND MAD_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/utils/libstdcxx-compatibility.cpp")
+ add_definitions("-DLIBSTDCXX_COMPAT=${LIBSTDCXX_COMPAT}")
+ endif(GNUCXX_VERSION VERSION_GREATER 4.1.2)
+endif((NOT APPLE) AND LIBSTDCXX_COMPAT AND CMAKE_COMPILER_IS_GNUCXX)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if(CMAKE_COMPILER_IS_GNUCXX)
if(GNUCXX_VERSION VERSION_GREATER 4.4 OR GNUCXX_VERSION VERSION_EQUAL 4.4)
- if(_AUTOINCLUDE_LIBSTDCXX)
+ if(INCLUDE_LIBSTDCXX)
# FIXME: The following only takes care of the symbolic link
# Need to implement copying of files containing version numbers in
# file name
@@ -288,7 +304,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
)
add_custom_target(copyLibStdCXX ALL DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/lib/${_LIBSTDCXX_FILENAME}")
- endif(_AUTOINCLUDE_LIBSTDCXX)
+ endif(INCLUDE_LIBSTDCXX)
# Also install it
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
View
232 src/utils/libstdcxx-compatibility.cpp
@@ -0,0 +1,232 @@
+/* ----------------------------------------------------------------------- *//**
+ *
+ * @file libstdcxx-compatibility.cpp
+ *
+ * @brief Declarations/definitions for using an "old" libstdc++ with a newer g++
+ *
+ * This file follows ideas proposed here: http://glandium.org/blog/?p=1901
+ * Unfortunately, MADlib seems to use libstdc++ to a greater extend than
+ * Firefox 4.0 did, so we need to do a bit more.
+ *
+ * The declarations and definitions in this file make it possible to build
+ * MADlib with the following versions of gcc (please add to the list), while
+ * continuing to only rely on libstdc++.so.6.0.8 (which corresponds to
+ * gcc 4.1.2, and labels GLIBCXX_3.4.8, CXXABI_1.3.1).
+ *
+ * As of September 2012, there is still the need to support libstdc++.so.6.0.8,
+ * as this is the libstdc++ that shipped with RedHad/CentOS 5.
+ *
+ * Tested with the following versions of gcc:
+ * - gcc 4.4.2
+ * - gcc 4.5.4
+ * - gcc 4.6.2
+ *
+ * For a mapping between gcc versions, libstdc++ versions, and symbol versioning
+ * on the libstdc++.so binary, see:
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
+ *
+ *//* ----------------------------------------------------------------------- */
+
+#include <ostream>
+
+// The following macro was introduced with this commit:
+// http://gcc.gnu.org/viewcvs?diff_format=h&view=revision&revision=173774
+#ifndef _GLIBCXX_USE_NOEXCEPT
+ #define _GLIBCXX_USE_NOEXCEPT throw()
+#endif
+
+#define GCC_VERSION ( __GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+// CXXABI_1.3.2 symbols
+
+#if (LIBSTDCXX_COMPAT < 40300 && GCC_VERSION >= 40300)
+
+namespace __cxxabiv1 {
+
+/**
+ * @brief Virtual destructor for forced-unwinding class
+ *
+ * We provide an implementation to avoid CXXABI_1.3.2 symbol versions.
+ *
+ * Older versions of libstdc++ had the problem that POSIX thread cancellations
+ * while writing to an ostream caused an abort:
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28145
+ *
+ * Newer versions have an additional catch block for references of type
+ * __cxxabiv1::__forced_unwind, which represents the POSIX cancellation object:
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html
+ * See, e.g., file <bits/ostream.tcc> included from <ostream>. Catching
+ * exceptions of this type requires its \c type_info object. However, this
+ * object is not normally present in the current binary, as explained in the
+ * following.
+ *
+ * The type __cxxabiv1::__forced_unwind was only introduced in May 2007 (see
+ * attachments to the previous bug report) and thus after the release of
+ * gcc 4.1.2 (Feb 13, 2007, see http://gcc.gnu.org/releases.html).
+ *
+ * As http://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html explains:
+ * <blockquote>
+ * If the class declares any non-inline, non-pure virtual functions, the
+ * first one is chosen as the "key method" for the class, and the vtable is
+ * only emitted in the translation unit where the key method is defined.
+ * <blockquote>
+ *
+ * And later on the same page:
+ * <blockquote>
+ * For polymorphic classes (classes with virtual functions), the
+ * \c type_info object is written out along with the vtable [...].
+ * <blockquote>
+ *
+ * Hence, to include a vtable, we need a definition for the key method, which is
+ * the constructor. See the declaration here:
+ * http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/libsupc%2B%2B/cxxabi_forced.h
+ */
+__forced_unwind::~__forced_unwind() _GLIBCXX_USE_NOEXCEPT { }
+
+} // namespace __cxxabiv1
+
+#endif // (LIBSTDCXX_COMPAT < 40300 && GCC_VERSION >= 40300)
+
+
+// GLIBCXX_3.4.9 symbols
+
+#if (LIBSTDCXX_COMPAT < 40200 && GCC_VERSION >= 40200)
+
+namespace std {
+
+/**
+ * @brief Write a value to an ostream
+ *
+ * In recent versions of libstdc++, \c _M_insert contains the implementation for
+ * the various operator<<() overloads. Now, as http://glandium.org/blog/?p=1901
+ * explains, newer libstdc++ versions contain various instantiations for
+ * \c _M_insert, even though <bits/ostream.tcc> contains a general (template)
+ * definition.
+ *
+ * Older versions of libstdc++ did not contain implementations for \c _M_insert,
+ * so we instantiate them here. See this change:
+ * http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/bits/ostream.tcc?r1=109235&r2=109236&
+ */
+template ostream& ostream::_M_insert(bool);
+// The following four lines are not needed and commented out. Specialized
+// implementations exist for ostream<<([unsigned] {short|int}).
+// template ostream& ostream::_M_insert(short);
+// template ostream& ostream::_M_insert(unsigned short);
+// template ostream& ostream::_M_insert(int);
+// template ostream& ostream::_M_insert(unsigned int);
+template ostream& ostream::_M_insert(long);
+template ostream& ostream::_M_insert(unsigned long);
+#ifdef _GLIBCXX_USE_LONG_LONG
+template ostream& ostream::_M_insert(long long);
+template ostream& ostream::_M_insert(unsigned long long);
+#endif
+template ostream& ostream::_M_insert(float);
+template ostream& ostream::_M_insert(double);
+template ostream& ostream::_M_insert(long double);
+template ostream& ostream::_M_insert(const void*);
+
+/**
+ * @brief Write a sequence of characters to an ostream
+ *
+ * This function was only added with this commit:
+ * http://gcc.gnu.org/viewcvs?view=revision&revision=123692
+ */
+template ostream& __ostream_insert(ostream&, const char*, streamsize);
+
+} // namespace std
+
+#endif // (LIBSTDCXX_COMPAT < 40200 && GCC_VERSION >= 40200)
+
+
+// GLIBCXX_3.4.11 symbols
+
+#if (LIBSTDCXX_COMPAT < 40400 && GCC_VERSION >= 40400)
+
+namespace std {
+
+/**
+ * @brief Initialize an internal data structure of ctype<char>
+ *
+ * This was previously an inline function and moved out of line with this
+ * commit:
+ * http://gcc.gnu.org/viewcvs?view=revision&revision=140238
+ *
+ * See also this bug report:
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37455
+ *
+ * std::ctype<char>::_M_widen_init() is a function added to libstdc++ by
+ * Jerry Quinn with revision 74662 on Dec 16, 2003:
+ * http://gcc.gnu.org/viewcvs?diff_format=h&view=revision&revision=74662
+ *
+ * With explicit permission by Jerry Quinn from Oct 9, 2012, we include a
+ * verbatim copy of _M_widen_init() here. However, a static_cast was added to
+ * avoid a warning.
+ *
+ * Revision 74662 of the libstdc++-v3 file include/bits/locale_facets.h, where
+ * std::ctype<char>::_M_widen_init() has been copied from, also included the
+ * following notice in the file header:
+ * http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/bits/locale_facets.h?diff_format=h&view=markup&pathrev=74662
+ *
+ * <blockquote>
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction. [...]
+ * <blockquote>
+ */
+void
+ctype<char>::_M_widen_init() const {
+ char __tmp[sizeof(_M_widen)];
+ for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
+ __tmp[__i] = __i;
+ do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
+
+ _M_widen_ok = 1;
+ // Set _M_widen_ok to 2 if memcpy can't be used.
+ for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i)
+ if (__tmp[__i] != _M_widen[__i]) {
+ _M_widen_ok = 2;
+ break;
+ }
+}
+
+} // namespace std
+
+#endif // (LIBSTDCXX_COMPAT < 40400 && GCC_VERSION >= 40400)
+
+
+// GLIBCXX_3.5.15 symbols
+
+#if (LIBSTDCXX_COMPAT < 40600 && GCC_VERSION >= 40600)
+
+#include <stdexcept>
+
+namespace std {
+
+/**
+ * @brief Empty dtors for standard exceptions
+ *
+ * Later versions of libstdc++ added destructors to some standard exceptions.
+ * Definitions for these are missing in older versions of libstdc++.
+ *
+ * Of course, additing destructors is potentially dangerous and can change the
+ * ABI. However, these classes derived from \c runtime_error and \c logic_error
+ * before and therefore have always had virtual members.
+ *
+ * The first commit that added these destructors is:
+ * http://gcc.gnu.org/viewcvs?diff_format=h&view=revision&revision=170975
+ * This commit was included already in the first gcc 4.6.0 release:
+ * http://gcc.gnu.org/viewcvs/tags/gcc_4_6_0_release/libstdc%2B%2B-v3/src/stdexcept.cc
+ */
+domain_error::~domain_error() _GLIBCXX_USE_NOEXCEPT { }
+invalid_argument::~invalid_argument() _GLIBCXX_USE_NOEXCEPT { }
+length_error::~length_error() _GLIBCXX_USE_NOEXCEPT { }
+out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { }
+runtime_error::~runtime_error() _GLIBCXX_USE_NOEXCEPT { }
+range_error::~range_error() _GLIBCXX_USE_NOEXCEPT { }
+overflow_error::~overflow_error() _GLIBCXX_USE_NOEXCEPT { }
+underflow_error::~underflow_error() _GLIBCXX_USE_NOEXCEPT { }
+
+} // namespace std
+
+#endif // (LIBSTDCXX_COMPAT < 40600 && GCC_VERSION >= 40600)
Please sign in to comment.
Something went wrong with that request. Please try again.