Linking G+Smo together with other libraries that also use Eigen leads to problems #566
-
Hello everyone, when I try to link G+Smo and some other library that also uses Eigen into a bigger product, bad things start happening. The rest of the text is organised as follows.
Apologies for it being long, bear with me, please. (-; ExampleWe link G+Smo plus a library "another" together into an executable called "main". It assumes that we have compiled G+Smo in release mode and installed it to /path/to/install folder and that there is a copy of Eigen in /path/to/. Here's a scheme:
another/another.h #include <Eigen/IterativeLinearSolvers>
void useEigen(); another/another.cpp #include <Eigen/IterativeLinearSolvers>
#include <iostream>
void useEigen()
{
Eigen::SparseMatrix<double> lhs(2, 2);
lhs.insert(0, 0) = 1;
lhs.insert(1, 1) = 1;
Eigen::Vector2d rhs, res;
rhs(0) = 1;
rhs(1) = 2;
typename Eigen::BiCGSTAB<Eigen::SparseMatrix<double>, Eigen::IncompleteLUT<double> > solver;
solver.compute(lhs);
std::cout << "Solution to the system is:\n" << solver.solve(rhs) << "." << std::endl;
} another/Makefile CPPFLAGS += -Wall -fPIC -I/path/to/eigen
LDFLAGS += -shared
.PHONY: all clean
all: libanother.so
libanother.so: another.cpp
$(LINK.cc) $^ -o $@ $(LDLIBS)
clean:
@- $(RM) libanother.so main.cpp #include <gismo.h>
#include <another.h>
void useGismo()
{
gismo::gsBSplineBasis<double> basis(0.0, 1.0, 0, 2);
gismo::gsMatrix<double> u(1, 1);
u(0, 0) = 0.5;
gismo::gsMatrix<double> val = basis.eval(u);
std::cout << "3rd quadratic Bernstein polynomial at 0.5 evaluates to " << val(2, 0) << "." << std::endl;
}
int main()
{
useGismo();
useEigen();
return 0;
} Makefile
Let's compile everything:
Running the executable leads to
Exercise: Comment out the body of the function DiscussionIt is my understanding that the problem here is the co-existence of two copies of Eigen, which leads to a confusion during runtime. Solution 1We can rename the namespace
After re-compiling and re-installing G+Smo as well as of the "another" library, everything works now:
Caveats
Solution 2If I remember correctly, @filiatra is aware of the problem and has suggested to wrap the Solution 3Any ideas? |
Beta Was this translation helpful? Give feedback.
Replies: 14 comments
-
Hi and thnx for this report, I tried Solution 2 but it is rather complicated to do due to all the system file inclusions etc. A simple Solution 3: There will be always a possible problem of course: As you mention in Caveat 2, we need to impose the Eigen headers of G+Smo over the Eigen headers of "another". This might have an impact on "another" in the sense that it might expect a different version of Eigen. The only complete solution I can see here is a kind of Solution 2. But it looks very hard to do. |
Beta Was this translation helpful? Give feedback.
-
OK here is my proposed solution, finally closer to Solutions 1 and 2:
It seems to work. Including "gismo.h" before Eigen (g. in main.cpp) is recommended, and works fine. Including "gismo.h" after Eigen also works but produces some warnings: warning: "EIGEN_DEFAULT_DENSE_INDEX_TYPE" redefined These warn about the configuration of Eigen has changed inside G+Smo, therefore they can be useful to keep. Here is the commit (at branch eigen_fix) : https://github.com/gismo/gismo/compare/eigen_fix |
Beta Was this translation helpful? Give feedback.
-
Thanks! You are right in that we should also do something about folder naming and include guards.
I took the liberty of committing two little fixes. I will keep you updated about my testing progress. |
Beta Was this translation helpful? Give feedback.
-
After spending a weekend with this I am more confused than before. What seems clear is that there is a bug in my example: the Makefile of "another" should use the same compiler flags as the Makefile of "main", i.e., line 1 should read
The Eigen problem then disappears, at least in this example. @filiatra , can you reproduce it? |
Beta Was this translation helpful? Give feedback.
-
Thnx for the fixes. I think it is expected that if all compiler flags are the same and the eigen version is the same then eventually it will work even without renaming the namespace. |
Beta Was this translation helpful? Give feedback.
-
Here's one more idea (suggested by a friend of mine): Solution 4 Say we call this switch
to obtain an installed version of G+Smo that does not have Eigen in the install folder. One Eigen, no problem! This has a few advantages compared to renaming the namespace:
What do you think? |
Beta Was this translation helpful? Give feedback.
-
Yes this is a good idea and has I think we should do that. But I find it is also independent from the question to some extent: It does not really solve your problem where you have a library already compiled with Eigen possibly on a different machine and you try to link it to gismo after compiling it (possibly with Eigen installed in the system). So maybe Solution 3+4 should co-exist? |
Beta Was this translation helpful? Give feedback.
-
Ah, I see, you want to solve a more general problem. My goal was more modest: I was aiming at compiling both G+Smo and the other library on the same machine, with the same compiler (to avoid name-mangling problems) and with the same Eigen. In the end, I would like to be able to do something like
I think that Solution 4 would be enough for this but not for the situation you mention. To be honest, that situation seems quite difficult to me and I am not sure if we can realistically hope to be able solve it. Or do you think that Solution 3 would be enough then?
If we go for Solution 3, I don't see any advantage of going for 4 as well. Am I missing something? |
Beta Was this translation helpful? Give feedback.
-
For sure the more general problem can be solved to some extent, there could always be conflicts. The interest I see Solution 4 is two points:
For Solution 3:
Overall I can see situations where either delegating to external Eigen or wanting to use our own private & renamed copy will came in handy |
Beta Was this translation helpful? Give feedback.
-
I agree with you in all the points you mention.
Yes. For me it is difficult to imagine using Solution 3 and 4 at the same time. So I guess we need to choose one of them or come up with something yet different. Do you know of any guidelines or best practices that we can read? I have spent quite some time googling around but without much luck except for this suggestion to do what we did with Eigen so far. |
Beta Was this translation helpful? Give feedback.
-
Solution 5 Make another depend not the copy of Eigen in /path/to/eigen but to G+Smo's Eigen in /path/to/gismo/external. This solution is surprisingly simple and has been working very well for me since 1.5 years or so. It would break though if another would follow the same philosophy as G+Smo, i.e., if it were shipped with its own copy of Eigen. Since this is not very probable, I think there is no acute need for action in G+Smo now. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Yes, please. |
Beta Was this translation helpful? Give feedback.
-
We have gone for solution 1 in PR #617 . This still does not prevent using solution 5. |
Beta Was this translation helpful? Give feedback.
We have gone for solution 1 in PR #617 . This still does not prevent using solution 5.