Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time

Using OpenDDS in a CMake Project

OpenDDS can be used with CMake-Based projects by using the OpenDDS CMake Config package (located here). This package bridges the gap between the MPC build system used by OpenDDS and CMake-Based projects by exposing OpenDDS CMake targets (see comments here), and by providing the OPENDDS_TARGET_SOURCES macro which simplifies IDL compilation.

Table of Contents:

Requirements

In order to use the Config module, CMake version 3.3.2 or greater is required. However, to run the Messenger examples, version 3.8.2 or greater is required (due to some dependencies which simplify the custom file-copy targets).

CMake Messenger Examples

Developer's Guide Messenger Example

For a simple quick-start example of an CMakeLists.txt using OpenDDS see the Developer's Guide Messenger example.

Advanced Examples

Included with OpenDDS are two example CMake-Based Messenger applications which exist to showcase two different strategies for adding IDL files:

  1. Messenger with direct IDL inclusion
  2. Messenger with auxiliary IDL library

The first scenario adds the IDL file directly into each executable so the generated headers/sources are added to the publisher/subscriber targets independently.

The second scenario creates a library which has the IDL-generated headers/sources) added to it. The publisher and subscriber executables then link against the library to use the IDL-generated code.

Configure-Generated Variables

The configure script ($DDS_ROOT/configure) is responsible for generating the config.cmake file (placed in $DDS_ROOT/cmake), which has various configuration options. These options provide the OpenDDS CMake package with the required context it needs to integrate with the OpenDDS code generators and libraries.

Note: With an installed version of OpenDDS (generated using make install), config.cmake will be placed in /path/to/install-prefix-dir/lib/cmake/OpenDDS. This location allows CMake to locate the file using CMAKE_PREFIX_PATH.

Not all of the variables in this file are used. They are procedurally generated from variables in the configure script. However, to get a better sense of how they are being used take a look at the options.cmake file. This is where various CMake C/C++ compile-time defines and IDL-Compiler flags are set/unset depending upon which variables are enabled/disabled.

If you are using OpenDDS libraries that were built without the help of the configure script, the config.cmake file needs to be created manually. See Manually Creating config.cmake in the advanced section below.

Using the OpenDDS CMake Package

The OpenDDS CMake package is based upon the standard CMake packaging guidelines, so the typical generate/compile steps only require setting the CMAKE_PREFIX_PATH and calling find_package(OpenDDS) within a CMakeLists.txt file. In addition, the following cache variables/options can be used to control the behavior of the OpenDDS CMake package.

Cache Variables/Options Understood by OpenDDS

Cache Variable Description Default
OPENDDS_CMAKE_VERBOSE Print detailed status information at CMake-Generation time OFF
OPENDDS_DEFAULT_NESTED Topic types must be declared explicitly. ON
OPENDDS_FILENAME_ONLY_INCLUDES No directory info in generated #includes. OFF

Libraries

The following libraries are some of what can be defined by the package:

  • OpenDDS::Dcps
    • Core OpenDDS Library
  • OpenDDS::Rtps
    • RTPS Discovery
  • OpenDDS::InfoRepoDiscovery
    • InfoRepo Discovery
  • OpenDDS::Rtps_Udp
    • RTPS Transport
  • OpenDDS::Multicast
    • Multicast Transport
  • OpenDDS::Shmem
    • Shared Memory Transport
  • OpenDDS::Tcp
    • TCP Transport
  • OpenDDS::Udp
    • UDP Transport
  • OpenDDS::Security
    • DDS Security Implementation, if Available
  • OpenDDS::OpenDDS
    • A Combination of all the Previous Libraries

See OpenDDSConfig.cmake for all the libraries and more details on them.

Example Using OpenDDS Source Tree

When using the CMake Package, the OpenDDS build environment variables (from setenv.sh or setenv.cmd) do not need to be set. CMake's variable CMAKE_PREFIX_PATH needs to include the top directory of OpenDDS's source tree, that is the directory known as DDS_ROOT when OpenDDS was compiled.

To generate/compile the Messenger with direct IDL inclusion within the OpenDDS source tree:

Unix

cd tests/cmake/Messenger/Messenger_1
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=<location of OpenDDS source tree> ..
cmake --build .

Windows

The following assumes Visual Studio 2017 using 64-bit architecture (adjust the CMake -G parameter if using something different).

cd tests\cmake\Messenger\Messenger_1
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=<location of OpenDDS source tree> -G "Visual Studio 15 2017 Win64" ..
cmake --build .

Example Using Installed OpenDDS (Unix only)

The --prefix switch can be passed to configure to enable the install target, which will install OpenDDS (including the OpenDDS CMake Config module) into the specified directory. See the INSTALL document for details.

Note: Be sure to pass an absolute path to --prefix.

DDS_WORKSPACE=$(pwd)
cd OpenDDS-src
./configure --prefix=$DDS_WORKSPACE/opendds-install
make
make install
cd tests/Messenger/Messenger_1
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=$DDS_WORKSPACE/opendds-install ..
cmake --build .

Note: While this will build the Messenger_1 example, the run_test.pl script will not work due to missing Perl dependencies.

Adding IDL Sources with OPENDDS_TARGET_SOURCES

Aside from importing the various OpenDDS targets, the OpenDDS Config Package provides an easy way to add IDL sources to CMake targets. This is achieved by the OPENDDS_TARGET_SOURCES macro, which behaves similarly to the built-in target_sources command except for the following:

  • Items are IDL sources instead of C/C++ sources.
  • The scope-qualifier (PUBLIC, PRIVATE, INTERFACE) is not required. When it is omitted, PRIVATE is used by default.
  • Command-line options can be supplied to the TAO/OpenDDS IDL compilers using TAO_IDL_OPTIONS and/or OPENDDS_IDL_OPTIONS (if the default behavior is not suitable).
    • Add OPENDDS_IDL_OPTIONS -Lc++11 to use the C++11 IDL Mapping.
  • A command-line option is available to force creation of typecodes by using SUPPRESS_ANYS OFF. This value will overrule the one received from config.cmake OPENDDS_SUPPRESS_ANYS.

When IDL sources are supplied, custom commands are generated which will be invoked to compile the IDL sources into their component cpp/h files.

NOTE: C/C++ items can also be accepted and added to the target, but passing non-IDL sources was deprecated in OpenDDS 3.15.

If the passed-in target is a shared library, a custom command will also be added to generate the required IDL export header file (target_export.h), which is necessary to properly export symbols for the IDL-Generated sources.

Usage Summary

OPENDDS_TARGET_SOURCES(target
  [items...]
  [<INTERFACE|PUBLIC|PRIVATE> items...]
  [TAO_IDL_OPTIONS options...]
  [OPENDDS_IDL_OPTIONS options...]
  [SUPPRESS_ANYS ON|OFF]
)

Example

Based on the Messenger with direct IDL inclusion, here is a snippet showing how IDL files can be added directly to executable targets using the OPENDDS_TARGET_SOURCES macro:

add_executable(publisher
  "publisher.cpp"
  "Writer.cpp"
)
OPENDDS_TARGET_SOURCES(publisher "Messenger.idl")
target_link_libraries(publisher OpenDDS::OpenDDS)

This is fine for small IDL files and builds with a few targets that need the code generated from IDL, but it can be improved upon.

Another snippet, based upon Messenger with auxiliary IDL library, showcases how an auxiliary IDL library can be created for inclusion by other executables:

add_library(messenger)
OPENDDS_TARGET_SOURCES(messenger "Messenger.idl")
target_link_libraries(messenger OpenDDS::Dcps)

add_executable(publisher
  "publisher.cpp"
  "Writer.cpp"
)
target_link_libraries(publisher OpenDDS::OpenDDS)

Here the generated code from the IDL is only compiled once. This is especially advantageous if you have a significant amount of IDL and/or have many targets that require the IDL. Additionally if the library is a shared library, executables can share that file and this reduces the size of the executable files.

Note: This may issue a warning in earlier versions of CMake due to the messenger library not having any sources added with it in the call to add_library.

Advanced Usage

Manually Creating config.cmake

In order to work with config.cmake it is important to understand the purpose of its contained variables. Below is a list of the important variables with some information on their purpose.

Optional OpenDDS Features

When OpenDDS is built using the MPC build-system and optional features are specified, various C/C++; tao_idl; and opendds_idl compiler macros are set on dependent libraries or executables. These defines are set by MPC using the dcps_optional_features.mpb file.

CMake-Based targets must also inherit the defined macros, so the functionality in dcps_optional_features.mpb is simulated using options.cmake and its associated config.cmake. As such, if features are enabled/disabled when compiling OpenDDS then it is paramount that the MPC features are also matched within config.cmake prior to compilation.

This table outlines the feature-related variables and their expected default values (generated when the configure script is run without arguments). If any feature is explicitly enabled/disabled in the OpenDDS build then the corresponding CMake variable below should be set to either ON or OFF depending on the desired state.

CMake Variable Notes (from configure script output) Default
OPENDDS_BUILT_IN_TOPICS Built-in Topics ON
OPENDDS_CONTENT_FILTERED_TOPIC ContentFilteredTopic (CS Profile) ON
OPENDDS_CONTENT_SUBSCRIPTION Content-Subscription Profile. When this is set to OFF then CONTENT_FILTERED_TOPIC, MULTI_TOPIC, and QUERY_CONDITION will also be set to OFF. See the OpenDDS Dev Guide ch. 5 for info. ON
OPENDDS_MULTI_TOPIC MultiTopic (CS Profile) ON
OPENDDS_OBJECT_MODEL_PROFILE Object Model Profile ON
OPENDDS_OWNERSHIP_KIND_EXCLUSIVE Exclusive Ownership (Ownership Profile) ON
OPENDDS_OWNERSHIP_PROFILE Ownership Profile. When this is set to OFF then OWNERSHIP_KIND_EXCLUSIVE will also be set to OFF. ON
OPENDDS_PERSISTENCE_PROFILE Persistence Profile ON
OPENDDS_QUERY_CONDITION QueryCondition (CS Profile) ON
OPENDDS_SECURITY DDS Security plugin OFF
OPENDDS_SAFETY_PROFILE Safety Profile OFF

Build-Related Options

The following values impact the build in one way or another.

CMake Variable Notes Default
OPENDDS_ACE Location of ACE root dir. N/A
OPENDDS_TAO Location of TAO root dir. N/A
OPENDDS_NO_DEBUG Sets NDEBUG flags on ACE for non-debug builds (Unix only) OFF
OPENDDS_INLINE ACE's inline build flag See below
OPENDDS_STATIC Use static libraries OFF
OPENDDS_XERCES3 Adds dependencies to targets; required when OPENDDS_SECURITY is ON OFF
OPENDDS_CXX11 ACE/TAO and OpenDDS were built with C++11 or later. N/A
OPENDDS_WCHAR ACE/TAO and OpenDDS were built to prefer wide characters. OFF
OPENDDS_VERSIONED_NAMEPSACE ACE/TAO and OpenDDS have versioned namespaces. OFF
OPENDDS_FEATURES List of additional features which impact the build. N/A

OPENDDS_INLINE should be explicitly set to ON or OFF (based on the ACE platform_macros.GNU variable inline) in config.cmake unless you will only be using a CMake Microsoft Visual Studio Generator.

OPENDDS_DEFAULT_NESTED

When parsing IDL, OpenDDS will determine if it should be prepared for a struct or union to be used in a topic if its "nested" value is false. See the OpenDDS Developer's Guide for more information.

OPENDDS_DEFAULT_NESTED sets the global default for what the "nested" property is. If this value is ON, then topic types for a given project must be declared using annotations. If it's OFF, then every valid type is assumed to be needed for use as a topic type by default, which might add code to the IDL type support libraries that will never be used.

This default can also be controlled on a finer level when calling OPENDDS_TARGET_SOURCES by passing --default-nested or --no-default-nested to OPENDDS_IDL_OPTIONS. For example:

add_library(messenger)
OPENDDS_TARGET_SOURCES(messenger
  Messenger.idl
  OPENDDS_IDL_OPTIONS --no-default-nested
)

OPENDDS_FILENAME_ONLY_INCLUDES

This setting tells OpenDDS's IDL compiler to strip path information from #include lines in generated files. Turning the option on can make it easier to specify build rules for IDL files that include other IDL files.

OPENDDS_LANGUAGE_MAPPINGS

After OPENDDS_TARGET_SOURCES is used on a target, it will have the OPENDDS_LANGUAGE_MAPPINGS target property set. This signifies the IDL language mappings available in the IDL bindings generated into the target based on what is passed to OPENDDS_IDL_OPTIONS. It will be a list that can contain one or more of the following:

  • "C++03"
    • Default IDL-to-C++ mapping generated by default.
  • "C++11"
    • IDL-to-C++11 mapping available when passing -Lc++11.
  • "FACE"
    • Will appear if -Lface is passed.
  • "Java"
    • Currently unsupported in the CMake module, but this will appear in the list if -Wb,java is passed.

If the CMake version is at least 3.12, then this property will exported with the target.