• Diff for "rosbuild/CMakeLists"
Differences between revisions 126 and 128 (spanning 2 versions)
Revision 126 as of 2010-01-13 18:25:29
Size: 36041
Editor: BrianGerkey
Comment:
Revision 128 as of 2010-01-13 21:25:24
Size: 35663
Editor: VijayPradeep
Comment:
Deletions are marked like this. Additions are marked like this.
Line 471: Line 471:
<launch> <node pkg="map_server" type="map_server" args="$(find map_server)/test/testmap.bmp 0.1"/> <test test-name="map_server_test" pkg="map_server" type="rtest"/> </launch> <launch>
  <node pkg="map_server" type="map_server"
        args="$(find map_server)/test/testmap.bmp 0.1"/>
  <test test-name="map_server_test" pkg="map_server" type="rtest"/>
</launch>
Line 671: Line 675:
The release unit in ROS is a [[Stack|stack]]. `rosbuild` offers support for making source distributions of stacks ([[StackBuildFiles|more information]]). The release unit in ROS is a [[Stacks|stack]]. `rosbuild` offers support for making source distributions of stacks ([[StackBuildFiles|more information]]).

Writing a ROS CMakeLists.txt file

This page documents the CMake API provided by rosbuild.

Jump to examples, or detailed documentation.

We use CMake to build ROS packages. You need to install CMake on your system. Each package requires a file, called CMakeLists.txt to tell CMake how to build it. This file is analogous to a Makefile as used by make.

If you're unfamiliar with CMakeLists.txt, that's ok, because most ROS packages follow a very simple pattern that is described below. Of course, you can always use the full power of CMake, for which you may want to consult the CMake documentation.

NOTE: To support older platforms, we use only features that are available in CMake 2.4.6. Check the 2.4.6 docs to verify the availability of a feature you want to use.

Contents

  1. Writing a ROS CMakeLists.txt file
    1. Examples
      1. Building an executable
      2. Building a library
      3. Building a library and an executable that uses it
      4. Testing for system capabilities
        1. Checking for a function
        2. Checking for a header
        3. When something critical is missing
        4. Architecture-specific build flags
      5. Adding compile / link flags
        1. Compiling and linking with profiling
        2. Linking against a library in your package
        3. Linking against an external library
        4. Linking against libraries built by other ROS packages
        5. Removing default compile / link flags
        6. Using pkg-config to find an external dependency
      6. Sources in multiple directories
    2. Detailed documentation
      1. rosbuild.cmake
      2. rosbuild_init
      3. Build macros
        1. rosbuild_add_executable
        2. rosbuild_add_library
        3. rosbuild_add_swigpy_library
        4. rosbuild_add_compile_flags
        5. rosbuild_remove_compile_flags
        6. rosbuild_add_link_flags
        7. rosbuild_remove_link_flags
        8. rosbuild_add_boost_directories
        9. rosbuild_link_boost
        10. rosbuild_invoke_rospack
        11. rosbuild_find_ros_package
      4. Test macros
        1. rosbuild_add_gtest
        2. rosbuild_add_gtest_labeled
        3. rosbuild_add_gtest_future
        4. rosbuild_add_gtest_build_flags
        5. rosbuild_add_pyunit
        6. rosbuild_add_pyunit_labeled
        7. rosbuild_add_pyunit_future
        8. rosbuild_add_rostest
        9. rosbuild_add_rostest_labeled
        10. rosbuild_add_rostest_future
        11. rosbuild_add_rostest_graphical (DEPRECATED)
        12. rosbuild_declare_test
        13. rosbuild_count_cores
        14. rosbuild_check_for_display
        15. rosbuild_check_for_vm
      5. Message / service macros
        1. rosbuild_gensrv
        2. rosbuild_genmsg
        3. rosbuild_add_generated_msgs
        4. rosbuild_add_generated_srvs
      6. Downloading files during the build
        1. rosbuild_download_data
        2. rosbuild_download_test_data
      7. Making stack distributions
        1. rosbuild_make_distribution

Examples

Building an executable

A simple package that creates a single binary from one source file might look like this:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_executable(bumblebee_bridge bumblebee_bridge.cpp)

The first line tells CMake what version you need. The second line includes the rosbuild.cmake module, which provides some macros to simplify common ROS build operations.

The third and fourth lines invoke two of these macros. rosbuild_init() invokes rospack to retrieve the build flags for this package. This includes getting compile and link flags for all of bumblebee_bridge's dependencies.

The rosbuild_add_executable call says that you want to build an executable called bumblebee_bridge from the source file bumblebee_bridge.cpp (more source files could have listed there). This macro automatically brings in the compile and link flags exported by the dependencies that were declared in this package's manifest.xml. By default, the executable will go in the same directory as the source file(s). See rosbuild_init() below to change this default.

NOTE: the rosbuild_init() macro does NOT bring in the compile or link flags that are exported by the package presently being built. It ONLY brings in the flags exported by the present package's dependencies. The flags in the export section of your manifest.xml are for use by others, not by you. If you need some of your package's exported flags when building the package itself, use the appropriate CMake calls in your CMakeLists.txt, such as include_directories() and target_link_libraries(). See below for examples.

But see Linking against libraries built by other ROS packages for when not to use target_link_libraries().

Building a library

Many ROS packages build a library, like so:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_library(TF src/libTF.cpp src/Pose3DCache.cpp src/Pose3D.cpp)

This file compile a library, called libTF, from the three source files listed. By default, the library will go into the lib directory in your package. See rosbuild_init() below for changing this default.

Building a library and an executable that uses it

To extend the previous example, you may want to build a library, and then use it in building an executable, for example, a test program:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_library(TF src/libTF.cpp src/Pose3DCache.cpp src/Pose3D.cpp)
rosbuild_add_executable(testTF src/test/main.cpp)
target_link_libraries(testTF TF)

This case is similar to the previous one, with the addition of a call to rosbuild_add_executable(), and a call to target_link_libraries(). The latter call is needed to tell CMake that the executable testTF depends on the library libTF.

Testing for system capabilities

We strive for ROS to be cross-platform. In some cases, this requires different code for different systems. CMake provides a rich set of tools for testing capabilities, and provides a way for you to condition your code on the results of these tests. Below are some examples; for more information, see the CMake manual.

NOTE: always test for capabilities, not system type. E.g., test for the presence vs. absence of the function clock_gettime(), not whether your running on Windows vs. Linux.

Checking for a function

Let's say we want to use the function trunc(), but we know that it's not available everywhere (note that determining which functions are and are not available everywhere is not easy; best to learn over time). In our CMakeLists.txt, we add these lines:

include(CheckFunctionExists)
# Not everybody has trunc (e.g., Windows, embedded arm-linux)
CHECK_FUNCTION_EXISTS(trunc HAVE_TRUNC)
# Output test results to config.h
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)

The first line pulls in the standard CMake modules that provides function-checking. The second line invokes this check, putting the result in the CMake variable HAVE_TRUNC. Now, we want to get that value into our code. The third line reads in a template header called config.h.in and does replacements on it to produce a header config.h that can be #include'd in our C code.

The config.h.in looks like this:

#cmakedefine HAVE_TRUNC

If the system has trunc(), then the resulting config.h will look like this:

#define HAVE_TRUNC

If the system doesn't have trunc(), you'd get this:

/* #undef HAVE_TRUNC */

In either case, you can then do this in your code that needs to behave differently:

#include <config.h>
...
#ifdef HAVE_TRUNC
  <use trunc() as usual>
#else
  <work around the fact that trunc() isn't available>
#endif

Checking for a header

A slight variant on the previous example is to test for a header. The relevant CMakeLists.txt content:

include(CheckIncludeFiles)
# Not everybody has <ifaddrs.h> (e.g., embedded arm-linux)
CHECK_INCLUDE_FILES(ifaddrs.h HAVE_IFADDRS_H)
# Output test results to config.h
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)

The rest is the same as before.

When something critical is missing

It can happen that you must have some capability that isn't available everywhere. For example, a program that uses the Linux joystick interface needs the header <linux/joystick.h>. Without it, this program can't be compiled.

One strategy is to simply #include the header, and let the build break when it's not around. This is not very informative or nice to the user.

A better strategy is to test for the header and tell the user what the problem is. E.g.,:

# Must have <linux/joystick.h>
include(CheckIncludeFiles)
check_include_files(linux/joystick.h HAVE_LINUX_JOYSTICK_H)
if(NOT HAVE_LINUX_JOYSTICK_H)
  message(FATAL_ERROR "Can't proceed without <linux/joystick.h>")
endif(NOT HAVE_LINUX_JOYSTICK_H)

In this case, we don't create a config.h, because we're not going to use the result of the test in our code (the header is still unconditionally #included). The call to message() with the FATAL_ERROR option prints the message to the screen and stops the build.

Architecture-specific build flags

One exception to the above-mentioned prohibition against checking for system type is when you want to supply processor-specific build flags for the purpose of optimization. Use the builtin CMakeDetermineSystem module. E.g.:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
# Include the module
include(CMakeDetermineSystem)
rosbuild_init()
rosbuild_add_library(starfeature src/detector.cpp src/integral.cpp src/keypoint.cpp)
# Add processor-independent flags
rosbuild_add_compile_flags(starfeature -save-temps)
# Check for processor type and add appropriate flags
if(CMAKE_SYSTEM_PROCESSOR MATCHES "i686")
  rosbuild_add_compile_flags(starfeature -march=pentium3 -msse3)
endif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686")

In addition to CMAKE_SYSTEM_PROCESSOR, you might want to check CMAKE_SYSTEM_NAME and CMAKE_SYSTEM_VERSION.

It is sometimes the case that you need to add compile and/or link flags that are not reported by rosbuild_init(), including when linking against libraries that are built within the package. Adding library search paths, libraries to link against, and include search paths is easily handled via standard CMake commands, such as target_link_libraries(), include_directories(), and link_directories().

In general, these commands append their arguments to what came before, so you can use them to add to what rosbuild_init() already assembled.

To add or remove other link flags (e.g., warnings, optimizations), use rosbuild_add_compile_flags(), rosbuild_remove_compile_flags(), rosbuild_add_link_flags(), and rosbuild_remove_link_flags().

Compiling and linking with profiling

Example: we want to build map_server with profiling enabled, so that it will generate a gmon.out file that can be examined with gprof:

rosbuild_add_executable(map_server map_server.cc)
rosbuild_add_compile_flags(map_server "-pg")
rosbuild_add_link_flags(map_server "-pg")

The set_target_properties() command can be used to add any other flags you want.

Linking against a library in your package

Example: rosTF builds the library librosTF, then builds two executables that link against it:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_library(rosTF src/rosTF.cpp)
rosbuild_add_executable(testServer src/testServer.cc)
target_link_libraries(testServer rosTF)
rosbuild_add_executable(testClient src/testClient.cc)
target_link_libraries(testClient rosTF)

Linking against an external library

Example: wavefront_player needs to link against libwavefront_standalone:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_executable(wavefront_player wavefront_player.cc)
target_link_libraries(wavefront_player wavefront_standalone)

Read the next section for when not to use target_link_libraries().

Linking against libraries built by other ROS packages

Do not use target_link_libraries() to link against a library built by another ROS package. Libraries built by other ROS packages should export appropriate link flags that will be added to your package build automatically because of the package dependencies. If you find that your package doesn't build because you're missing a -lfoo argument for some libfoo that's built by another package, go fix the other package, by adding -lfoo to the export line in its manifest.xml.

Example, the default compile line include -fno-strict-aliasing. If you know what you're doing, you may want to remove this flag, to allow strict aliasing:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_executable(wavefront_player wavefront_player.cc)
rosbuild_remove_compile_flags(wavefront_player "-fno-strict-aliasing")

Using pkg-config to find an external dependency

Example: map_server needs gdk-pixbuf-2.0, which is not available as a ROS package, so we find it with pkg-config and add the appropriate flags into the build:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_executable(map_server map_server.cc)

include($ENV{ROS_ROOT}/core/rosbuild/FindPkgConfig.cmake)
pkg_check_modules(GDKPIXBUF REQUIRED gdk-pixbuf-2.0)
include_directories(${GDKPIXBUF_INCLUDE_DIRS})
link_directories(${GDKPIXBUF_LIBRARY_DIRS})
target_link_libraries(map_server ${GDKPIXBUF_LIBRARIES})

Note that we include FindPkgConfig.cmake from the ROS tree. This is because it was introduced into the CMake distribution after 2.4.6.

Sources in multiple directories

If you like, you can keep your package's source files in separate subdirectories within the package directory. In this situation, you should keep the basic ROS/CMake setup the same in the top-level CMakeLists.txt, with the addition of the add_subdirectory() command:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
set(EXECUTABLE_OUTPUT_PATH ${roscpp_tutorials_SOURCE_DIR}/bin)
add_subdirectory(src)

The src/CMakeLists.txt might in turn refer to other directories:

add_subdirectory(talker)
add_subdirectory(listener)
add_subdirectory(case_flip)
add_subdirectory(case_flip_client)
add_subdirectory(notify_connect)

When you reach a directory where you want to build something, you've inherited the build setup from above, so you can just declare what you want to build (src/talker/CMakeLists.txt):

rosbuild_add_executable(talker talker.cpp)

Detailed documentation

rosbuild.cmake

To use any of the ROS macros, you must first do this:

include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)

This line brings in the rosbuild.cmake file, which defines the macros described below.

rosbuild_init

rosbuild_init()

This macro should be called first. It does the following (assume ${pkg} is the name of the package, and ${dir} is the package directory):

  • Configure default output locations:
    • executables go in ${dir}
    • libraries go in ${dir}/lib
  • Add ${dir}/include to the search path for include files
  • Invoke rospack to get compile and link flags, storing the result in several variables (but you don't need to access them directly if you're using the rosbuild_add_executable and rosbuild_add_library macros):

    • -I compile flags go in ${pkg}_INCLUDE_DIRS
    • other compile flags go in ${pkg}_CFLAGS_OTHER
    • -L link flags go in ${pkg}_LIBRARY_DIRS
    • -l link flags go in ${pkg}_LIBRARIES
    • other link flags go in ${pkg}_LDFLAGS_OTHER

Note that you are free to override the default output locations after invoking rosbuild_init(). E.g., if you want your binaries in ${pkg}/bin, you might do this:

rosbuild_init()
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

To put your libraries somewhere strange:

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/libraries)

NOTE: the rosbuild_init() macro does NOT bring in the compile or link flags that are exported by the package presently being built. It ONLY brings in the flags exported by the present package's dependencies. The flags in the export section of your manifest.xml are for use by others, not by you. If you need some of your package's exported flags when building the package itself, use the appropriate CMake calls in your CMakeLists.txt, such as include_directories() and target_link_libraries().

But see Linking against libraries built by other ROS packages for when not to use target_link_libraries().

Build macros

rosbuild_add_executable

rosbuild_add_executable(exe src1 src2...)

This macro declares an executable that is to be built. It is a simple wrapper around the standard CMake command add_executable(), and takes exactly the same arguments. In addition to invoking add_executable(), this macro invokes set_target_properties() and target_link_libraries() to incorporate the compile and link flags found by the rosbuild_init() macro.

NOTE: Do not call your executable test. This target name is reserved for unit testing, and CMake will fail if you try it. If you really want your executable to be called test, you can do it like so:

rosbuild_add_executable(mytest src/test.cpp)
set_target_properties(mytest PROPERTIES OUTPUT_NAME test)

But if you're building test programs, you should do it with rosbuild_add_gtest(); see below.

If you're building an executable that shouldn't be built in the make all step (e.g., if you intend to use rosbuild_add_gtest_build_flags()), then use CMake's EXCLUDE_FROM_ALL option, e.g.:

rosbuild_add_executable(mytest EXCLUDE_FROM_ALL src/test.cpp)
rosbuild_add_gtest_build_flags(mytest)

rosbuild_add_library

rosbuild_add_library(lib src1 src2...)

This macro declares a library that is to be built. It is a simple wrapper around the standard CMake command add_library(), and takes exactly the same arguments. In addition to invoking add_library(), this macro invokes set_target_properties() to incorporate the compile flags found by the rosbuild_init() macro.

Example usage:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
rosbuild_add_library(XmlRpc src/XmlRpcClient.cpp
                   src/XmlRpcDispatch.cpp
                   src/XmlRpcServer.cpp
                   src/XmlRpcServerConnection.cpp
                   src/XmlRpcServerMethod.cpp
                   src/XmlRpcSocket.cpp
                   src/XmlRpcSource.cpp
                   src/XmlRpcUtil.cpp
                   src/XmlRpcValue.cpp)

NOTE: Do not call your library test. This target name is reserved for unit testing, and CMake will fail if you try it.

rosbuild_add_swigpy_library

New in 0.11

rosbuild_add_swigpy_library(target lib src1 src2...)

This macro is a variation on rosbuild_add_library() that should be used when building a SWIG-generated library that will be imported by Python. The first argument is a unique target name, which you can pass to things like target_link_libraries(). The rest of the arguments are the same as you would normally pass to rosbuild_add_library().

This macro will generate a library called _<lib>.<ext>, where <lib> is what you passed in, and <ext> is the appropriate extension for a shared library. On OS X, the extension is forced to .so, to allow module imports to work with the MacPorts version of Python.

Example usage:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
find_package(PythonLibs REQUIRED)
rosbuild_add_swigpy_library(python_foo foo foo_swig_generated.cpp bar.cpp)
target_link_libraries(python_foo ${PYTHON_LIBRARIES})

This example will produce a library named _foo.so on most platforms.

NOTE: Do not call your target test. This target name is reserved for unit testing, and CMake will fail if you try it.

rosbuild_add_compile_flags

rosbuild_add_compile_flags(target flags)

This macro adds compile flags for the given target. You can use it to add things like warning or optimization settings, but don't use it to add library/include search paths, -D definitions, or libraries to link against. Use CMake builtin commands (link_directories(), include_directories(), add_definitions(), target_link_libraries()) for those cases.

But see Linking against libraries built by other ROS packages for when not to use target_link_libraries().

rosbuild_remove_compile_flags

rosbuild_remove_compile_flags(target flags)

This macro removes compile flags for the given target.

rosbuild_add_link_flags(target flags)

This macro adds link flags for the given target. You can use it to add things like profiling settings, but don't use it to add library/include search paths, -D definitions, or libraries to link against. Use CMake builtin commands (link_directories() include_directories(), add_definitions(), target_link_libraries()) for those cases.

But see Linking against libraries built by other ROS packages for when not to use target_link_libraries().

rosbuild_remove_link_flags(target flags)

This macro removes link flags for the given target.

rosbuild_add_boost_directories

rosbuild_add_boost_directories()

This macro adds the boost include/library directories to your search paths.

rosbuild_link_boost(target lib1 lib2 lib3 ...)

This macro adds the boost link flags to a target, given some boost libraries you want to link against. Example:

rosbuild_link_boost(my_exe thread regex)

rosbuild_invoke_rospack

rosbuild_invoke_rospack(pkg prefix varname rospack_args)

This macro invokes rospack. Specifically, it invokes:

rospack ${rospack_args) ${pkg}

It stores the result in the variable ${prefix}_${varname}. Failure to invoke rospack is fatal.

rosbuild_find_ros_package

rosbuild_find_ros_package(pkg)

This macro searches for the given ROS package. If the package is found, then the variable ${pkg}_PACKAGE_PATH is set to the absolute path to the package. If the package is not found, the variable is not set.

Test macros

rosbuild_add_gtest

rosbuild_add_gtest(testexe src1 src2 ...)

This macro declares a Google Test (gtest) executable that is to be built. The arguments are the same as rosbuild_add_executable (in fact this macro calls through to rosbuild_add_executable). The named executable is built from the sources, and added as a dependency to the test target. This macro invokes rosbuild_add_gtest_build_flags(), which adds the gtest build flags to the named executable. To build the executable, use make tests.

When make test is run, each gtest executable is run like so:

testexe --gtest_output=xml:${rosbuild_test_results_dir}/${PROJECT_NAME}/${_testname}.xml

The current working directory is the top of the package's source tree.

Test output is printed to the console, and also stored in XML format in $ROS_ROOT/test/test_results/${project}, where ${project} is the name of the ROS package.

Multiple tests may be declared.

NOTE: Do not call your test test. This target name is reserved for unit testing, and CMake will fail if you try it.

rosbuild_add_gtest_labeled

Since 0.9.

rosbuild_add_gtest(label testexe src1 src2 ...)

This macro is the same as rosbuild_add_gtest(), except that it only declares the test if EITHER:

  • the environment variable ROS_BUILD_TEST_LABEL is unset; OR

  • the label argument is equal to the environment variable ROS_BUILD_TEST_LABEL.

Use this macro to declare tests that should not run in certain situations. Most commonly used with a continuous integration system.

rosbuild_add_gtest_future

rosbuild_add_gtest_future(testexe src1 src2 ...)

This macro is the same as rosbuild_add_gtest(), except that the resulting test will be only be run during make test-future. Use this macro to declare tests that fail now, but should pass in the future, after an existing bug is fixed or missing feature implemented.

We segregate future tests from current tests so that the automated build and test system can accurately report health of the system, including giving meaningful email notification on test failure.

rosbuild_add_gtest_build_flags

rosbuild_add_gtest_build_flags(testexe)

This macro adds the build flags necessary to compile and link an executable against gtest. Use this macro when you want to build a gtest exectuable, but not declare it to be a test on its own. This commonly occurs when you're using rostest and your test executable uses gtest. In this case you want the test executable to be run via rostest, not on its own.

This macro also invokes rosbuild_declare_test(), which adds a dependency from the tests target on the executable. To build the executable, use make tests.

E.g., here we build an executable called rtest that uses gtest, and declare a rostest that uses it:

rosbuild_add_executable(rtest test/rtest.cpp test/test_constants.cpp)
rosbuild_add_gtest_build_flags(rtest)
rosbuild_add_rostest(test/rtest.xml)

The accompanying rostest XML file might look like this:

<launch>
  <node pkg="map_server" type="map_server"
        args="$(find map_server)/test/testmap.bmp 0.1"/>
  <test test-name="map_server_test" pkg="map_server" type="rtest"/>
</launch> 

rosbuild_add_pyunit

rosbuild_add_pyunit(file)

This macro declares a Python unittest executable that is to be run. Make sure you consult the ROS unittest documentation as there are some additional items your unittest script needs to call.

When make test is run, each Python unit test is run like so:

python file --gtest_output=xml:${rosbuild_test_results_dir}/${PROJECT_NAME}/${_testname}.xml

The current working directory is the top of the package's source tree.

rosbuild_add_pyunit_labeled

Since 0.9.

rosbuild_add_pyunit(label file)

This macro is the same as rosbuild_add_pyunit(), except that it only declares the test if EITHER:

  • the environment variable ROS_BUILD_TEST_LABEL is unset; OR

  • the label argument is equal to the environment variable ROS_BUILD_TEST_LABEL.

Use this macro to declare tests that should not run in certain situations. Most commonly used with a continuous integration system.

rosbuild_add_pyunit_future

rosbuild_add_pyunit_future(file)

This macro is the same as rosbuild_add_pyunit(), except that the resulting test will be only be run during make test-future. Use this macro to declare tests that fail now, but should pass in the future, after an existing bug is fixed or missing feature implemented.

We segregate future tests from current tests so that the automated build and test system can accurately report health of the system, including giving meaningful email notification on test failure.

rosbuild_add_rostest

rosbuild_add_rostest(xmlfile)

This macro declares a rostest test that is to be run when testing the package. When make test is run on the package, the given xmlfile will be passed to rostest. Output goes in $ROS_ROOT/test/test_results/${project}, where ${project} is the name of the ROS package.

rosbuild_add_rostest_labeled

Since 0.9.

rosbuild_add_rostest(label file)

This macro is the same as rosbuild_add_rostest(), except that it only declares the test if EITHER:

  • the environment variable ROS_BUILD_TEST_LABEL is unset; OR

  • the label argument is equal to the environment variable ROS_BUILD_TEST_LABEL.

Use this macro to declare tests that should not run in certain situations. Most commonly used with a continuous integration system.

rosbuild_add_rostest_future

rosbuild_add_rostest_future(xmlfile)

This macro is the same as rosbuild_add_rostest(), except that the resulting test will be only be run during make test-future. Use this macro to declare tests that fail now, but should pass in the future, after an existing bug is fixed or missing feature implemented.

We segregate future tests from current tests so that the automated build and test system can accurately report health of the system, including giving meaningful email notification on test failure.

rosbuild_add_rostest_graphical (DEPRECATED)

rosbuild_add_rostest_graphical(xmlfile)

DEPRECATED : use rosbuild_check_for_display() to check whether a display is available instead.

This macro is the same as rosbuild_add_rostest(), except that the resulting test will be prefixed with xvfb-run when run in the automated build and test system. Use this macro to designate tests that require a graphical display, so that they can be run appropriately in a headless environment

Note that xvfb-run is only called if a particular environment variable is set. If you want to test the headless behavior of your graphical test, install xvfb (e.g., sudo apt-get install xvfb), set the ROS_BUILD_XVFB environment variable to xvfb-fun, then make test.

rosbuild_declare_test

rosbuild_declare_test(exe)

This macro declares that an executable is a test harness, which adds it to the make tests build. Use this macro to declare that an executable is only used in testing. This macro is automatically invoked for any executable that is declared via rosbuild_add_gtest(), rosbuild_add_gtest_future(), or rosbuild_add_gtest_build_flags(). So you only need to use this macro for an executable that is used in testing, but isn't a test itself; e.g., a node that is used in setting up a rostest.

This macro does not exclude building the executable from the make all build. To do this, you must supply the EXCLUDE_FROM_ALL option when calling rosbuild_add_executable().

rosbuild_count_cores

Since 0.10.

rosbuild_count_cores(num)

This macro calls out to Python to determine the number of physical cores on your machine, and writes this number into num. It's intended for use in gating tests that require a lot of processing. E.g., if you want to run a test only when you have at least 4 cores:

rosbuild_count_cores(cores)
if(cores GREATER 4 OR cores EQUAL 4)
  rosbuild_add_rostest(my_crazy_test.xml)
endif(cores GREATER 4 OR cores EQUAL 4)

rosbuild_check_for_display

Since 0.10.

rosbuild_check_for_display(var)

This macro checks for the presence of an X display (currently by looking at the exit status from calling xdpyinfo). It sets var to 1 if there is a display, and 0 otherwise. It's intended for us in gating tests that require an X display, e.g.:

rosbuild_check_for_display(disp)
if(disp)
  rosbuild_add_rostest(my_graphical_test.xml)
endif(disp)

rosbuild_check_for_vm

Since 0.9.

rosbuild_check_for_vm(result)

This macro determines whether the build is happening on a virtual machine. Currently, it just looks for "/proc/xen". The intended use is gating tests that have strict timing requirements. The assumption is that a non-VM will have low load.

E.g., to only run a test on a non-VM:

rosbuild_check_for_vm(vm)
if(NOT vm)
  rosbuild_add_rostest(my_strict_timing_test.xml)
endif(NOT vm)

Message / service macros

rosbuild_gensrv

rosbuild_gensrv()

This macro processes service specifications that defined locally in a package. In particular, it runs the gensrv script on all *.srv files found in the srv subdirectory of the package.

Example usage:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
gensrv()
# the service provider
rosbuild_add_executable(deadreckon deadreckon.cpp)
# a dumb test client
rosbuild_add_executable(test_deadreckon_service test_deadreckon_service.cpp)

rosbuild_genmsg

rosbuild_genmsg()

This macro processes message specifications that defined locally in a package. In particular, it runs the genmsg script on all *.msg files found in the msg subdirectory of the package.

rosbuild_add_generated_msgs

rosbuild_add_generated_msgs(AutoGen1.msg AutoGen2.msg)

This macro sets up for auto-generation of one or more messages. It creates an expectation that the message files passed as arguments will be created during the build. This macro may be called more than once. This macro must be called before rosbuild_init().

rosbuild_add_generated_srvs

rosbuild_add_generated_srvs(AutoGen1.srv AutoGen2.srv)

This macro sets up for auto-generation of one or more services. It creates an expectation that the service files passed as arguments will be created during the build. This macro may be called more than once. This macro must be called before rosbuild_init().

Downloading files during the build

It is sometimes necessary to download files during the build. This is usually done to avoid checking large, often binary, files into Subversion. Some macros are provided to help in these cases

rosbuild_download_data

(New in 0.8; 3-argument form new in 0.9)

rosbuild_download_data(url filename md5sum)

DEPRECATED 2-argument form, without an md5sum:

rosbuild_download_data(url filename)

This macro sets up a target for downloading a file from url and saving it locally with the name filename, and checking the resulting file's md5 hash against md5sum. The target will fire on the all target, which means that it will happen during the main build of the package. There are no guarantees on ordering of steps within the all target (e.g., the download is not guaranteed to happen before a particular compilation step). The url should be fully-qualified (e.g., don't leave out the domain name), and the filename should be relative to your package directory.

The md5 hash is checked on every build; if it doesn't match, filename is deleted, and one attempt is made to re-download the file; if it still doesn't match, the build is aborted with an error.

Note for Willow Garage people: You should put your data at ipr:/var/www/pr.willowgarage.com/html/data, in a directory with the same name as your package.

rosbuild_download_test_data

(3-argument form new in 0.9)

rosbuild_download_test_data(url filename md5sum)

DEPRECATED 2-argument form, without an md5sum:

rosbuild_download_test_data(url filename)

This macro is the same as rosbuild_download_data(), except that it will fire on the tests target, which happens during the build of test programs, prior to running any tests.

Note for Willow Garage people: You should put your data at ipr:/var/www/pr.willowgarage.com/html/data, in a directory with the same name as your package.

Making stack distributions

The release unit in ROS is a stack. rosbuild offers support for making source distributions of stacks (more information).

rosbuild_make_distribution

rosbuild_make_distribution(version)

This macro performs the set up necessary to produce a source tarball of the stack, at the given version.

Wiki: rosbuild/CMakeLists (last edited 2013-06-17 22:29:35 by DirkThomas)