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
which simplifies IDL compilation.
Table of Contents:
- CMake Messenger Examples
- Configure-Generated Variables
- Using the OpenDDS CMake Package
- Adding IDL Sources with
- Advanced Usage
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
Included with OpenDDS are two example CMake-Based Messenger applications which exist to showcase two different strategies for adding IDL files:
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.
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
config.cmake will be placed in
/path/to/install-prefix-dir/lib/cmake/OpenDDS. This location allows CMake to
locate the file using
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
so the typical generate/compile steps only require setting the
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
||Print detailed status information at CMake-Generation time||
||Topic types must be declared explicitly.||
||No directory info in generated #includes.||
The following libraries are some of what can be defined by the package:
- Core OpenDDS Library
- RTPS Discovery
- InfoRepo Discovery
- RTPS Transport
- Multicast Transport
- Shared Memory Transport
- TCP Transport
- UDP Transport
- DDS Security Implementation, if Available
- 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.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:
cd tests/cmake/Messenger/Messenger_1 mkdir build cd build cmake -DCMAKE_PREFIX_PATH=<location of OpenDDS source tree> .. cmake --build .
The following assumes Visual Studio 2017 using 64-bit architecture (adjust the
-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)
--prefix switch can be passed to configure to enable the
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
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
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
OPENDDS_TARGET_SOURCES macro, which behaves similarly to the
target_sources command except for the following:
- Items are IDL sources instead of C/C++ sources.
- The scope-qualifier (
INTERFACE) is not required. When it is omitted,
PRIVATEis used by default.
- Command-line options can be supplied to the TAO/OpenDDS IDL compilers
OPENDDS_IDL_OPTIONS(if the default behavior is not suitable).
OPENDDS_IDL_OPTIONS -Lc++11to 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
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.
OPENDDS_TARGET_SOURCES(target [items...] [<INTERFACE|PUBLIC|PRIVATE> items...] [TAO_IDL_OPTIONS options...] [OPENDDS_IDL_OPTIONS options...] [SUPPRESS_ANYS ON|OFF] )
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
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
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++;
compiler macros are set on dependent libraries or executables. These defines
are set by MPC using the
CMake-Based targets must also inherit the defined macros, so the functionality
dcps_optional_features.mpb is simulated using
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
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
OFF depending on the desired state.
|CMake Variable||Notes (from configure script output)||Default|
||ContentFilteredTopic (CS Profile)||
||Content-Subscription Profile. When this is set to
||MultiTopic (CS Profile)||
||Object Model Profile||
||Exclusive Ownership (Ownership Profile)||
||Ownership Profile. When this is set to
||QueryCondition (CS Profile)||
||DDS Security plugin||
The following values impact the build in one way or another.
||Location of ACE root dir.||N/A|
||Location of TAO root dir.||N/A|
||Sets NDEBUG flags on ACE for non-debug builds (Unix only)||
||ACE's inline build flag||See below|
||Use static libraries||
||Adds dependencies to targets; required when
||ACE/TAO and OpenDDS were built with C++11 or later.||N/A|
||ACE/TAO and OpenDDS were built to prefer wide characters.||
||ACE/TAO and OpenDDS have versioned namespaces.||
||List of additional features which impact the build.||N/A|
OPENDDS_INLINE should be explicitly set to
OFF (based on the ACE
config.cmake unless you will only be using a CMake Microsoft Visual Studio Generator.
When parsing IDL, OpenDDS will determine if it should be prepared for a
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
OPENDDS_IDL_OPTIONS. For example:
add_library(messenger) OPENDDS_TARGET_SOURCES(messenger Messenger.idl OPENDDS_IDL_OPTIONS --no-default-nested )
This setting tells OpenDDS's IDL compiler to strip path information from
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_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:
- Default IDL-to-C++ mapping generated by default.
- IDL-to-C++11 mapping available when passing
- IDL-to-C++11 mapping available when passing
- Will appear if
- Will appear if
- Currently unsupported in the CMake module, but this will appear in the
- Currently unsupported in the CMake module, but this will appear in the list if
If the CMake version is at least 3.12, then this property will exported with the target.