Ask Your Question
1

CMake/Catkin: How to export imported target

asked 2016-01-11 16:28:39 -0500

Dave Coleman gravatar image

updated 2016-01-11 16:40:39 -0500

I have a pre-compiled shared library foo.so, and I'd like to wrap it in a catkin package for use by other catkin packages. So far I can accomplish all the linking issues if foo.so is in the same package as the targets that use it, but I am unable to get other packages to find the library externally. I have the following lines:

add_library(foo SHARED IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/foo.so)

It compiles and runs great if in the same CMakeLists.txt I have something like:

add_library(bar src/bar.cpp}
target_link_libraries(bar
  foo
  ${catkin_LIBRARIES}
)

But if I put this bar library in a different catkin package, it compiles fine but at runtime I get linking errors that then say missing symbols:

symbol lookup error: foo.so: undefined symbol

I have been researching and playing with adding things such as

set(${PROJECT_NAME}_EXPORTED_TARGETS foo)

or

export(TARGET foo)

But I'm really over my head. How do I export a pre-compiled shared library from one catkin package to another? I'm using catkin-tools.

Thanks!

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2016-01-11 17:36:14 -0500

Dave Coleman gravatar image

updated 2016-02-04 11:53:57 -0500

With the help of @wjwwood we came up with this workaround solution that still seems reliable. From what I can tell, CMake does not have proper support for exporting or installing imported targets, as per this discussion:

Imported targets were originally designed for importing from an existing installation of some external package so installing did not make sense at the time.

Our Solution:

In the first package's CMakeLists.txt that contains the pre-compiled shared object that you want to share, you need the following. Note that in this example ${PROJECT_NAME} and "foo" must be the same name, since we are using ${PROJECT_NAME} as the name of the library. This can be changed though.

# Configure Locations
set(foo_LOCATION ${PROJECT_SOURCE_DIR}/lib/libfoo.so)
set(foo_DESTINATION ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_LIB_DESTINATION}/lib${PROJECT_NAME}.so)
MESSAGE( STATUS "foo_LOCATION:         " ${foo_LOCATION} )
MESSAGE( STATUS "foo_DESTINATION:      " ${foo_DESTINATION} )

# Foo library
add_library(${PROJECT_NAME} SHARED IMPORTED)
set_property(TARGET ${PROJECT_NAME} PROPERTY IMPORTED_LOCATION ${foo_LOCATION})

# Unfortuantly an imported target is not copied to the devel/lib folder, so we do it manually
# so that installation of a catkin workspace is not required
# See http://answers.ros.org/question/223866/cmakecatkin-how-to-export-imported-target/
file(COPY ${foo_LOCATION}
  DESTINATION ${foo_DESTINATION}
)


# Mark imported library for installation using a workaround since imported
# targets do not have proper support for installation in CMakeLists
install(FILES ${foo_LOCATION} DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION})

And in the second packge's CMakeLists.txt the foo library is automatically linked using the normal

target_link_libraries(bar
  ${catkin_LIBRARIES}
)
edit flag offensive delete link more

Comments

A similar thing is done in the prosilica_gige_sdk package (here).

gvdhoorn gravatar image gvdhoorn  ( 2016-01-12 06:58:29 -0500 )edit

First of all, awesome work with this solution! I've been using this and the prosilica_gige_sdk to piece together a ROS package for a pre-compiled dll library on Windows. For lack of a better word, it has been... fun.

@Dave Coleman, quick question about your solution, what is the purpose of this section?

# Foo library
add_library(${PROJECT_NAME} SHARED IMPORTED)
set_property(TARGET ${PROJECT_NAME} PROPERTY IMPORTED_LOCATION ${foo_LOCATION})

Since you are copying the library files directly to the devel and install spaces, why do you need to create a CMAKE target for the imported library?

Mitch Woodside gravatar image Mitch Woodside  ( 2020-01-06 17:50:42 -0500 )edit
1

answered 2016-01-11 16:49:52 -0500

duck-development gravatar image

You could copy also the foo lib since it is shared and bar need foo to run. Or you copy the foo lib in /usr/local/lib or you add the path of foe in the lib search path.

edit flag offensive delete link more

Comments

this is what we kind of ended up doing, thanks!

Dave Coleman gravatar image Dave Coleman  ( 2016-01-11 17:37:07 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2016-01-11 16:28:39 -0500

Seen: 2,664 times

Last updated: Feb 04 '16