ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
2

Where should generated header files be generated to? How can I then export them with catkin?

asked 2014-01-27 23:26:58 -0600

loliveira gravatar image

I have the following CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(datatypes)

find_package(catkin REQUIRED)
catkin_package(
->INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION}
#  LIBRARIES rtdb_config
#  CATKIN_DEPENDS other_catkin_pkg
#  DEPENDS system_lib
)

file(MAKE_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION})
FILE(GLOB DATATYPE_RAW ${PROJECT_SOURCE_DIR}/datatypes/*)
add_custom_target(${PROJECT_NAME}
    ALL
    COMMAND generate_some_header_files_to ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}
    SOURCES ${DATATYPE_RAW}
)

Where the custom command generates header files to be used by other packages in the dir ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}. (Not sure this dir should be used!!)

The problem seems to be that since this directory was still not created it fails to be exported by catkin_package:

catkin_package() include dir '/home/.../devel/include' is neither an absolute directory nor exists relative to '/home/.../src/rtdb/src/datatypes'

Now the question: Where should generated header files be generated to? How can I then export them with catkin?

Thanks in advance.

Luis

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
2

answered 2014-01-28 05:09:51 -0600

Dirk Thomas gravatar image

Your approach described in the question was almost right. As the CMake error indicates the path you specified as catkin_package(INCLUDE_DIRS ...) must exist when the function is being invoked. Therefore you have to move the MAKE_DIRECTORY line above the function. But since the function is also responsible to define the catkin DESTINATION variables you need to get them explicitly before using catkin_destinations().

Further more you need to export your target which is responsible to generate the headers in order for downstream packages be able to cleanly depend on them being generated before. Usually you should pass EXPORTED_TARGETS ${PROJECT_NAME}_generate_headers to catkin (but due to a bug until now you have to set the variable ${PROJECT_NAME}_EXPORTED_TARGETS instead).

Last but not least you need to install the header files.

The complete example would then look like this:

cmake_minimum_required(VERSION 2.8.3)
project(datatypes)

find_package(catkin REQUIRED)

catkin_destinations()
file(MAKE_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION})
file(GLOB DATATYPE_RAW ${PROJECT_SOURCE_DIR}/datatypes/*)

# using a better target name for the custom target
add_custom_target(${PROJECT_NAME}_generate_headers
  ALL
  COMMAND generate_some_header_files_to ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  SOURCES ${DATATYPE_RAW}
)
set(${PROJECT_NAME}_EXPORTED_TARGETS ${PROJECT_NAME}_generate_headers)

catkin_package(
  INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_INCLUDE_DESTINATION}
  # instead of set(${PROJECT_NAME}_EXPORTED_TARGETS ...)
  # but will only work as of catkin 0.5.81
  # EXPORTED_TARGETS ${PROJECT_NAME}_generate_headers
)

# no need for patterns / excludes since the path should only contain the generated headers
# by using the directory name with a slash at the end
# the directory name and destination become more natural
# (both mentioning CATKIN_PACKAGE_INCLUDE_DESTINATION)
install(
  DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
)
edit flag offensive delete link more

Comments

Perfect... that seems to be exactly what I'm looking for... unfortunately the good config breaks the compilation :) (my fault this time) ;) Only using catkin 0.5.79 so I'll use the first option.

loliveira gravatar image loliveira  ( 2014-01-28 06:25:21 -0600 )edit
1

answered 2014-01-28 04:25:59 -0600

joq gravatar image

The recommended solution is to mention your include/ subdirectory to catkin_package():

catkin_package(INCLUDE_DIRS include)

Then, follow standard ROS practice and place all external header files under include/your_package/, and install them this way:

install(DIRECTORY include/${PROJECT_NAME}/
        DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
edit flag offensive delete link more

Comments

This does not address the question regarding generated headers.

Dirk Thomas gravatar image Dirk Thomas  ( 2014-01-28 04:36:27 -0600 )edit

So your suggestion is to place the generated header files in the src directory? I've thought about that but usualy compiletime generated files go to the build directory. The install step works fine, I install to *sorry next comment*

loliveira gravatar image loliveira  ( 2014-01-28 04:49:26 -0600 )edit

install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_INCLUDE_DESTINATION} DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION} FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" PATTERN ".svn" EXCLUDE )

loliveira gravatar image loliveira  ( 2014-01-28 04:49:29 -0600 )edit

As Dirk said, I overlooked the "generated" part of your question and answered only the "where to install" part. Sorry to have wasted everyone's time.

joq gravatar image joq  ( 2014-01-28 06:17:59 -0600 )edit

Don't worry, all help is welcome even if it overlooks some part of the question ;)

loliveira gravatar image loliveira  ( 2014-01-28 06:36:10 -0600 )edit
0

answered 2014-01-28 01:09:12 -0600

Wolf gravatar image

Just generate your headers to

<catkin_ws>/devel/include/<package_name>/

and forget about catkin_package( INCLUDE_DIRS ...

Message headers are also generated there, so each package sees files in this include folder. By adding the package name in your include like

#include "package_name/header_file.h"

you have the header files properly separated by packages in this folder and your depending package will find them when being compiled.

This worked for me. I have not yet used any install options, though. If you have to install your package, I am not sure whether this would work. (Good luck in this case and tell me what you have dome;) )

One more hint: The headers have to be generated before a file that includes them can be compiled. You can assure this using the add_dependency() command of cmake where you add your custom target as depenceny of e. g. an exec target that is compiled of files which include your generated header.

edit flag offensive delete link more

Comments

Thanks for the answer. I put it on that folder for that reason. However, if devel is not sourced yet (because it doesn't exist) the header will not be seen by the packages. You have to: catkin_make; source devel/setup.bash; catkin_make It works, but it is not elegant ;)

loliveira gravatar image loliveira  ( 2014-01-28 01:18:00 -0600 )edit

Well, of course, it's my quick hack, better solutions appreciated;)

Wolf gravatar image Wolf  ( 2014-01-28 03:31:10 -0600 )edit

Ignoring `catkin_package(INCLUDE_DIRS` will not work when creating a Debian package and/or other packages want to depend on this package.

Dirk Thomas gravatar image Dirk Thomas  ( 2014-01-28 04:37:07 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2014-01-27 23:26:58 -0600

Seen: 3,395 times

Last updated: Jan 28 '14