################################ Using OpenDDS in a CMake Project ################################ .. seealso:: :ref:`cmake-building` OpenDDS can be used with `CMake `__\-based projects by using the :ghfile:`OpenDDS CMake config package `. This package bridges the gap between the MPC build system used by OpenDDS and CMake-based projects by providing :ref:`imported library targets ` and the ability to add IDL to a target using :cmake:func:`opendds_target_sources`. ************ Requirements ************ CMake version 3.3.2 or greater is required to use the CMake package, but 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 :ghfile:`Developer’s Guide Messenger example `. The following instructions show how to configure and build it: .. tab:: Linux, macOS, BSDs, etc. Make sure the environment is setup by using ``source setenv.sh``. .. code:: bash cd DevGuideExamples/DCPS/Messenger mkdir build cd build cmake .. cmake --build . perl run_test.pl .. tab:: Windows Make sure the environment is setup by using ``call setenv.cmd``. .. code:: bat 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 :ref:`install` for details. .. note:: Be sure to pass an absolute path to ``--prefix``. .. code:: bash 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 :ghfile:`CMake tests ` are written primarily as tests, but can also be used as examples for specific features and approaches. ``find_package(OpenDDS)`` ========================= To use the OpenDDS CMake package, first it has to be loaded using `find_package `__. For example to mandatorily load OpenDDS: .. code:: cmake 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 .. _cmake-components: Components ---------- .. versionadded:: 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 ...)`` (or alternatively ``find_package(OpenDDS REQUIRED [COMPONENTS] ...)``) require additional executables, libraries, and features. These can be: - :ref:`Executables ` and :ref:`Libraries ` Example: .. code-block:: cmake find_package(OpenDDS REQUIRED OpenDDS::Rtps_Udp OpenDDS::RtpsRelay) - :ref:`Features ` 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: .. code-block:: cmake 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 when OpenDDS is built. - ``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 allows ``OPTIONAL_COMPONENTS`` to have an effect because normally everything is treated as optional. Example: .. code-block:: cmake find_package(OpenDDS REQUIRED NO_DEFAULTS ACE::ACE OPTIONAL_COMPONENTS TAO::TAO) This just makes :cmake:tgt:`ACE::ACE` and optionally :cmake:tgt:`TAO::TAO` available. Normally :cmake:tgt:`ACE::ACE`, :cmake:tgt:`TAO::TAO`, and :cmake:tgt:`OpenDDS::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 :cmake:func:`opendds_target_sources`. Here is how it's used in the :ghfile:`Developer’s Guide Messenger example `: .. literalinclude:: ../../../DevGuideExamples/DCPS/Messenger/CMakeLists.txt :language: cmake :start-at: IDL TypeSupport Library :end-before: set(opendds_libs 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 :cmake:func:`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 :ghfile:`Developer’s Guide Messenger example `: .. literalinclude:: ../../../DevGuideExamples/DCPS/Messenger/CMakeLists.txt :language: cmake :start-at: set(opendds_libs :end-at: target_link_libraries(subscriber ${opendds_libs}) See :ref:`cmake-libraries` for all the libraries the CMake package can provide. .. _cmake-install-imported-runtime-artifacts: ``install(IMPORTED_RUNTIME_ARTIFACTS)`` ======================================= .. versionadded:: 3.20 If using CMake 3.21 or later, it’s possible to install :ref:`executables ` and :ref:`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. :cmake:func:`opendds_get_library_dependencies` is provided to help find out what libraries need to be installed. See the :ghfile:`install Test ` for an example of using this. .. versionchanged:: 3.25 There are now :ref:`executables ` that can be installed. .. _cmake-installing-generated-interface-files: Installing Generated Interface Files ==================================== .. versionadded:: 3.20 It is possible to install files from the :ref:`OPENDDS_*_INTERFACE_FILES target properties ` for downstream projects to use. See the :ghfile:`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 :cmake:func:`opendds_install_interface_files`. Manually Creating ``config.cmake`` ================================== The :ghfile:`configure script ` is responsible for generating the ``config.cmake`` file in :ghfile:`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 :ref:`cmake-config-vars` for all the possible values to set. ********* Reference ********* Targets ======= .. _cmake-libraries: Libraries --------- The CMake package can provide library targets that can be linked using `target_link_libraries `__ or installed using :ref:`cmake-install-imported-runtime-artifacts`. .. cmake:tgt:: OpenDDS::Dcps Required, the core OpenDDS Library .. cmake:tgt:: OpenDDS::Rtps :ref:`rtps-disc` .. cmake:tgt:: OpenDDS::InfoRepoDiscovery :ref:`inforepo-disc` .. cmake:tgt:: OpenDDS::Rtps_Udp :ref:`rtps-udp-transport` .. cmake:tgt:: OpenDDS::Multicast :ref:`multicast-transport` .. cmake:tgt:: OpenDDS::Shmem :ref:`shmem-transport` .. cmake:tgt:: OpenDDS::Tcp :ref:`tcp-transport` .. cmake:tgt:: OpenDDS::Udp :ref:`udp-transport` .. cmake:tgt:: OpenDDS::Security :ref:`sec` .. cmake:tgt:: OpenDDS::RtpsRelayLib Support library for :cmake:tgt:`OpenDDS::RtpsRelay`. .. versionadded:: 3.25 .. cmake:tgt:: ACE::ACE :no-contents-entry: Required .. cmake:tgt:: ACE::XML_Utils :no-contents-entry: .. cmake:tgt:: TAO::TAO :no-contents-entry: Required .. cmake:tgt:: TAO::IDL_FE :no-contents-entry: .. cmake:tgt:: TAO::AnyTypeCode :no-contents-entry: .. cmake:tgt:: TAO::BiDirGIOP :no-contents-entry: .. cmake:tgt:: TAO::CodecFactory :no-contents-entry: .. cmake:tgt:: TAO::IORManip :no-contents-entry: .. cmake:tgt:: TAO::IORTable :no-contents-entry: .. cmake:tgt:: TAO::ImR_Client :no-contents-entry: .. cmake:tgt:: TAO::PI :no-contents-entry: .. cmake:tgt:: TAO::PortableServer :no-contents-entry: .. cmake:tgt:: TAO::Svc_Utils :no-contents-entry: .. cmake:tgt:: TAO::Valuetype :no-contents-entry: .. _cmake-executables: Executables ----------- .. versionadded:: 3.25 The CMake package can provide executable targets that can be called manually from CMake or installed using :ref:`cmake-install-imported-runtime-artifacts`. .. cmake:tgt:: ACE::ace_gperf Required .. cmake:tgt:: TAO::tao_idl Required, :term:`tao_idl` .. cmake:tgt:: OpenDDS::opendds_idl Required, :ref:`opendds_idl` .. cmake:tgt:: OpenDDS::DCPSInfoRepo :ref:`inforepo` .. cmake:tgt:: OpenDDS::RtpsRelay :ref:`rtpsrelay` .. cmake:tgt:: OpenDDS::dcpsinfo_dump Utility for :ref:`inforepo` .. cmake:tgt:: OpenDDS::inspect :ghfile:`tools/inspect/README.rst` .. cmake:tgt:: OpenDDS::repoctl Utility for :ref:`inforepo` Functions ========= .. |multiple-call-export-note| replace:: If there are multiple calls to :cmake:func:`opendds_target_sources` or :cmake:func:`opendds_export_header` on the same target, only the export header settings of the first call are used. .. cmake:func:: opendds_target_sources :: opendds_target_sources( [...] [PRIVATE|PUBLIC|INTERFACE ...] [TAO_IDL_OPTIONS