Ask Your Question
1

How let other catkin packages depend on a library built with ExternalProject_Add(...)?

asked 2016-05-02 07:57:30 -0500

Hi,

I encountered difficulties wrapping an external driver into a catkin package such that other catkin packages can depend on it. The driver is provided by a company as open-source, it builds without cmake, and it is distributed through a public mercurial repository.

To conveniently pull in upstream updates, I wanted to have the build process checkout and build a specific commit. I know this is discouraged behavior for releasing ROS packages through the build-farm. But for the moment I do not intend to release the package through the build-farm.

I tried using the CMake command ExternalProject_Add because of the following question: http://answers.ros.org/question/63259...

Building the driver library works fine, but any depending catkin package is not aware of the build target for the library. Does anybody know how to properly expose the library and the build target itself to other catkin packages?

Here are the details. In my package igh_eml I successfully build a library called ethercat. igh_eml's CMakeLists.txt looks like this:

project(igh_eml)

find_package(catkin REQUIRED)

catkin_package(
  INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/include
  LIBRARIES ethercat)

include(ExternalProject)
ExternalProject_Add(upstream_igh_eml
# #--Download step----------
  HG_REPOSITORY http://hg.code.sf.net/p/etherlabmaster/code         # URL of mercurial repo
  HG_TAG 792892ab4806                # Mercurial branch name, commit id or tag
  TIMEOUT 30           # Time allowed for file download operations
  # #--Update/Patch step----------
  UPDATE_COMMAND touch <SOURCE_DIR>/config.h COMMAND mkdir -p <SOURCE_DIR>/include <SOURCE_DIR>/lib    # Source work-tree update command
  # #--Configure step-------------
  CONFIGURE_COMMAND touch <SOURCE_DIR>/ChangeLog COMMAND autoreconf -i <SOURCE_DIR> COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --disable-kernel --enable-hrtimer --enable-tool  # Build tree configuration command
  # #--Build step-----------------
  BUILD_IN_SOURCE 1         # Use source dir for build dir
)

ExternalProject_Get_Property(upstream_igh_eml source_dir)

add_custom_command(TARGET upstream_igh_eml POST_BUILD
    COMMAND cp 
      ${source_dir}/../../include/ecrt.h 
      ${CATKIN_DEVEL_PREFIX}/include/
)

add_custom_command(TARGET upstream_igh_eml POST_BUILD
     COMMAND cp 
     ${source_dir}/../../include/ectty.h
     ${CATKIN_DEVEL_PREFIX}/include
)

add_custom_command(TARGET upstream_igh_eml POST_BUILD
    COMMAND cp 
    ${source_dir}/../../lib/libethercat.so
    ${CATKIN_DEVEL_PREFIX}/lib
 )

Here is a link to the actual file: https://github.com/code-iai/iai_robot...

My second package omnidriver_ethercat depends on igh_eml on gives this error:

CMake Error at /home/georg/ros/indigo/boxy_refactoring/devel/share/igh_eml/cmake/igh_emlConfig.cmake:141 (message):
  Project 'omni_ethercat' tried to find library 'ethercat'.  The library is
  neither a target nor built/installed properly.  Did you compile project
  'igh_eml'? Did you find_package() it before the subdirectory containing its
  code is included?

Here is a link to CMakeLists of omnidrive_ethercat : https://github.com/code-iai/iai_robot...

Does anybody know how I declare that the library ethercat will be build through ExternalProject_Add? Furthermore, how can I make other catkin packages wait for that build target to finish? Thanks in advance for any help!

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2016-05-02 10:19:30 -0500

gvdhoorn gravatar image

Does anybody know how I declare that the library ethercat will be build through ExternalProject_Add?

One option would be to use CMake's IMPORTED TARGET support for that. Let the external library build, install everything in the proper locations (ie: CATKIN_PACKAGE_LIB_DESTINATION etc) and then import the library. After importing, export it in your catkin_package(LIBRARIES ..) call. Dependent packages should now automatically pick it up.

Furthermore, how can I make other catkin packages wait for that build target to finish?

This will most likely start to work as soon as you import & export the library properly.

edit flag offensive delete link more

Comments

Thank you for your answer! It pointed me into the right direction.

Georg Bartels gravatar imageGeorg Bartels ( 2016-05-03 06:37:38 -0500 )edit
1

answered 2016-05-03 06:49:17 -0500

gvdhoorn's answer pointed me into the right direction. I provide my own solution for documentation.

Here is the CMakeLists of igh_eml which checks out and builds the external mercurial repository:

cmake_minimum_required(VERSION 2.8.3)
project(igh_eml)

find_package(catkin REQUIRED)

include(ExternalProject)
ExternalProject_Add(upstream_igh_eml
  HG_REPOSITORY http://hg.code.sf.net/p/etherlabmaster/code
  HG_TAG 792892ab4806
  TIMEOUT 30
  UPDATE_COMMAND touch <SOURCE_DIR>/config.h COMMAND mkdir -p <SOURCE_DIR>/include <SOURCE_DIR>/lib
  CONFIGURE_COMMAND touch <SOURCE_DIR>/ChangeLog COMMAND autoreconf -i <SOURCE_DIR> COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --disable-kernel --enable-hrtimer --enable-tool
  BUILD_IN_SOURCE 1
  INSTALL_DIR ${CATKIN_DEVEL_PREFIX}
)

add_library(ethercat SHARED IMPORTED)
set_target_properties(ethercat PROPERTIES IMPORTED_LOCATION ${CATKIN_DEVEL_PREFIX}/lib/libethercat.so)
add_dependencies(ethercat upstream_igh_eml)

catkin_package(
    LIBRARIES ethercat
)

Important notes: (1) catkin_package has to be called AFTER the build and import calls. (2) Exporting the include files at ${CATKIN_DEVEL_PREFIX}/include with catkin_package was not possible, that directory does not exist when catkin_package is interpreted.

The depending package omnidrive_ethercat has the following CMakeLIsts:

cmake_minimum_required(VERSION 2.8.3)
project(omni_ethercat)

find_package(catkin REQUIRED COMPONENTS ... igh_eml ...)

catkin_package(
  CATKIN_DEPENDS ... igh_eml ...)

include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(omni_ethercat src/omni_ethercat.cpp src/omnilib/omnilib.c src/omnilib/realtime.c)
target_link_libraries(omni_ethercat ${catkin_LIBRARIES})
add_dependencies(omni_ethercat upstream_igh_eml)

Important note: I have to directly depend on the build target upstream_igh_eml to halt compilation until all the h-files and so-files in igh_eml have been downloaded and built. The target ethercat was not enough. Also, I did not find out how to export this target through a CMake variable.

So, this a working solution, but there is room for improvement...

edit flag offensive delete link more

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-05-02 07:57:30 -0500

Seen: 1,179 times

Last updated: May 03 '16