4

I just started using Eigen and I've run into a multiple definition issue. I've tracked down the precise issue, and here's a minimal example.

Works:

// File common1.hpp
#include <Eigen/Dense>
// File common2.hpp
#include "common1.hpp"
// File main.cpp
#include "common2.hpp"

clang++ main.cpp compiles with this.

Doesn't work:

// File common1.hpp
#include <Eigen/Dense>
// File common2.hpp
#include "common1.hpp"
// File common2.cpp
#include "common2.hpp"
// File main.cpp
#include "common2.hpp"

clang++ main.cpp common2.cpp fails with this with the error:

/tmp/common2-f75caf.o: In function `bool Eigen::numext::equal_strict<double, double>(double const&, double const&)':
common2.cpp:(.text+0x30): multiple definition of `bool Eigen::numext::equal_strict<double, double>(double const&, double const&)'
/tmp/main-8e7100.o:main.cpp:(.text+0x30): first defined here
/tmp/common2-f75caf.o: In function `bool Eigen::numext::equal_strict<float, float>(float const&, float const&)':
common2.cpp:(.text+0x0): multiple definition of `bool Eigen::numext::equal_strict<float, float>(float const&, float const&)'
/tmp/main-8e7100.o:main.cpp:(.text+0x0): first defined here
/tmp/common2-f75caf.o: In function `bool Eigen::numext::not_equal_strict<double, double>(double const&, double const&)':
common2.cpp:(.text+0x90): multiple definition of `bool Eigen::numext::not_equal_strict<double, double>(double const&, double const&)'
/tmp/main-8e7100.o:main.cpp:(.text+0x90): first defined here
/tmp/common2-f75caf.o: In function `bool Eigen::numext::not_equal_strict<float, float>(float const&, float const&)':
common2.cpp:(.text+0x60): multiple definition of `bool Eigen::numext::not_equal_strict<float, float>(float const&, float const&)'
/tmp/main-8e7100.o:main.cpp:(.text+0x60): first defined here
clang-7.0: error: linker command failed with exit code 1 (use -v to see invocation)

I really like Eigen's C++ API, and I'd really like to keep using it. I've looked at a few projects that use Eigen, and they do the second block of code using their own namespaces. I tried that, but got the same error. Any help would be appreciated.

Edit: Clang version 7. Eigen: Pulled from Github mirror in the past month or so.

Chronum
  • 187
  • 6
  • 1
    Cannot reproduce here (Arch Linux with clang 6, not clang 7). Do you get the same error with gcc? – Philipp Claßen Apr 30 '18 at 20:08
  • I did get the same error with gcc, if I remember right. gcc 7.2.0. Edited question. Maybe this is a problem with the recent changes and a release version like 3.3.4 would work? – Chronum Apr 30 '18 at 20:14
  • 1
    `Meta.h` in `Eigen/src/Core/util`, lines 551-566 on https://github.com/eigenteam/eigen-git-mirror – Chronum Apr 30 '18 at 20:22
  • 3
    https://github.com/eigenteam/eigen-git-mirror/blob/923e74c74ad451297957554f741f43f70e66e54b/Eigen/src/Core/util/Meta.h#L548-L557 – melpomene Apr 30 '18 at 20:29
  • Weird. Those functions [are marked as `inline` regardless](https://github.com/eigenteam/eigen-git-mirror/blob/3d9d5982609bc227f86d7f760f59ee26abddfab4/Eigen/src/Core/util/Macros.h#L522-L528), (I didn't have to look up whether explicit template function specializations are automatically `inline` like template functions are). – Justin Apr 30 '18 at 20:30
  • So it appears that something's just broken with bleeding-edge versions of Eigen and I should just use the latest release version? It's still a bit off since Philipp couldn't reproduce this, but maybe the Eigen version is different? – Chronum Apr 30 '18 at 20:40
  • The solution appears to be to use the release version of Eigen (3.3.4 as of writing this). I'll leave this up for a bit longer to see if anyone else has any ideas. If not, this appears to be a solution, so I'll add it. – Chronum Apr 30 '18 at 21:28
  • "Eigen: Pulled from Github mirror in the past month or so." what is the exact tag or commit that your clone is at (`git log -n 1` to get the commit hash)? The code written there might be buggy, which could explain what happened here – Justin Apr 30 '18 at 22:36
  • 1
    The commit marked by @melpomene should have fixed your issue. Here is the corresponding commit in the orininal repository for reference: https://bitbucket.org/eigen/eigen/commits/1f08827edccbe08648146cc584fcbd7f4bfb3e33 – chtz May 01 '18 at 00:49
  • @chtz https://github.com/eigenteam/eigen-git-mirror/commit/11a3c93ee327dd2be34bc56bc04a5ebcb3340256 This does in fact cause the exact problem that I had. And the inlining hasn't happened yet, which would explain it. – Chronum May 01 '18 at 01:17
  • The problem is that the git mirror has stopped to sync 8 days ago. – ggael May 01 '18 at 04:08
  • https://github.com/eigenteam/eigen-git-mirror still seems to be a mirror of https://bitbucket.org/eigen/eigen/, as of the commit 10 hours ago. Am I missing something? – Chronum May 01 '18 at 04:40

1 Answers1

2

This was the results of https://github.com/eigenteam/eigen-git-mirror/commit/11a3c93ee327dd2be34bc56bc04a5ebcb3340256 where the relevant functions in the error haven't been inlined yet.

This can be fixed in general by using Eigen's latest release version (3.3.4 at the time of writing this), or more specifically, by using code at or after https://github.com/eigenteam/eigen-git-mirror/commit/37ca6e8ee578bf490b04f4e977c4ecb081d35e9f

On Bitbucket, 37ca6e is https://bitbucket.org/eigen/eigen/commits/1f08827edccbe08648146cc584fcbd7f4bfb3e33

Both test cases now work, thanks to everyone who helped find/fix this.

Chronum
  • 187
  • 6