# CMake/Catkin: How to export imported target

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 close merge delete ## 2 Answers Sort by » oldest newest most voted 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
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} )  more ## Comments A similar thing is done in the prosilica_gige_sdk package (here). ( 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?

( 2020-01-06 17:50:42 -0500 )edit

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.

more

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

( 2016-01-11 17:37:07 -0500 )edit