Using CMake¶
To build a package¶
To build a Sen package, use the add_sen_package function:
add_sen_package(
TARGET <target>
[MAINTAINER <maintainer>]
[DESCRIPTION <description>]
[VERSION <version>]
[BASE_PATH base_path]
[EXPORT_NAME name of the Sen package exported, defaults to target's name if not set]
[SCHEMA_PATH path]
[GEN_HDR_FILES variable]
[CODEGEN_SETTINGS file]
[HLA_OUTPUT_DIR path]
[SOURCES [files...]]
[DEPS [dependencies...]]
[PRIVATE_DEPS [dependencies...]]
[STL_FILES [files...]]
[HLA_FOM_DIRS [dirs...]]
[HLA_MAPPINGS_FILE [files...]]
[EXPORTED_CLASSES name of the classes exported by the package (if null, the exported classes are parsed automatically from the source files)]
[IS_COMPONENT flag used if we want to implement a custom Sen component]
[NO_SCHEMA flag used when we dont want to generate a JSON schema for the YAML configuration files of the package]
[PUBLIC_SYMBOLS flag used when we want to mark the symbols of the generated code as visible]
[TEST_TARGET name] if provided, a (static) test target is created (it exposes the internal package symbols)
)
It takes the following parameters:
| Name | Mandatory | Multiple | Description |
|---|---|---|---|
TARGET |
Name of the target that will be created for this component. | ||
MAINTAINER |
Name of the maintainer/author. | ||
DESCRIPTION |
Textual description of the implemented function. | ||
VERSION |
Semantic versioning for the generated binary. | ||
BASE_PATH |
Import path for Sen files and the one to be used by its dependencies. | ||
EXPORT_NAME |
Name of the exported Sen package. Defaults to the target's name if not set. | ||
SCHEMA_PATH |
Path where you want to have the data model schema. | ||
GEN_HDR_FILES |
Variable containing generated header files. | ||
CODEGEN_SETTINGS |
Path to the JSON file containing the settings for the code generator. | ||
HLA_OUTPUT_DIR |
Path where HLA output files will be placed. | ||
SOURCES |
List of source files (relative to this file). | ||
DEPS |
List of libraries that the component will publicly link to. | ||
PRIVATE_DEPS |
List of libraries that the component will privately link to. | ||
STL_FILES |
List of STL files to process from which the Sen package will generate code. | ||
HLA_FOM_DIRS |
Directories containing HLA FOM files. | ||
HLA_MAPPINGS_FILE |
Files containing HLA mappings. | ||
EXPORTED_CLASSES |
Name of the classes exported by the package (if null, the exported classes are parsed automatically from the source files). | ||
IS_COMPONENT |
If present, a sen component is generated. | ||
PUBLIC_SYMBOLS |
If present, all symbols of the generated code are visible. | ||
NO_SCHEMA |
If present, no schema is generated for the data model. | ||
TEST_TARGET |
If used, a (static) test target is created exposing internal package symbols. |
For example,
add_sen_package(
TARGET
calculators
MAINTAINER
"Enrique Parodi Spalazzi (enrique.parodi@airbus.com)"
VERSION
"0.0.1"
DESCRIPTION
"Example package"
SOURCES
src/casio_calculator.cpp
src/faulty_calculator.cpp
STL_FILES
stl/calculator.stl
SCHEMA_PATH
${CMAKE_CURRENT_BINARY_DIR}
)
How to use the DEPS and PRIVATE options for dependencies¶
The DEPS and PRIVATE_DEPS options of the add_sen_package function are used to link
dependencies to a package. These dependencies can be of two different types:
- Other Sen packages: these dependencies are linked against our package and their
BASE_PATHproperties are transmitted to our package, so we can include STL/XML files in the generated code of our package. This is very important, as only linking Sen packages is not enough for using their interface files, we need to add them to theDEPSoption. - Dependencies that are not Sen packages: These are just linked to our Sen package as dependencies.
DEPSlinks the dependency asPUBLICandPRIVATE_DEPSdoes it asPRIVATE.
Using Sen packages as dependencies of other Sen packages¶
If you plan to use the package as a dependency for other packages, and therefore want the symbols in
that package to be exported, set the PUBLIC_SYMBOLS flag in the add_sen_package function. This
can also be achieved by calling sen_generate_package, which is an alias of add_sen_package with
the PUBLIC_SYMBOLS flag on. However, the use of sen_generate_package is not advised as it will
be deprecated in the future, and it was only added to keep retro-compatibility with previous
versions.
Important note: only types in the generated code are exported, if you want any of the types of
your package implementation (the ones defined in the SOURCES) to be exported, you need to
explicitly export it using the SEN_EXPORT macro, as the symbols in the package will be hidden by
default.
Below is an example of two packages, where one of them is linked as a dependency to the other:
add_sen_package(
TARGET
hla_fom
BASE_PATH
${CMAKE_CURRENT_LIST_DIR}
HLA_OUTPUT_DIR
hla_fom
HLA_FOM_DIRS
rpr netn link16
GEN_HDR_FILES
fom_headers
HLA_MAPPINGS_FILE
base_mappings.xml
SCHEMA_PATH
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC_SYMBOLS
)
add_sen_package(
TARGET
aircrafts
MAINTAINER
"Enrique Parodi Spalazzi (enrique.parodi@airbus.com)"
VERSION
"0.0.1"
DESCRIPTION
"Dummy entities for testing"
STL_FILES
stl/dummy_aircraft.stl
SOURCES
src/dummy_aircraft_impl.cpp
DEPS
hla_fom sen::util
SCHEMA_PATH
${CMAKE_CURRENT_BINARY_DIR}
)
As you can see, the hla_fom package is linked as a dependency of the aircrafts package,
therefore it is marked with the PUBLIC_SYMBOLS flag.
How to test the internal implementation of a package? The TEST_TARGET option¶
Sen packages have all symbols hidden by default. This means that if we want to have a test executable for the implementation details of a package, we cannot link that executable directly against the package and expect it to work. All the symbols in the package will not be visible to the test executable.
In order to tackle this problem, we created the TEST_TARGET option on the add_sen_package
function. In the TEST_TARGET option, the user can specify the name of a test_target (e.g.
<target_name>_test) which will finally be a STATIC library containing the package code.
Then, the test executable can be linked against that test target and, due to the static linking, all the symbols will be available in our executable.
However, adding the TEST_TARGET option changes how the add_sen_package function works: in order
to avoid compiling the package twice (one as <target_name> and one as <target_name>_test), we
use an intermediate cmake OBJECT target called <target_name>_obj, which is the one that is
actually compiled. This implies that any modification that we want to do to our package outside
the add_sen_package function, we want to do it to the <target_name>_obj and not to the
<target_name>.
Below is an example of a Sen package with the TEST_TARGET option enabled:
add_sen_package(
TARGET
my_package
SOURCES
${base_sources}
STL_FILES
stl/configuration.stl stl/options.stl stl/types.stl
DEPS
asio::asio
llhttp::llhttp
nlohmann_json::nlohmann_json
spdlog::spdlog
BASE_PATH
${CMAKE_CURRENT_SOURCE_DIR}
TEST_TARGET
my_package_test
)
target_include_directories(my_package_obj PUBLIC directories/to/include)
add_executable(gtest_for_my_package test.cpp)
target_link_libraries(gtest_for_my_package PRIVATE my_package_test)
As you can see in the example above, the include directories property is set to my_package_obj and
not to my_package or my_package_test. Afterward, the gtest_for_my_package executable is linked
against the my_package_test.
How to implement a custom Sen component, the IS_COMPONENT flag (Advanced)¶
If you want to implement your own Sen component, just add the IS_COMPONENT flag to the
add_sen_package function. Below is a usage example of the add_sen_package function being used to
add a Sen component:
add_sen_package(
TARGET
example_component
MAINTAINER
"Enrique Parodi Spalazzi (enrique.parodi@airbus.com)"
VERSION
"0.0.1"
DESCRIPTION
"Executes a method call during object removal"
SOURCES
component.cpp
STL_FILES
stl/example.stl
IS_COMPONENT
)
Other utilities¶
Direct code generation¶
sen_generate_cpp(
TARGET <target>
[BASE_PATH base_path]
[STL_FILES [files...]]
[HLA_FOM_DIRS [directories...]]
[HLA_MAPPINGS_FILE file]
[GEN_HDR_FILES variable]
[CODEGEN_SETTINGS file]
)
For example,
or,
sen_generate_cpp(
TARGET
fom_lib
HLA_FOM_DIRS
rpr
netn
GEN_HDR_FILES
fom_headers
HLA_MAPPINGS_FILE
mapping.xml
)
Static analysis¶
The sen_enable_static_analysis function enables clang-tidy for the target.
UML diagrams¶
Sen can generate PlantUML diagrams.
sen_generate_uml(
[BASE_PATH base_path]
[STL_FILES [files...]] | [HLA_FOM_DIRS [directories...]]
[CLASSES_ONLY | TYPES_ONLY | TYPES_ONLY_NO_ENUMS]
OUT output_file
)
For example:
sen_generate_uml(
TARGET
fom_lib_uml
OUT
${CMAKE_CURRENT_BINARY_DIR}/fom.plantuml
HLA_FOM_DIRS
rpr
netn
CLASSES_ONLY
)
Target configuration¶
The function, sen_configure_target(<target>) adds all the compiler and linker flags, warnings and
options for building a Sen binary target.
Python and YAML generation¶
You can use Python to store your configuration data. This provides a more flexible, readable and powerful way of managing complex parameters.
The Sen kernel takes the configuration data from YAML files, but Python can be used to generate the YAML files. To help you in this task, Sen provides means for generating Python code consisting in dataclasses for a type-safe approach.
There is a CMake function that helps you invoke the code generator:
sen_generate_python(
TARGET <target>
[BASE_PATH base_path]
[STL_FILES [files...]]
[HLA_FOM_DIRS [directories...]]
[HLA_MAPPINGS_FILE file]
[GEN_HDR_FILES variable]
)
It works like the other code generation functions. There will be one output .py file per input file (STL or HLA), and the output folder structure will mimic that of the input.
Once you have your generated Python code, you will want to write the configuration Python file(s). There is another CMake function that helps you in generating the final YAML file:
sen_generate_yaml(
TARGET <target>
SCRIPT python_script
OUTPUT output_file
[DEPS [dependencies...]]
)
In the DEPS argument you need to set all the dependencies, and be sure to add the target that you
used to generate the Python code. This way, this function will automatically configure the
PYTHONPATH with the folders that host the generated code.
Keep in mind that the generated Python code and the generated YAML file are not meant to be kept under version control. The idea is to have a single source of truth: your config script for the data, and the STL (or HLA) files for the types.
If mypy is found, this function will run the checks on the script.
Obtaining external interfaces information¶
Sen provides the necessary functionality to obtain interfaces files (such as stls or HLA FOM
xmls) when consuming packages from outside your project.
The following CMake utility obtains interface-related properties from a target such as STL_FILES,
BASE_PATH or HLA_FOM_DIRS.
After calling this function, you will be able to fetch the INSTALL_STL_FILES, INSTALL_BASE_PATH
and INSTALL_HLA_FOM_DIRS properties who will contain the necessary paths and information for you
to generate code using the functions described above based on your needs.
A more detailed guide on this function and on the whole process of exporting and consuming external interfaces can be found in the following guides:
- How to export interfaces in Sen-based projects
- How to consume external interfaces in Sen-based projects
- How to generate CMake packages to export pre-built interfaces
Automatic configuration and installation of -config.cmake.in files¶
A -config.cmake.in file contains the configuration of a CMake package. In a nutshell, this files
contain the CMake code of a project that will be executed when you call find_package() to consume
it externally. Sen offers a small CMake helper who eases the installation process of this type of
files. This function will come in handy when a project contains several -config.cmake.in files in
different subdirectories of the project.
The function takes a list of directories who contain -config.cmake.in files and configures the
files so that they are generated and installed in your CMAKE_INSTALL_PREFIX directory. It will
also install the -config.cmake.in files found in the current list directory. This directory will
almost certainly match the directory where your install.cmake file is found, since this function
should only be used when generating a CMake install package.
More detail on functionality and information on when should this function be used can be found on the How to generate CMake packages to export pre-built interfaces guide.