Building HelloWorld with CMake¶
In the Installation Test your installation section, the HelloWorld test used the files in the default installation. Another way is to use the CMake 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:
1#
2# Copyright(c) 2019 to 2022 ZettaScale Technology and others
3#
4# This program and the accompanying materials are made available under the
5# terms of the Eclipse Public License v. 2.0 which is available at
6# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
7# v. 1.0 which is available at
8# http://www.eclipse.org/org/documents/edl-v10.php.
9#
10# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
11#
12cmake_minimum_required(VERSION 3.16)
13project(helloword LANGUAGES C)
14
15if(NOT TARGET CycloneDDS::ddsc)
16 # Find the CycloneDDS package.
17 find_package(CycloneDDS REQUIRED)
18endif()
19
20# This is a convenience function, provided by the CycloneDDS package,
21# that will supply a library target related the the given idl file.
22# In short, it takes the idl file, generates the source files with
23# the proper data types and compiles them into a library.
24idlc_generate(TARGET HelloWorldData_lib FILES "HelloWorldData.idl" WARNINGS no-implicit-extensibility)
25
26# Both executables have only one related source file.
27add_executable(HelloworldPublisher publisher.c)
28add_executable(HelloworldSubscriber subscriber.c)
29
30# Both executables need to be linked to the idl data type library and
31# the ddsc API library.
32target_link_libraries(HelloworldPublisher HelloWorldData_lib CycloneDDS::ddsc)
33target_link_libraries(HelloworldSubscriber HelloWorldData_lib CycloneDDS::ddsc)
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 Cyclone DDS based application, you must link your business code to the following:
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:
The executables of the Cyclone DDS-based application (HelloworldPublisher
and HelloworldSubscriber
) are linked to Cyclone DDS 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 Cyclone DDS <install-location> as CMake
Prefix Path. For example: cmake -DCMAKE_PREFIX_PATH=<install-location>
. If
you have further issues, please refer to CMake’s Using dependencies guide.
|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:
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:
mkdir build cd build
Configure the build environment:
cmake -DCMAKE_PREFIX_PATH=<install-location> ..
cmake -DCMAKE_PREFIX_PATH=<install-location> ..
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. 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 Cyclone DDS 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 Cyclone DDS in downstream projects.CMake uses the
CMakeLists.txt
in the HelloWorld directory to create “makefiles” that target the native platform. The Cyclone DDS build directory is now ready to build theHelloworldPublisher
andHelloworldSubscriber
executables. Run:cmake --build .
Your build directory now contains your executables (on Windows they may be in a
Release
orDebug
subdirectory).
Test the build¶
Open two terminals inside the directory with the HelloWorld files.
In the first terminal, start the subscriber by running
HelloWorldSubscriber
../HelloworldSubscriber
./HelloworldSubscriber
HelloworldSubscriber.exe
In the second terminal, start the publisher by running
HelloWorldPublisher
../HelloworldPublisher
./HelloworldPublisher
HelloworldPublisher.exe
HelloworldPublisher
appears as follows:
HelloworldSubscriber
appears as follows: