Using OpenDDS in a CMake Project#
See also
OpenDDS can be used with CMake-based projects by using the OpenDDS CMake config package.
This package bridges the gap between the MPC build system used by OpenDDS and CMake-based projects by providing imported library targets and the ability to add IDL to a target using opendds_target_sources
.
Requirements#
CMake version 3.3.2 or greater is required to use the CMake package, but some some features require newer versions.
Using the OpenDDS CMake Package#
Examples#
Developer’s Guide Messenger Example#
For a simple quick-start example of a CMakeLists.txt
using OpenDDS with CMake see the Developer’s Guide Messenger example.
The following instructions show how to configure and build it:
Make sure the environment is setup by using source setenv.sh
.
cd DevGuideExamples/DCPS/Messenger
mkdir build
cd build
cmake ..
cmake --build .
perl run_test.pl
Make sure the environment is setup by using call setenv.cmd
.
cd DevGuideExamples\DCPS\Messenger
mkdir build
cd build
cmake ..
cmake --build .
perl run_test.pl
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 package) into the specified directory.
See Installation for details.
Note
Be sure to pass an absolute path to --prefix
.
OPENDDS_PREFIX="$PWD/opendds-install"
DDS_ROOT="$PWD/OpenDDS"
ACE_ROOT="$DDS_ROOT/ACE_wrappers"
cd OpenDDS
./configure --prefix="$OPENDDS_PREFIX"
make -j $(getconf _NPROCESSORS_ONLN)
make install
cd DevGuideExamples/DCPS/Messenger
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH="$OPENDDS_PREFIX" ..
cmake --build .
PERL5LIB="$DDS_ROOT/bin:$ACE_ROOT/bin" LD_LIBRARY_PATH="$OPENDDS_PREFIX/lib:$LD_LIBRARY_PATH" perl run_test.pl
Other Examples#
The CMake tests are written primarily as tests, but can also be used as examples for specific features and approaches.
find_package#
To use the OpenDDS CMake package, first it has to be loaded using find_package. For example to mandatorily load OpenDDS:
find_package(OpenDDS REQUIRED)
For this to work, CMake has to be able to find the package.
If the OpenDDS build environment variables (from source setenv.sh
or call setenv.cmd
) are set then CMake should be able to find it using the PATH
environment variable.
If those environment variables aren’t set, OpenDDS was installed to a path CMake doesn’t search automatically, or CMake can’t otherwise find the OpenDDS package, then CMake has to be told about it explicitly somehow.
This can be done a number of ways, which includes adding the OpenDDS source tree or install prefix path to CMAKE_PREFIX_PATH
or setting OPENDDS_ROOT
to that path (if using CMake 3.12 or later).
Consult the find_package
documentation for your CMake version for all the details on how CMake could find OpenDDS.
Here is the documentation for the latest version of CMake
Components#
New in version 3.25.
By default the package will search for all libraries and executables, but only require the bare minimum for ACE/TAO and OpenDDS.
Arguments can be passed to find_package(OpenDDS COMPONENTS <argument>...)
(or alternatively find_package(OpenDDS REQUIRED [COMPONENTS] <argument>...)
) add to what’s required.
These can be:
Executables and Libraries
Example:
find_package(OpenDDS REQUIRED OpenDDS::Rtps_Udp OpenDDS::RtpsRelay)
-
Feature names should be the same as the variable, but without the leading
OPENDDS_
and all lowercase. Feature names by themselves will be required to be enabled. If using CMake 3.9 or higher and the name is followed by=
, then the CMake boolean value following that determines if the feature must be enabled or disabled.Example:
find_package(OpenDDS REQUIRED built_in_topics safety_profile=OFF)
Note
Passing features to
OPTIONAL_COMPONENTS
is treated as an error. It doesn’t make sense to optionally request them because they are fixed. NO_DEFAULTS
Passing
NO_DEFAULTS
will only search for and require what is specified. This allows using ACE/TAO without OpenDDS being built, assuming the package is configured correctly. It also allowsOPTIONAL_COMPONENTS
to have an effect because normally everything is treated as optional.Example:
find_package(OpenDDS REQUIRED NO_DEFAULTS ACE::ACE OPTIONAL_COMPONENTS TAO::TAO)
This just makes
ACE::ACE
and optionallyTAO::TAO
available. NormallyACE::ACE
,TAO::TAO
, andOpenDDS::Dcps
are unconditionally searched for and required.
Adding IDL Sources with opendds_target_sources#
The CMake config package provides an easy way to add IDL sources to CMake targets using opendds_target_sources
.
Here is how it’s used in the Developer’s Guide Messenger example:
# IDL TypeSupport Library
add_library(messenger_idl)
opendds_target_sources(messenger_idl PUBLIC "Messenger.idl")
target_link_libraries(messenger_idl PUBLIC OpenDDS::Dcps)
Here the IDL is added to a library that is shared by the executables, but opendds_target_sources
can also be used on executables directly.
Note
CMake version 3.10 and below will issue a harmless warning if add_library
is called without any sources.
See opendds_target_sources
for all the options it accepts.
Linking OpenDDS Libraries#
In addition to C++ types generated from IDL and their type support, OpenDDS applications need discovery and transport to talk to each other. target_link_libraries should be used with all the libraries needed. Here is the usage in the Developer’s Guide Messenger example:
set(opendds_libs
OpenDDS::Dcps # Core OpenDDS Library
OpenDDS::InfoRepoDiscovery OpenDDS::Tcp # For run_test.pl
OpenDDS::Rtps OpenDDS::Rtps_Udp # For run_test.pl --rtps
messenger_idl
)
# Publisher
add_executable(publisher
Publisher.cpp
)
target_link_libraries(publisher ${opendds_libs})
# Subscriber
add_executable(subscriber
Subscriber.cpp
DataReaderListenerImpl.cpp
)
target_link_libraries(subscriber ${opendds_libs})
See Libraries for all the libraries the CMake package can provide.
install(IMPORTED_RUNTIME_ARTIFACTS)#
New in version 3.20.
If using CMake 3.21 or later, it’s possible to install executables and shared libraries from OpenDDS, ACE, and TAO in CMake along side the application using install(IMPORTED_RUNTIME_ARTIFACTS). This will just install shared libraries and executables, not static libraries, headers, or anything else required for building applications.
If OpenDDS and ACE/TAO is built with clang
, the shared libraries might be missing an SONAME
entry.
It is an issue with ACE/TAO.
If trying to use install(IMPORTED_RUNTIME_ARTIFACTS)
in this case, it causes the dynamic linker to ignore the libraries and report that they could not be found.
One workaround is to add SOFLAGS+=-Wl,-h,$(SONAME)
to $ACE_ROOT/include/makeinclude/platform_macros.GNU
before building.
This can be done manually after running the configure script or by passing --macros=SOFLAGS+=-Wl,-h,\$\(SONAME\)
to the configure script.
opendds_get_library_dependencies
is provided to help find out what libraries need to be installed.
See the install Test for an example of using this.
Changed in version 3.25: There are now executables that can be installed.
Installing Generated Interface Files#
New in version 3.20.
It is possible to install files from the OPENDDS_*_INTERFACE_FILES target properties for downstream projects to use.
See the install Test for an example of this.
It uses install(FILES), but there isn’t any restriction on what installation method can be used.
For example, the PUBLIC_HEADER target property could be set on target to the desired files from the interface lists.
Then they could be installed using install(TARGETS … PUBLIC_HEADER …).
Another method is provided by opendds_install_interface_files
.
Manually Creating config.cmake#
The configure script is responsible for generating the config.cmake
file in 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.
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 Config Variables for all the possible values to set.
Reference#
Targets#
Libraries#
The CMake package can provide library targets that can be linked using target_link_libraries or installed using install(IMPORTED_RUNTIME_ARTIFACTS).
- OpenDDS::Dcps#
Required, the core OpenDDS Library
- OpenDDS::Rtps#
- OpenDDS::InfoRepoDiscovery#
- OpenDDS::Rtps_Udp#
- OpenDDS::Multicast#
- OpenDDS::Shmem#
- OpenDDS::Tcp#
- OpenDDS::Udp#
- OpenDDS::Security#
- OpenDDS::RtpsRelayLib#
Support library for
OpenDDS::RtpsRelay
.New in version 3.25.
- ACE::ACE#
Required
- ACE::XML_Utils#
- TAO::TAO#
Required
- TAO::IDL_FE#
- TAO::AnyTypeCode#
- TAO::BiDirGIOP#
- TAO::CodecFactory#
- TAO::IORManip#
- TAO::IORTable#
- TAO::ImR_Client#
- TAO::PI#
- TAO::PortableServer#
- TAO::Svc_Utils#
- TAO::Valuetype#
Executables#
New in version 3.25.
The CMake package can provide executable targets that can be called manually from CMake or installed using install(IMPORTED_RUNTIME_ARTIFACTS).
- ACE::ace_gperf#
Required
- TAO::tao_idl#
Required
- OpenDDS::opendds_idl#
Required
- OpenDDS::DCPSInfoRepo#
- OpenDDS::RtpsRelay#
- OpenDDS::dcpsinfo_dump#
- OpenDDS::inspect#
- OpenDDS::repoctl#
Functions#
- opendds_target_sources#
opendds_target_sources(<target> [<idl-file>...] [PRIVATE|PUBLIC|INTERFACE <idl-file>...] [TAO_IDL_OPTIONS <option>...] [OPENDDS_IDL_OPTIONS <option>...] [SUPPRESS_ANYS TRUE|FALSE] [ALWAYS_GENERATE_LIB_EXPORT_HEADER TRUE|FALSE] [USE_EXPORT <export-header>;<export-macro>] [USE_VERSIONED_NAMESPACE <vns-header>;<vns-prefix>] [GENERATE_SERVER_SKELETONS TRUE|FALSE] [AUTO_LINK TRUE|FALSE] [INCLUDE_BASE <dir>] [SKIP_TAO_IDL] [SKIP_OPENDDS_IDL] )
A function that acts like target_sources, but it adds IDL files and the resulting generated code to a target.
<idl file>...
are IDL files that can be absolute or relative to CMAKE_CURRENT_SOURCE_DIR. Each one will generate code usingtao_idl
andopendds_idl
that is added to the target. The optional scope-qualifier (PRIVATE
,PUBLIC
,INTERFACE
) sets the scope of the generated files. When it is omitted,OPENDDS_DEFAULT_SCOPE
is used.Deprecated since version 3.15: C/C++ files can also be passed along with IDL files, but this has been deprecated.
- OPENDDS_IDL_OPTIONS <option>...#
Pass options to opendds_idl. Add
OPENDDS_IDL_OPTIONS -Lc++11
to use the C++11 IDL Mapping.
- SUPPRESS_ANYS TRUE|FALSE#
If
FALSE
, TAO TypeCode forany
will be generated. The default is set byOPENDDS_SUPPRESS_ANYS
.New in version 3.17.
- ALWAYS_GENERATE_LIB_EXPORT_HEADER TRUE|FALSE#
If
TRUE
, an header for exporting symbols in a shared library will be always generated as long the target is some sort of library. This is only really useful if the target is a library that uses the export header itself and also needs to be built as a static library as well. IfFALSE
, then it will only be done if the target is a shared library. The default is set byOPENDDS_ALWAYS_GENERATE_LIB_EXPORT_HEADER
.New in version 3.20.
- USE_EXPORT <export-header>;<export-macro>#
Pass a CMake list (
;
-delimited) of an existing export header and export macro to use in the generated code.New in version 3.25.
- USE_VERSIONED_NAMESPACE <version-ns-header>;<version-ns-prefix>#
Pass a CMake list (
;
-delimited) of an existing versioned namespace header and prefix to use in the generated code.New in version 3.26.
- GENERATE_SERVER_SKELETONS TRUE|FALSE#
tao_idl
generate code for CORBA servers. The default isFALSE
.tao_idl
by itself does this by default, but by defaultopendds_target_sources
passes-SS
to suppress this as it’s not normally useful to an OpenDDS application.New in version 3.25.
- AUTO_LINK TRUE|FALSE#
Automatically link
OpenDDS::Dcps
or other dependencies to the target using the “max” scope. IfFALSE
then dependencies will have to be linked manually. The default is set byOPENDDS_AUTO_LINK_DCPS
.New in version 3.25.
- INCLUDE_BASE <dir>#
Recreates the directory structure of all the passed IDLs relative to the passed base directory in the generated files. This allows using IDL files from multiple directories.
opendds_install_interface_files
is proved to help install generated files that result from this. Any IDL file passed that’s outside the include base will cause an error.The default behavior is the legacy behavior that assumes a flat hierarchy. Starting with OpenDDS 4.0 this will always be enabled and will default to
CMAKE_CURRENT_SOURCE_DIR
.New in version 3.26.
- SKIP_TAO_IDL#
Skip invoking
tao_idl
on the IDL files that are passed in. This will still runtao_idl
on*TypeSupport.idl
files unlessSKIP_OPENDDS_IDL
is passed in or-SI
is passed toopendds_target_sources(OPENDDS_IDL_OPTIONS)
.New in version 3.25.
- SKIP_OPENDDS_IDL#
Skip invoking
opendds_idl
on the IDL files.New in version 3.25.
After
opendds_target_sources
is run on a target, it will have these target properties set on it:- OPENDDS_LANGUAGE_MAPPINGS#
This holds the IDL language mappings used in the target based on what is passed to
opendds_target_sources(OPENDDS_IDL_OPTIONS)
.It will be a list that can contain one or more of the following:
"C++03"
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.
If the CMake version is at least 3.12, then this property will be exported with the target.
New in version 3.15.
- OPENDDS_GENERATED_DIRECTORY#
The is the directory where generated files have been placed. This is an absolute path and is not exported with the target. See Installing Generated Interface Files for more information.
New in version 3.20.
The following
OPENDDS_*_INTERFACE_FILES
target properties are used to help with Installing Generated Interface Files. Some notes about these properties:All paths are absolute.
All the generated files will be somewhere within the path from the
OPENDDS_GENERATED_DIRECTORY
target property of the target.All the properties have the
INTERFACE
in their name, but this includesPUBLIC
scoped files asPUBLIC
impliesINTERFACE
in CMake.PRIVATE
scoped files are excluded from these lists as they shouldn’t have a use outside the target.These properties are not exported with the target because the paths may not be valid any more if the build directory has been removed or the export is being used on another machine.
- OPENDDS_PASSED_IDL_INTERFACE_FILES#
The
PUBLIC
andINTERFACE
scoped IDL files passed.New in version 3.20.
- OPENDDS_GENERATED_IDL_INTERFACE_FILES#
The IDL files generated from the IDL files in
OPENDDS_PASSED_IDL_INTERFACE_FILES
.New in version 3.20.
- OPENDDS_ALL_IDL_INTERFACE_FILES#
Combination of
OPENDDS_PASSED_IDL_INTERFACE_FILES
andOPENDDS_GENERATED_IDL_INTERFACE_FILES
.
- OPENDDS_GENERATED_HEADER_FILES#
The
.h
and.inl
files generated fromOPENDDS_ALL_IDL_INTERFACE_FILES
.New in version 3.20.
- OPENDDS_ALL_GENERATED_INTERFACE_FILES#
Combination of
OPENDDS_GENERATED_IDL_INTERFACE_FILES
andOPENDDS_GENERATED_HEADER_FILES
.New in version 3.20.
- OPENDDS_ALL_INTERFACE_FILES#
All the
INTERFACE
andPUBLIC
scoped files that were passed in or generated.New in version 3.20.
Changed in version 3.25:
OPENDDS_TARGET_SOURCES
is now calledopendds_target_sources
, but this shouldn’t affect anything because functions and macros are case-insensitive in CMake.
- opendds_get_library_dependencies#
opendds_get_library_dependencies(<output-list-var-name> <target>...)
If given targets provided by the CMake package, it will return a list of the targets along with their ACE, TAO, and OpenDDS dependencies. This is provided to help use install(IMPORTED_RUNTIME_ARTIFACTS).
New in version 3.20.
- opendds_export_header#
opendds_export_header(<target> [USE_EXPORT_VAR <use-export-var-name>])
Generates a header that is compatible with ACE’s generate_export_file.pl for exporting symbols in shared libraries. The header will able to be included as
<target>_export.h
and the macro that can be used to export symbols will be named<target>_Export
. It is the same functionopendds_target_sources
uses so all the same info about generated files applies.- USE_EXPORT_VAR <use-export-var-name>#
Set a variable with the given name that contains a list with the location of the generated export header and the macro name to export a symbol.
New in version 3.25.
- opendds_install_interface_files#
opendds_install_interface_files(<target> [DEST <dir>] [INCLUDE_BASE <dir>] [EXTRA_GENERATED_FILES <file>...] )
A helper function that installs the files from the OPENDDS_*_INTERFACE_FILES target properties of the given target and is meant to be used with
opendds_target_sources(INCLUDE_BASE)
. The install path of a fileidl_file
could be described asDEST/relative(idl_file,INCLUDE_BASE)/idl_file
.- DEST <dir>#
The base directory to install them to. By default this is CMAKE_INSTALL_INCLUDEDIR.
- INCLUDE_BASE <dir>#
The source directory relative to the source IDL files to define the directory structure of the installed files. This should probably be the same as
opendds_target_sources(INCLUDE_BASE)
. By default this isCMAKE_CURRENT_SOURCE_DIR
.
- EXTRA_GENERATED_FILES <file>...#
Extra custom files that are in
OPENDDS_GENERATED_DIRECTORY
to install using the same method.
New in version 3.26.
Variables#
Package Options#
These variables can be used to override default behavior of the CMake package.
Warning
Except for OPENDDS_CMAKE_VERBOSE
, do not set these when building OpenDDS using CMake.
All the others will either have no effect or break the build.
- OPENDDS_CMAKE_VERBOSE#
If
TRUE
, then log detailed status information at configure-time. The default for this isFALSE
.New in version 3.25: The variable can also contain a list of categories to log more verbosely:
all
Enables all logging
components
Logs what components were passed and the exact list of libraries are being searched for and required.
imports
Logs the paths of executables and libraries that are going to be imported.
opendds_target_sources
Logs the arguments of
opendds_target_sources
and what files will be generated.
- OPENDDS_DEFAULT_NESTED#
If
TRUE
, then topic types must be declared explicitly using annotations. The default for this isTRUE
.This can also be controlled on a finer level by passing
--default-nested
or--no-default-nested
toopendds_target_sources(OPENDDS_IDL_OPTIONS)
. For example:add_library(messenger) opendds_target_sources(messenger PUBLIC Messenger.idl OPENDDS_IDL_OPTIONS --no-default-nested )
- OPENDDS_FILENAME_ONLY_INCLUDES#
Setting this to
TRUE
tellsopendds_idl
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. The default for this isFALSE
.New in version 3.15.
Deprecated since version 3.26:
opendds_target_sources(INCLUDE_BASE)
is a better way to handle IDL in multiple nested directories.
- OPENDDS_SUPPRESS_ANYS#
Default value for
opendds_target_sources(SUPPRESS_ANYS)
. The default for this isTRUE
.New in version 3.17.
- OPENDDS_ALWAYS_GENERATE_LIB_EXPORT_HEADER#
Default value for
opendds_target_sources(ALWAYS_GENERATE_LIB_EXPORT_HEADER)
. The default for this isFALSE
.New in version 3.20.
- OPENDDS_DEFAULT_SCOPE#
Default scope of unscoped files in
opendds_target_sources
. It must bePRIVATE
,PUBLIC
, orINTERFACE
. The default for this isPRIVATE
.New in version 3.20.
- OPENDDS_AUTO_LINK_DCPS#
Default value for
opendds_target_sources(AUTO_LINK)
. The default for this isFALSE
.Note
This is off by default because it’s not compatible with any existing usage of target_link_libraries that doesn’t specify a scope. The default for this will be
TRUE
starting in OpenDDS 4.0.New in version 3.24.
- OPENDDS_USE_CORRECT_INCLUDE_SCOPE#
If
TRUE
, then include directories of generated files using the “max” scope specified inopendds_target_sources
. The default for this isFALSE
, which always includes them using thePUBLIC
scope.Note
This is off by default because it could cause “Cannot find source file” errors on
TypeSupport.idl
files generated in a another directory. This will be fixed in OpenDDS 4.0 by requiring at least CMake 3.20 to get CMP0118. This variable will be removed in OpenDDS 4.0 and the behavior will be the same as if this variable was set toTRUE
.New in version 3.24.
Config Variables#
These variables are set by the configure
script in an MPC-built OpenDDS and normally shouldn’t be changed.
They can be changed when configuring a CMake-built OpenDDS using -D
, but should not be changed after that.
See also
Dependencies#
- OPENDDS_ACE_VERSION#
The version of ACE being used.
New in version 3.27.
- OPENDDS_TAO_VERSION#
The version of TAO being used.
New in version 3.27.
- OPENDDS_GTEST#
Path to GoogleTest
- OPENDDS_HOST_TOOLS#
A directory that contains a
bin
directory withopendds_idl
to be used for cross-compiling.New in version 3.26.
- OPENDDS_ACE_TAO_HOST_TOOLS#
A directory that contains a
bin
directory withtao_idl
andace_gperf
to be used for cross-compiling. This isn’t set by default unlessOPENDDS_HOST_TOOLS
is set, in which case it defaults to that.New in version 3.26.
Features#
- OPENDDS_CXX11#
ACE/TAO and OpenDDS were built with C++11 or later. Default depends on the compiler being used. Has no effect when building OpenDDS using CMake.
- OPENDDS_DEBUG#
Default depends on CMAKE_BUILD_TYPE. When building OpenDDS using CMake
CMAKE_BUILD_TYPE
should be used.
- OPENDDS_OPTIMIZE#
Default depends on CMAKE_BUILD_TYPE. When building OpenDDS using CMake
CMAKE_BUILD_TYPE
should be used.
- OPENDDS_INLINE#
.inl
files are included in header files. Default isON
Has no effect when building OpenDDS using CMake.
- OPENDDS_VERSIONED_NAMEPSACE#
ACE/TAO and OpenDDS have versioned namespaces. Default is
OFF
- OPENDDS_STATIC#
ACE/TAO are built as static libraries. Default depends on BUILD_SHARED_LIBS. When building OpenDDS using CMake
BUILD_SHARED_LIBS
should be used.
- OPENDDS_WCHAR#
ACE/TAO prefers using wide characters. Default is
OFF
- OPENDDS_TAO_IIOP#
Default is
ON
- OPENDDS_TAO_OPTIMIZE_COLLOCATED_INVOCATIONS#
Default is
ON
- OPENDDS_BUILT_IN_TOPICS#
Default is
ON
- OPENDDS_OBJECT_MODEL_PROFILE#
Default is
ON
- OPENDDS_PERSISTENCE_PROFILE#
Default is
ON
- OPENDDS_OWNERSHIP_PROFILE#
Default is
ON
- OPENDDS_OWNERSHIP_KIND_EXCLUSIVE#
Default is the value of
OPENDDS_OWNERSHIP_PROFILE
.
- OPENDDS_CONTENT_SUBSCRIPTION#
Default is
ON
- OPENDDS_CONTENT_FILTERED_TOPIC#
Default is the value of
OPENDDS_CONTENT_SUBSCRIPTION
.
- OPENDDS_MULTI_TOPIC#
Default is the value of
OPENDDS_CONTENT_SUBSCRIPTION
.
- OPENDDS_QUERY_CONDITION#
Default is the value of
OPENDDS_CONTENT_SUBSCRIPTION
.
- OPENDDS_SECURITY#
Default is
OFF
- OPENDDS_SAFETY_PROFILE#
Default is
OFF