Ceres install, local lib global include

716 views
Skip to first unread message

Chris Sweeney

unread,
Feb 10, 2015, 4:40:25 AM2/10/15
to ceres-...@googlegroups.com
Hi,

I ran into an interesting installation error for Ceres recently. I am compiled a library (lets call it LibFoo) that uses Ceres and all compiles and works well. Then in a separate library, MyLib, I include and link LibFoo. Now when I compile MyLib I am getting an error:

/usr/bin/ld: //usr/local/lib/libceres.a(evaluator.cc.o): undefined reference to symbol 'pthread_rwlock_wrlock@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

I see that this error happened before on this list because of a thread library export. What is interesting, though, is that it appears that when LibFoo uses FIND_PACKAGE(Ceres) the variables CERES_INCLUDE_DIRS is "/usr/local/include;/usr/local/include/eigen3;/usr/include"  but CERES_LIBRARIES is simply "ceres". So (I think) the installed headers are found but the local lib is being used...?

I further examined the Targets-release.cmake file for LibFoo and notice:

set_target_properties(foo PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "ceres;/usr/lib/x86_64-linux-gnu/libgflags.so;/usr/lib/x86_64-linux-gnu/libglog.so;"
  IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libfoo.a"
  )

Note that LibFoo uses gflags, and glog on its own. As said before, LibFoo compiles and works fine on its own, it is only when I try to compile MyLib with LibFoo that things break. It seems weird that the ceres lib would be the local library... could this be why I am getting this error?

Thanks,
Chris

Alex Stewart

unread,
Feb 10, 2015, 5:07:01 AM2/10/15
to ceres-...@googlegroups.com
Chris,

This is a common confusion, when you use find_package() to pull in Ceres:

find_package(Ceres REQUIRED)
message("CERES_LIBRARIES = ${CERES_LIBRARIES}")

You would see the output:

CERES_LIBRARIES = ceres

*However*, this does *not* refer to the compiled Ceres library: /usr/local/libceres.a/so (assuming you installed it there), but instead it is the *name* of a CMake imported target which gets declared when /usr/local/share/Ceres/CeresConfig.cmake is read, which is what happens when you call find_package(Ceres).

If you added the following:

get_target_property(CERES_IMPORTED_LIBS ${CERES_LIBRARIES} IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE)
message("CERES_IMPORTED_LIBS = ${CERES_IMPORTED_LIBS}”)

You would see any other public link libraries for your Ceres build (/usr/local/lib/libglog.so usually), similarly you can query for the actual libceres.a/so library that the imported CMake target represents.

The reason you are having an issue is that imported targets are *not* (re)exported when a project which imported them is exported.  Somewhat annoyingly, instead what is exported is just the name of the imported target, with no other information.  Hence when you exported Foo, you see ‘ceres’ in the list of link libraries.  The issue is that in a project which imports Foo, CMake will interpret ‘ceres’ as meaning libceres.a/so if it exists on the path.  This loses all information about other link libraries required that was present in the exported Ceres target.

The solution to this, is to add a find_package(Ceres QUIET) to your FooConfig.cmake, that way whenever anyone calls find_package(Foo), and FooConfig.cmake is called it will try and find Ceres (quietly, so no errors will be thrown - this is up to you, if Foo requires Ceres then remove QUIET - see my link below for a more expansive solution).  This will result in CeresConfig.cmake being called (when building MyLib), and thus the ‘ceres’ target will be imported into the current project (MyLib in your example) - then everything should build fine, because now ‘ceres’ refers to the imported target, not just the compiled libceres.a/so library on its own.

As you’re actually the second person this week to ask me about this (although the first for Ceres), I will update the docs to add some info on this.

-Alex

P.S. I also wrote this up for an issue someone raised previously here: https://code.google.com/p/ceres-solver/issues/detail?id=143 (I don’t mean of course that you should have found/read this - just adding a link in case my previous explanation was any clearer).


--
You received this message because you are subscribed to the Google Groups "Ceres Solver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceres-solver...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/c2cb63a9-1b82-4433-aba8-d56d90c38ed6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Sweeney

unread,
Feb 10, 2015, 5:11:32 AM2/10/15
to ceres-...@googlegroups.com
Hi Alex,

Thank you so much for the detailed response. Your explanation makes perfect sense and further thanks for explaining it in a way that non-CMake experts (like me) can easily understand.

Glad to see the issue lies with Foo and not with Ceres. I will fix things in Foo on my end then!

Chris

Reply all
Reply to author
Forward
0 new messages