Hi. I'm packaging something that uses Eigen, and I'm running into a persistent compatibility issue I don't currently know how to solve. Help appreciated.
Here's the problem. Eigen is a C++ header-only library that's heavy into templating. So all the functions inside Eigen produce weak symbols, and usually the linker will see many identical copies of the same weak symbol, from each compile unit and shared object being linked. The linker picks ONE of the weak definitions. This is the intended behavior in C++ because every copy is supposed to be identical. But in Eigen they're not identical: it does different things based on preprocessor defines, and you get crashes. Here's a simplified illustration of what happens. eigen3/Eigen/src/Core/util/Memory.h contains: EIGEN_DEVICE_FUNC inline void* aligned_malloc(std::size_t size) { check_that_malloc_is_allowed(); void *result; #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED EIGEN_USING_STD(malloc) result = malloc(size); #if EIGEN_DEFAULT_ALIGN_BYTES==16 eigen_assert((size<16 || (std::size_t(result)%16)==0) && "System's malloc returned an unaligned pointer. Compile with EIGEN_MALLOC_ALREADY_ALIGNED=0 to fallback to handmade aligned memory allocator."); #endif #else result = handmade_aligned_malloc(size); #endif if(!result && size) throw_std_bad_alloc(); return result; } EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr) { #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED EIGEN_USING_STD(free) free(ptr); #else handmade_aligned_free(ptr); #endif } The EIGEN_DEFAULT_ALIGN_BYTES and EIGEN_MALLOC_ALREADY_ALIGNED macros can vary based on things like __SSE__ and __AVX__ and such. Now let's say you're packaging a library. Let's call it libg2o. This is NOT header-only, and somewhere it does #include <Eigen/....> which eventually includes Memory.h. The libg2o.so that ends up in the "libg2o0" package then gets a weak symbol for "aligned_malloc" and "aligned_free" that encodes the compiler flags that were used when building libg2o.so. So far so good. Now let's say you have a user. They're writing a program that uses both libg2o and Eigen. They're writing their own application, not intended to go into Debian. So they build with -msse -mavx and all the other fun stuff. THEIR weak copies of "aligned_malloc" and "aligned_free" are different and incompatible with the copies in libg2o. And the application is then likely to crash because at least something somewhere will be allocated with one copy and deallocated with another. This is just terrible design from the eigen and c++ people, but that's what we have. Has anybody here run into this? How does one build the libg2o package so that users don't crash their application when using it? I tried to demand maximum alignment in libg2o, which fixes some things but not all. Currently debugging to find a better solution, but I suspect somebody has already fought this. Thanks