.. include:: ../../external-links.part.rst

.. index::
    single: HelloWorld; Building
    single: CMake

##############################
Building HelloWorld with CMake
##############################

In the Installation :ref:`test__install` section, the :ref:`helloworld_test` test used 
the files in the default installation. Another way is to use the |url::cmake_link| 
build tool.

CMake is an open-source, cross-platform family of tools to build, test, and package 
software. It controls the software compilation process using simple platform and 
compiler-independent configuration files. It also generates the native makefiles, 
projects, and workspaces of your development environment. CMake's main strength is 
built portability. The same CMake input files can be built with GNU make, Visual 
Studio (6,7,8) IDEs, Borland make, nmake, and XCode, and so on.

Another advantage of CMake is building out-of-source. It simply works
out of the box. This facilitates:

- Easy cleanup (no cluttering the source tree). Remove the build directory to start 
  from scratch.
- Multiple build targets. It is possible to have up-to-date debug and release targets 
  without having to recompile the entire tree. It is easy for systems that do the 
  cross-platform compilation to have up-to-date builds for the host and target platform.

To use CMake, you must provide a ``CMakeLists.txt``, a copy of which, can be found in 
the ``<cyclonedds-directory>examples/helloworld`` directory that comes with the 
**Hello World!** example. The content is shown below:

The content of the ``CMakeLists.txt`` is:

.. tabs::

    .. group-tab:: Core DDS (C)

        .. literalinclude:: ../../../../examples/helloworld/CMakeLists.txt
           :language: cmake
           :linenos:

    .. group-tab:: C++

        .. code-block:: cmake

            project(helloworld LANGUAGES C CXX)
            cmake_minimum_required(VERSION 3.5)

            if (NOT TARGET CycloneDDS CXX::ddscxx)
            find_package(CycloneDDS CXX REQUIRED)
            endif()

            # Convenience function, provided by the idlc backend for CXX that generates a CMake
            # target for the given IDL file. The function calls idlc to generate
            # source files and compiles them into a library.
            idlcxx_generate(TARGET ddscxxHelloWorldData_lib FILES HelloWorldData.idl WARNINGS no-implicit-extensibility)

            add_executable(ddscxxHelloworldPublisher publisher.cpp)
            add_executable(ddscxxHelloworldSubscriber subscriber.cpp)

            # Link both executables to IDL data type library and ddscxx.
            target_link_libraries(ddscxxHelloworldPublisher ddscxxHelloWorldData_lib CycloneDDS CXX::ddscxx)
            target_link_libraries(ddscxxHelloworldSubscriber ddscxxHelloWorldData_lib CycloneDDS CXX::ddscxx)

            set_property(TARGET ddscxxHelloworldPublisher PROPERTY CXX_STANDARD 11)
            set_property(TARGET ddscxxHelloworldSubscriber PROPERTY CXX_STANDARD 11)


To build a |var-project-short| based application, you must link your business code to 
the following:

.. tabs::

    .. group-tab:: Core DDS (C)

        - The ``ddsc`` library that contains the DDS API for the application.

        - The helper functions and structures that represent your datatypes. These helpers are 
          generated by the IDL compiler and can be accessed through the CMake 
          (``idlc_generate``) call that takes the idl file (for example, ``HelloWorld.idl``) 
          as input, then packages the datatyped helpers in a library (for example, 
          ``HelloWorldData_lib``).

        The ``idlc_generate`` call makes use of how the IDL compiler generates the helpers' 
        functions and structures. The following diagram shows the process:

        .. image:: /_static/gettingstarted-figures/dds-application-design.png

        The executables of the |var-project-short|-based application (``HelloworldPublisher``
        and ``HelloworldSubscriber``) are linked to |var-project-short| with the CMake 
        ``target_link_libraries()`` call. This call combines the ``ddsc`` lib, the datatype 
        helper lib and the application code.

        .. note::
            CMake attempts to find the ``CycloneDDS`` CMake package in the default system 
            locations. If you experience problems with not being able to locate ``CycloneDDS`` 
            it is often enough to include the |var-project-short| <install-location> as CMake 
            Prefix Path. For example: ``cmake -DCMAKE_PREFIX_PATH=<install-location>``. If 
            you have further issues, please refer to CMake's |url::cmake_dependencies|.

    .. group-tab:: C++

        - ``|var-project-short| C++`` libraries that contain the DDS CXX API your 
          application needs.

        - The wrapper classes and structures that represent your datatypes and the 
          customized-DataWriter's and readers that can handle these data types. The 
          CMake statement generates these classes ``idlcxx_generate()`` that incepts 
          the IDL file invokes the IDL compiler and packages the datatype wrapper 
          classes in a library (e.g. ``ddscxxHelloWorldData_lib``).

        This process is outlined as follows:

        .. image:: /_static/gettingstarted-figures/6.1.1-1.png

        Setting the property for the applications in the CMake
        ``set_property()`` statement compiles the application against the
        ``C++ 11`` standard.

        The application executable (``ddscxxHellowordPublisher``) is built with
        the CMake ``target_link_libraries()`` statement which links the ddscxx
        lib, the datatype wrapper classes lib (e.g ``ddscxxHelloWorldData_lib``)
        and the application code lib.

        CMake tries to find the ``CycloneDDS`` and ``CycloneDDSCXX``
        CMake packages, the details regarding how to locate those packages are
        described in the next section. When the packages are found, every path
        and dependencies are automatically set.

Building the HelloWorld Example
===============================

.. note::
    We recommend that to build examples or applications out-of-source, create a 
    ``build`` directory inside the copy of the HelloWorld example directory. 
    
#. Open a terminal inside the directory with the HelloWorld files.
#. Run:

   .. code-block:: console

      mkdir build
        cd build

#. Configure the build environment:

   .. tabs::

       .. group-tab:: Linux

           .. code-block:: console

               cmake -DCMAKE_PREFIX_PATH=<install-location> ..

       .. group-tab:: macOS

           .. code-block:: console

               cmake -DCMAKE_PREFIX_PATH=<install-location> ..

       .. group-tab:: Windows

           .. code-block:: console

               cmake -G <generator-name> -DCMAKE_PREFIX_PATH=<install-location> ..

           On Windows you can build with one of several generators. Usually if you omit the ``-G <generator-name>``
           it will pick a sensible default, but if it doesn't work or picks something unexpected you can go to the
           `CMake generators documentation <https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html>`__.
           For example, "Visual Studio 15 2017 Win64" targets a 64-bit build using Visual Studio 2017.

           .. warning::

               If manually specifying generators be careful about mixing and matching! If you compiled |var-project-short| with 32-bit libraries
               and you try to compile **Hello World!** as 64-bit or vice-versa it will not work.

           .. warning::

               Weird things can happen if you mix ``-DCMAKE_BUILD_TYPE=Release``, ``-DCMAKE_BUILD_TYPE=RelWithDebInfo`` and ``-DCMAKE_BUILD_TYPE=Debug``,
               try to match what you picked for |var-project-short| in downstream projects.

#. CMake uses the ``CMakeLists.txt`` in the HelloWorld directory to create "makefiles" 
   that target the native platform. The |var-project-short| build directory is now ready 
   to build the ``HelloworldPublisher`` and ``HelloworldSubscriber`` executables. Run:

   .. code-block:: console

       cmake --build .

   Your build directory now contains your executables (on Windows they may be in a 
   ``Release`` or ``Debug`` subdirectory).

Test the build
==============

.. include:: helloworld_run.part.rst
