.. _section-building-source:
Building |me_h|
===============
Before you get started with |rti_me|, you must build the Platform Support
Library (PSL) for your platform from the source code provided in your
|me| installation. This section describes how to compile the
PSL for an architecture supported by RTI (see :ref:`rl_supported_v2`
for more information).
.. note::
|me| also requires a Platform Independent Library (PIL), which
is provided as a pre-compiled binary in your |me| installation and does
not need to be built.
This section is written for developers and engineers with a background in
software development. RTI recommends reading this section in order, as
one subsection may refer to or assume knowledge about concepts described in a
preceding subsection.
.. contents::
:local:
.. _section-set-up-build-environment:
Setting up the build environment
--------------------------------
The following terminology is used to refer to the environment in which |me|
is built and run:
- The *host* is the machine that runs the software to compile and
link |me|.
- The *target* is the machine that runs |me|.
- In many cases |me| is built *and* run on the same machine. This
is referred to as a *self-hosted environment*.
The *environment* is the collection of tools, OS, compiler, linker,
hardware, etc., needed to build and run applications.
The word *must* describes a requirement that must be met.
Failure to meet a *must* requirement may result in failure to
compile, use, or run |me|.
The word *should* describes a requirement that is strongly recommended
to be met. A failure to meet a *should* recommendation may
require modification to how |me| is built, used, or run.
The word *may* is used to describe an optional feature.
The host environment
....................
|me| has been designed to be easy to build and to require few tools on
the host.
The host machine **must**:
- support long filenames (8.3 will not work). |me| does not require a
case-sensitive file-system.
- have the necessary compiler, linkers, and build-tools installed.
The host machine **should**:
- have `CMake `_ (www.cmake.org) installed. Note that it is not
required to use `CMake `_ to build |me|, and in some cases it may
also not be recommended. As a rule of thumb, if |me| can be built
from the command-line, `CMake `_ is recommended.
- be able to run bash shell scripts (Unix type systems) or BAT scripts
(Windows machines).
Supported host environments are Windows (cygwin and mingw are not tested),
Linux, and macOS systems.
Typical examples of host machines are:
- a Linux PC with the GNU tools installed (make, gcc, g++, etc.).
- a Mac computer with Xcode and the command-line tools installed.
- a Windows computer with Microsoft Visual Studio Express edition.
- a Linux, Mac or Windows computer with an embedded development tool-suite.
The target environment
......................
The target machine must:
- support 8-bit, 16-bit, and 32-bit signed and unsigned integers. Note that a
16-bit CPU (or even 8-bit) is supported as long as the listed types are
supported.
|me| supports 64-bit CPUs, and it does not use any native 64-bit
quantities internally.
The target compiler should:
- have a C compiler that is C99 compliant. Note that many non-standard
compilers work, but may require additional configuration.
The remainder of this manual assumes that the target environment is one
supported by RTI:
- POSIX (Linux, macOS, QNX®, VOS, iOS, Android)
- VxWorks 6.9 or later
- Windows
- QNX
.. _`psl_compiling`:
Building the PSL
----------------
There are two recommended methods to compile the PSL: by running the ``rtime-make``
script (which invokes CMake), or by invoking CMake manually. Both are described
in more detail below.
`CMake `_ is the
preferred tool to build |me| because it simplifies configuring the |me|
build options and generates build files for a variety of environments.
Note that CMake itself does not compile anything. CMake
is used to *generate* build files for a number of environments,
such as make, Eclipse® CDT, Xcode® and Visual Studio. Once the build-files
have been generated, any of the tools mentioned can be used to build |me|.
This system makes it easier to support building |me| in different build
environments. CMake is easy to install with pre-built binaries
for common environments and has no dependencies on external tools.
Alternatively, you can include the PSL source as part of a |me| application.
Refer to :ref:`custom-build-environments` for more information on this option.
Building the PSL with rtime-make
................................
The |me| source bundle includes a bash (UNIX) and BAT (Windows) script to
simplify the invocation of `CMake `_. These scripts are
a convenient way to invoke `CMake `_ with the correct
options.
Run the ``rtime-make`` script with the following command:
.. code-block:: console
RTIMEHOME/resource/scripts/rtime-make --config Debug --target armv8leElfqcc8.3.0CERT-QOS2.2.1 \
-G "Unix Makefiles" --build
Here is an explanation of each argument in the above command:
- ``--config Debug``: Create Debug build.
- ``--target ``: The target for the sources to be built. Refer to
:ref:`rl_supported_v2` for the architecture abbreviations of supported
platforms.
- ``--build Build``: The generated project files.
To get a list of all the options, run:
.. code-block:: console
rtime-make -h
To get help for a specific target, run:
.. code-block:: console
rtime-make --target --help
Building the PSL with CMake
...........................
.. _`prepare-psl`:
Preparing to build
''''''''''''''''''
RTI recommends creating a unique directory for each build
configuration. A build configuration can be created to address specific
architectures, compiler settings, or different |me| build options.
RTI recommends assigning a descriptive *name* to each build
configuration, using a common format. While there are no requirements to
the format for functional correctness, the toolchain files in
|me| use the **RTIME_TARGET_NAME** variable to determine various
compiler options and selections.
RTI uses the following format for the target architecture PSL:
.. code-block:: none
{cpu}{compiler}{profile}-{OS}
- ``{cpu}``: the CPU that the library was compiled for.
- ``{compiler}``: the compiler used to build the library.
- ``{profile}``: CERT if the library was built to be Cert-compatible;
otherwise empty.
- ``{OS}``: The operating system that the PSL was compiled for.
For example, the target name ``armv8leElfqcc8.3.0CERT-QOS2.2.1`` describes a
PSL for |me| for an Armv8 CPU, running QOS 2.2.1, compiled with gcc 8.3.0.
Files built by each build configuration will be stored under
``RTIMEHOME/build/[Debug | Release]/``. These directories are referred to
as build directories or ``RTIMEBUILD``. The structure of the ``RTIMEBUILD`` depends on
the generated build files and should be regarded as an intermediate directory.
Creating build files from the command line
''''''''''''''''''''''''''''''''''''''''''
Open a terminal window in the ``RTIMEHOME`` directory and create the ``RTIMEBUILD``
directory. Change to the ``RTIMEBUILD`` directory and invoke CMake
with the following arguments:
.. code-block:: console
cmake -G -DCMAKE_BUILD_TYPE= \
-DCMAKE_TOOLCHAIN_FILE= \
-DRTIME_TARGET_NAME=
Depending on the generator, do one of the following:
- For IDE generators (such as Eclipse, Visual Studio, Xcode), open the generated
solution/project files and build the project/solution.
- For command-line tools (such as make, nmake, ninja), run the build-tool.
After a successful build, the output is placed in ``RTIMEHOME/lib/``.
The generated build files may contain different sub-projects that are
specific to the tool. For example, in Xcode and Visual Studio, the following
targets are available:
- ``ALL_BUILD``: Builds all the projects.
- ``\rti_me_``: Builds only the specific library. Note that that dependent
libraries are built first.
- ``ZERO_CHECK``: Runs `CMake `_ to regenerate project
files in case something changed in the build input. This target does not
need to be built manually.
For command-line tools, try `` help`` for a list of available targets to
build. For example, if UNIX makefiles were generated::
make help
CMake flags used by |me_h|
''''''''''''''''''''''''''
The following CMake flags (``-D``) are understood by |me| and may be useful
when building outside of the source bundle installed by RTI. An example would
be incorporating the |me| source in a project tree and invoking cmake directly
on the ``CMakeLists.txt`` file provided by |me|.
- ``-DRTIME_TARGET_NAME=`` - The name of the target (equivalant to ``--target`` to ``rtime-make``).
The default value is the name of the source directory.
- ``-DRTIME_CMAKE_ROOT=`` - Where to place the CMake build files.
The default value is *\/build/cmake*.
- ``-DRTIME_BUILD_ROOT=`` - Where to place the intermediate build files.
The default value is *\/build*.
- ``-DRTIME_SYSTEM_FILE=`` or an empty string - This file can be used to
set the PLATFORM_LIBS variable used by |me| to link with. If an empty
string is specified, no system file is loaded. This option may be useful
when cmake can detect all that is needed. The default value
is not defined, which means CMake will try to detect the system to build for.
- ``-DRTI_NO_SHARED_LIB=true`` - Do not build shared libraries. The default is undefined,
which means shared libraries are built. NOTE: This flag must be undefined
to build shared libraries. Setting the value to false is not supported.
- ``-DRTI_MANUAL_BUILDID=true`` - Do not automatically generate a build ID.
The default value is undefined, which means CMake will generate a new build each time
the libraries are built. Setting the value to false is not supported. The
build ID is in its own source and only forces a recompile of a few files.
Note that it is necessary to generate a build ID at least once (this is done
automatically). Also, a build ID is not supported for cmake versions
less than 2.8.11 because the TIMESTAMP function does not exist.
- ``-DRTIME_DDS_DISABLE_PARTICIPANT_MESSAGE_DATA=false`` Disables P2P Message Data
inter-participant channel. This channel is needed to use
:link_connextmicro_dds_api_c_up_one:`DDS_AUTOMATIC_LIVELINESS_QOS `
and :link_connextmicro_dds_api_c_up_one:`DDS_MANUAL_BY_PARTICIPANT_LIVELINESS_QOS `
with a finite lease duration.
Compile-time options
--------------------
The |me| PSL source supports compile-time options. These options
are generally used to control:
- Enabling/disabling features.
- Inclusion/exclusion of debug information.
- Inclusion/exclusion of APIs.
- Target platform definitions.
- Target compiler definitions.
.. note::
It is no longer possible to build a single library using `CMake `_.
Refer to `Custom Build Environments`_ for information on customized builds.
Debug information
.................
Please note that |me| debug information is independent of a debug build
as defined by a compiler. In the context of |me|, debug information refers
to inclusion of:
- Logging of error-codes.
- Tracing of events.
- Precondition checks (argument checking for API functions).
Unless explicitly included/excluded, the following rule is used:
- For CMAKE_BUILD_TYPE = Release, the NDEBUG preprocessor directive is defined.
Defining NDEBUG includes logging, but excludes tracing and precondition checks.
- For CMAKE_BUILD_TYPE = Debug, the NDEBUG preprocessor directive is undefined.
With NDEBUG undefined, logging, tracing and precondition checks are included.
To manually determine the level of debug information, the following options
are available:
- **OSAPI_ENABLE_LOG** (Include/Exclude/Default)
- Include - Include logging.
- Exclude - Exclude logging.
- Default - Include logging based on the default rule.
- **OSAPI_ENABLE_TRACE** (Include/Exclude/Default)
- Include - Include tracing.
- Exclude - Exclude tracing.
- Default - Include tracing based on the default rule.
- **OSAPI_ENABLE_PRECONDITION** (Include/Exclude/Default)
- Include - Include tracing.
- Exclude - Exclude tracing.
- Default - Include precondition checks based on the default rule.
Platform selection
..................
The |me| build system looks for target platform files in
``RTIMEHOME/include/osapi``. All files that match ``osapi_os_*.h`` are listed
under **RTIME_OSAPI_PLATFORM**. Thus, if RTI ports |me| to a new platform, the
target platform files will automatically be listed and available for selection.
The default behavior, ````, is to try to determine the target platform
based on header files. The following target platforms are known to work:
- Linux (posix)
- QNX (posix)
However, for custom ports, ```` may not work. In that case, select the
appropriate platform definition file instead of ````.
Compiler selection
..................
The |me| build system looks for target compiler files in
``RTIMEHOME/include/osapi``. All files that match ``osapi_cc_*.h`` are listed
under **RTIME_OSAPI_COMPILER**. Thus, if RTI adds a new compiler definition file,
it will automatically be listed and available for selection.
The default behavior, ````, is to try to determine the target
compiler based on header-files. The following target compilers are known
to work:
- GCC (stdc)
- clang (stdc)
- MSVC (stdc)
However, for others, ```` may not work. In that case, select the
appropriate compiler definition file instead of ````.
UDP options
...........
Checking the **RTIME_UDP_ENABLE_IPALIASES** option disables filtering out IP aliases.
Note that this currently only works on platforms where each IP alias has
its own interface name, such as eth0:1, eth1:2, etc.
Checking the **RTIME_UDP_ENABLE_TRANSFORMS_DOC** option enables UDP transformations in
the UDP transport.
Checking the **RTIME_UDP_EXCLUDE_BUILTIN** option excludes the UDP transport from being built.
.. _custom-build-environments:
Custom build environments
-------------------------
The preferred method to build |me| is to use `CMake `_. However,
in some cases it may be more convenient, or even necessary, to use a custom build
environment. For example:
- Embedded systems often have numerous compiler, linker, and board-specific
options that are easier to manage in a managed build.
- The compiler cannot be invoked outside of the build environment because it
is an integral part of the development environment.
- Sometimes better optimization may be achieved if all the components of
a project are built together.
- It is easier to port |me|.
Importing the |me_h| code
.........................
The process for importing the |me| source code into a project varies
depending on the development environment. However, in general the following
steps are needed:
- Create a new project or open an existing project.
- Import the entire |me| source tree from the file-system. Note that
some environments let you choose whether to make a copy-only link
to the original files.
- Add the following include paths:
- \/include/rti_me
- \/include/rti_me/rti_me_psl
- \/src/dds_c/domain
- \/src/dds_c/infrastructure
- \/src/dds_c/publication
- \/src/dds_c/subscription
- \/src/dds_c/topic
- \/src/dds_c/type
- Add a compile-time definition ``-DRTIME_TARGET_NAME="target name"``
(note that the ``"`` must be included).
- Add a compile-time definition ``-DNDEBUG`` for a release build.
- Add a compile-time definition of either ``-DRTI_ENDIAN_LITTLE`` for a
little-endian platform or ``-DRTI_ENDIAN_BIG`` for a big-endian platform.
- If custom OSAPI definitions are used, add a compile-time
definition ``-DOSAPI_OS_DEF_H="my_os_file"``.
- If custom compiler definitions are used, add a compile-time
definition ``-DOSAPI_CC_DEF_H="my_cc_file.h"`` .