KasperskyOS Community Edition 1.2

Building a KasperskyOS-based solution

This section contains the following information:

  • Description of the KasperskyOS-based solution build process.
  • Descriptions of the scripts, libraries and build templates provided in KasperskyOS Community Edition.
  • Information on how to use dynamic libraries in a KasperskyOS-based solution.

In this section

Building a solution image

Build process overview

Using CMake from the contents of KasperskyOS Community Edition

CMake libraries in KasperskyOS Community Edition

Building without CMake

Using dynamic libraries

Page top
[Topic cmake_build_solution]

Building a solution image

A KasperskyOS-based solution consists of system software (including the KasperskyOS kernel and Kaspersky Security Module) and application software integrated for operation within a software/hardware system.

For more details, refer to Structure and startup of a KasperskyOS-based solution.

System programs and application software

Programs are divided into two types according to their purpose:

  • System programs create the infrastructure for application software. For example, they facilitate hardware operations, support the IPC mechanism, and implement file systems and network protocols. System programs are included in KasperskyOS Community Edition. If necessary, you can develop your own system programs.
  • Application software is designed for interaction with a solution user and for performing user tasks. Application software is not included in KasperskyOS Community Edition.

Building programs during the solution build process

During a solution build, programs are divided into the following two types:

  • System programs provided as executable files in KasperskyOS Community Edition.
  • System programs or application software that requires linking to an executable file.

Programs that require linking are divided into the following types:

  • System programs that implement an IPC interface whose ready-to-use transport libraries are provided in KasperskyOS Community Edition.
  • Application software that implements its own IPC interface. To build this software, transport methods and types need to be generated by using the NK compiler.
  • Client programs that do not provide endpoints.

Building a solution image

KasperskyOS Community Edition provides an image of the KasperskyOS kernel and the executable files of some system programs and driver applications that are ready to use in a solution.

A specialized Einit program intended for starting all other programs, and a Kaspersky Security Module are built for each specific solution and are therefore not already provided in KasperskyOS Community Edition. Instead, the toolchain provided in KasperskyOS Community Edition includes the tools for building these resources.

The general step-by-step build scenario is described in the article titled Build process overview. A solution image can be built as follows:

  • [Recommended] Using scripts of the CMake build system, which is provided in KasperskyOS Community Edition.
  • [Without CMake] Using other automated build systems or manually with scripts and compilers provided in KasperskyOS Community Edition.
Page top
[Topic cmake_solution_image]

Build process overview

To build a solution image, the following is required:

  1. Prepare EDL, CDL and IDL descriptions of applications, an init description file (init.yaml by default), and files containing a description of the solution security policy (security.psl by default).

    When building with CMake, an EDL description can be generated by using the generate_edl_file() command.

  2. Generate *.edl.h files for all programs except the system programs provided in KasperskyOS Community Edition.
  3. For programs that implement their own IPC interface, generate code of the transport methods and types that are used for generating, sending, receiving and processing IPC messages.
  4. Build all programs that are part of the solution, and link them to the transport libraries of system programs or applications if necessary. To build applications that implement their own IPC interface, you will need the code containing transport methods and types that was generated at step 3.
    • When building with CMake, standard build commands are used for this purpose. The necessary cross-compilation configuration is done automatically.
    • When building without CMake, the cross compilers included in KasperskyOS Community Edition must be manually used for this purpose.
  5. Build the Einit initializing program.
    • When building with CMake, the Einit program is built during the solution image build process using the build_kos_qemu_image() and build_kos_hw_image() commands.
    • When building without CMake, the einit tool must be used to generate the code of the Einit program. Then the Einit application must be built using the cross compiler that is provided in KasperskyOS Community Edition.
  6. Build the Kaspersky Security Module.
  7. Create the solution image.

Example 1

For the basic hello example included in KasperskyOS Community Edition that contains one application that does not provide any services, the build scenario looks as follows:

Example 2

The echo example included in KasperskyOS Community Edition describes a basic case of interaction between two programs via an IPC mechanism. To set up this interaction, you will need to implement an interface with the Ping method on a server and put the Ping service into a new component (for example, Responder), and an instance of this component needs to be put into the EDL description of the Server program.

If a solution contains programs that utilize an IPC mechanism, the build scenario looks as follows:

Page top
[Topic cmake_common_build_scheme]

Using CMake from the contents of KasperskyOS Community Edition

To automate the process of preparing the solution image, you need to configure the CMake build system. You can base this system on the build system parameters used in the examples from KasperskyOS Community Edition.

CMakeLists.txt files use the standard CMake syntax, and commands and macros from libraries provided in KasperskyOS Community Edition.

Recommended structure of project directories

When creating a KasperskyOS-based solution, it is recommended to use the following directory structure in a project:

Example structure of project directories

example$ tree . ├── CMakeLists.txt ├── hello │ ├── CMakeLists.txt │ ├── src │ │ ├── hello.c ├── einit │ ├── CMakeLists.txt │ ├── src │ │ ├── init.yaml.in │ │ ├── security.psl.in ├── resources │ ├── Hello.idl │ ├── Hello.cdl │ ├── Hello.edl

Building a solution image

To build a solution image, you must use the cmake tool (the toolchain/bin/cmake executable file from KasperskyOS Community Edition).

Build script example:

build.sh

#!/bin/bash # Script to be run in the project root. # You can get information about the cmake tool run parameters # via the shell command cmake --help, and from # the official CMake documentation. TARGET="aarch64-kos" SDK_PREFIX="/opt/KasperskyOS-SDK" # Initialize the build system cmake \ -G "Unix Makefiles" \ -D CMAKE_BUILD_TYPE:STRING=Release \ -D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \ -S . \ -B build # Build # To build a solution image for QEMU, you must specify the target defined in the # NAME parameter of the CMake command build_kos_qemu_image() in the CMakeLists.txt file # for building the Einit program. # To build a solution image for the hardware platform, you must specify the target # defined in the NAME parameter of the CMake command build_kos_hw_image() in the # CMakeLists.txt file for building the Einit program. # To build a solution image for QEMU and start QEMU with this image, you must # specify the sim target. cmake --build build --target sim

In this section

CMakeLists.txt boot file

CMakeLists.txt files for building applications

CMakeLists.txt file for building the Einit program

init.yaml.in template

security.psl.in template

Page top
[Topic cmake_using_sdk_cmake]

CMakeLists.txt root file

The CMakeLists.txt boot file contains general build instructions for the entire solution.

The CMakeLists.txt boot file must contain the following commands:

  • cmake_minimum_required (VERSION 3.25) indicates the minimum supported version of CMake.

    For a KasperskyOS-based solution build, CMake version 3.25 or later is required.

    The required version of CMake is provided in KasperskyOS Community Edition and is used by default.

  • include (platform) connects the platform library of CMake.
  • initialize_platform() initializes the platform library.
  • project_header_default("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") sets the flags of the compiler and linker.
  • [Optional] Connect and configure packages for the provided system programs and drivers that need to be included in the solution:
    • A package is connected by using the find_package() command.
    • After connecting a package, you must add the package-related directories to the list of search directories by using the include_directories() command.
    • For some packages, you must also set the values of properties by using the set_target_properties() command.

    CMake descriptions of system programs and drivers provided in KasperskyOS Community Edition, and descriptions of their exported variables and properties are located in the corresponding files at /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/lib/cmake/<program name>/<program name>-config.cmake

  • The Einit initializing program must be built using the add_subdirectory(einit) command.
  • All applications to be built must be added by using the add_subdirectory(<program directory name>) command.

Example CMakeLists.txt boot file

CMakeLists.txt

cmake_minimum_required(VERSION 3.12) project (example) # Initializes the CMake library for the KasperskyOS SDK. include (platform) initialize_platform () project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") # Add package importing components for working with Virtual File System. # Components are imported from the following directory: /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/lib/cmake/vfs/vfs-config.cmake find_package (vfs REQUIRED COMPONENTS ENTITY CLIENT_LIB) include_directories (${vfs_INCLUDE}) # Add a package importing components for building an audit program and # connecting to it. find_package (klog REQUIRED) include_directories (${klog_INCLUDE}) # Build the Einit initializing program add_subdirectory (einit) # Build the hello application add_subdirectory (hello)
Page top
[Topic cmake_lists_root]

CMakeLists.txt files for building applications

The CMakeLists.txt file for building an application must contain the following commands:

  • include (platform/nk) connects the CMake library for working with the NK compiler.
  • project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") sets the flags of the compiler and linker.
  • An EDL description of a process class for a program can be generated by using the generate_edl_file() command.
  • If the program provides endpoints using an IPC mechanism, the following transport code must be generated:
    1. idl.h files are generated by the nk_build_idl_files() command
    2. cdl.h files are generated by the nk_build_cdl_files() command
    3. edl.h files are generated by the nk_build_edl_files() command
  • add_executable (<program name> "<path to the file containing the program source code>") adds the program build target.
  • add_dependencies (<program name> <name of the edl.h file build target>) adds a program build dependency on edl.h file generation.
  • target_link_libraries (<program name> <list of libraries>) determines the libraries that need to be linked with the program during the build.

    For example, if the program uses file I/O or network I/O, it must be linked with the ${vfs_CLIENT_LIB} transport library.

    CMake descriptions of system programs and drivers provided in KasperskyOS Community Edition, and descriptions of their exported variables and properties are located in the corresponding files at /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/lib/cmake/<program name>/<program name>-config.cmake

  • To automatically add descriptions of IPC channels to the init.yaml file when building a solution, you must define the EXTRA_CONNECTIONS property and assign it a value with descriptions of the relevant IPC channels.

    Please note the indentations at the beginning of strings in the EXTRA_CONNECTIONS property. These indentations are necessary to correctly insert values into the init.yaml file and must comply with its syntax requirements.

    Example of creating an IPC channel between a Client process and a Server process:

    set_target_properties (Client PROPERTIES EXTRA_CONNECTIONS " - target: Server id: server_connection")

    When building this solution, the description of this IPC channel will be automatically added to the init.yaml file when processing macros of the init.yaml.in template.

  • To automatically add a list of arguments for the main() function and a dictionary of environment variables to the init.yaml file when building a solution, you must define the EXTRA_ARGS and EXTRA_ENV properties and assign the appropriate values to them.

    Note the indentations at the beginning of strings in the EXTRA_ARGS and EXTRA_ENV properties. These indentations are necessary to correctly insert values into the init.yaml file and must comply with its syntax requirements.

    Example of sending the Client program the "-v" argument of the main() function and the environment variable VAR1 set to VALUE1:

    set_target_properties (Client PROPERTIES EXTRA_ARGS " - \"-v\"" EXTRA_ENV " VAR1: VALUE1")

    When building this solution, the description of the main() function argument and the environment variable value will be automatically added to the init.yaml file when processing macros of the init.yaml.in template.

Example CMakeLists.txt file for building a simple application

CMakeLists.txt

project (hello) # Tools for working with the NK compiler. include (platform/nk) # Set compile flags. project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") # Define the name of the project that includes the program. set (LOCAL_MODULE_NAME "example") # Define the application name. set (ENTITY_NAME "Hello") # Please note the contents of the init.yaml.in and security.psl.in templates # They define program names as ${LOCAL_MODULE_NAME}.${ENTITY_NAME} # Define the targets that will be used to create the generated files of the program. set (ENTITY_IDL_TARGET ${ENTITY_NAME}_idl) set (ENTITY_CDL_TARGET ${ENTITY_NAME}_cdl) set (ENTITY_EDL_TARGET ${ENTITY_NAME}_edl) # Define the name of the target that will be used to build the program. set (APP_TARGET ${ENTITY_NAME}_app) # Add the idl.h file build target. nk_build_idl_files (${ENTITY_IDL_TARGET} NK_MODULE ${LOCAL_MODULE_NAME} IDL "resources/Hello.idl" ) # Add the cdl.h file build target. nk_build_cdl_files (${ENTITY_CDL_TARGET} IDL_TARGET ${ENTITY_IDL_TARGET} NK_MODULE ${LOCAL_MODULE_NAME} CDL "resources/Hello.cdl") # Add the EDL file build target. The EDL_FILE variable is exported # and contains the path to the generated EDL file. generate_edl_file ( ${ENTITY_NAME} PREFIX ${LOCAL_MODULE_NAME} ) # Add the edl.h file build target. nk_build_edl_files (${ENTITY_EDL_TARGET} NK_MODULE ${LOCAL_MODULE_NAME} EDL ${EDL_FILE} ) # Define the target for the program build. add_executable (${APP_TARGET} "src/hello.c") # The program name in init.yaml and security.psl must match the name of the executable file set_target_properties (${APP_TARGET} PROPERTIES OUTPUT_NAME ${ENTITY_NAME}) # Libraries that are linked to the program during the build target_link_libraries ( ${APP_TARGET} PUBLIC ${vfs_CLIENT_LIB} # The program uses file I/O # and must be connected as a client to VFS )
Page top
[Topic cmake_lists_applied]

CMakeLists.txt file for building the Einit program

The CMakeLists.txt file for building the Einit initializing program must contain the following commands:

  • include (platform/image) connects the CMake library that contains the solution image build scripts.
  • project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") sets the flags of the compiler and linker.
  • Configure the packages of system programs and drivers that need to be included in the solution.
    • A package is connected by using the find_package () command.
    • For some packages, you must also set the values of properties by using the set_target_properties () command.

    CMake descriptions of system programs and drivers provided in KasperskyOS Community Edition, and descriptions of their exported variables and properties are located in the corresponding files at /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/lib/cmake/<program name>/<program name>-config.cmake

  • To automatically add descriptions of IPC channels between processes of system programs to the init.yaml file when building a solution, you must add these channels to the EXTRA_CONNECTIONS property for the corresponding programs.

    Please note the indentations at the beginning of strings in the EXTRA_CONNECTIONS property. These indentations are necessary to correctly insert values into the init.yaml file and must comply with its syntax requirements.

    For example, the VFS program does not have a channel for connecting to the Env program by default. To automatically add a description of this channel to the init.yaml file during a solution build, you must add the following call to the CMakeLists.txt file for building the Einit program:

    set_target_properties (${vfs_ENTITY} PROPERTIES EXTRA_CONNECTIONS " - target: env.Env id: {var: ENV_SERVICE_NAME, include: env/env.h}"

    When building this solution, the description of this IPC channel will be automatically added to the init.yaml file when processing macros of the init.yaml.in template.

  • To automatically add a list of arguments for the main() function and a dictionary of environment variables to the init.yaml file when building a solution, you must define the EXTRA_ARGS and EXTRA_ENV properties and assign the appropriate values to them.

    Note the indentations at the beginning of strings in the EXTRA_ARGS and EXTRA_ENV properties. These indentations are necessary to correctly insert values into the init.yaml file and must comply with its syntax requirements.

Example of sending the VfsEntity program the "-f fstab" argument of the main() function and the environment variable ROOTFS set to ramdisk0,0 / ext2 0:

set_target_properties (${vfs_ENTITY} PROPERTIES EXTRA_ARGS " - \"-f\" - \"fstab\"" EXTRA_ENV " ROOTFS: ramdisk0,0 / ext2 0")

When building this solution, the description of the main() function argument and the environment variable value will be automatically added to the init.yaml file when processing macros of the init.yaml.in template.

  • set(ENTITIES <full list of programs included in the solution>) defines the ENTITIES variable containing a list of executable files of all programs included in the solution.
  • One or both commands for building the solution image:

Example CMakeLists.txt file for building the Einit program

CMakeLists.txt

project (einit) # Connect the library containing solution image build scripts. include (platform/image) # Set compile flags. project_header_default ("STANDARD_GNU_11:YES" "STRICT_WARNINGS:NO") # Configure the VFS program. # By default, the VFS program is not mapped to a program implementing a block device. # If you need to use a block device, such as ata from the ata component, # you must define this device in the variable ${blkdev_ENTITY}_REPLACEMENT # For more information about exported variables and properties of the VFS program, # see /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/lib/cmake/vfs/vfs-config.cmake # find_package(ata) # set_target_properties (${vfs_ENTITY} PROPERTIES ${blkdev_ENTITY}_REPLACEMENT ${ata_ENTITY}) # In the simplest case, you do not need to interact with a drive. # For this reason, we set the value of the ${blkdev_ENTITY}_REPLACEMENT variable equal to an empty string set_target_properties (${vfs_ENTITY} PROPERTIES ${blkdev_ENTITY}_REPLACEMENT "") # Define the ENTITIES variable with a list of executable files of programs. # It is important to include all programs that are part of the project, except the Einit program. # Please note that the name of the executable file of a program must # match the name of the target indicated in add_executable() in the CMakeLists.txt file for building this program. set(ENTITIES ${vfs_ENTITY} Hello_app ) # Create the build target named kos-image, which is a solution image for the hardware platform. build_kos_hw_image (kos-image EINIT_ENTITY EinitHw CONNECTIONS_CFG "src/init.yaml.in" # template of the init.yaml file SECURITY_PSL "src/security.psl.in" # template of the security.psl file IMAGE_FILES ${ENTITIES} ) # Create the build target named kos-qemu-image, which is a solution image for QEMU. build_kos_qemu_image (kos-qemu-image EINIT_ENTITY EinitQemu CONNECTIONS_CFG "src/init.yaml.in" SECURITY_PSL "src/security.psl.in" IMAGE_FILES ${ENTITIES} )
Page top
[Topic cmake_lists_einit]

init.yaml.in template

The init.yaml.in template is used to automatically generate a part of the init.yaml file prior to building the Einit program using CMake tools.

When using the init.yaml.in template, you do not have to manually add descriptions of system programs and the IPC channels for connecting to them to the init.yaml file.

The init.yaml.in template must contain the following data:

  • Root entities key.
  • List of all applications included in the solution.
  • For applications that use an IPC mechanism, you must specify a list of IPC channels that connect this application to other applications.

    The IPC channels that connect this application to other applications are either indicated manually or specified in the CMakeLists.txt file for this application using the EXTRA_CONNECTIONS property.

    To specify a list of IPC channels that connect this application to system programs that are included in KasperskyOS Community Edition, the following macros are used:

    • @INIT_<program name>_ENTITY_CONNECTIONS@ – during the build, this is replaced with the list of IPC channels containing all system programs that are linked to the application. The target and id fields are filled according to the connect.yaml files from KasperskyOS Community Edition located in /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/include/<system program name>).

      This macro needs to be used if the application does not have connections to other applications but instead connects only to system programs. This macro adds the root connections key.

    • @INIT_<program name>_ENTITY_CONNECTIONS+@ – during the build, the list of IPC channels containing all system programs that are linked to the application is added to the manually defined list of IPC channels. This macro does not add the root connections key.

      This macro needs to be used if the application has connections to other applications that were manually indicated in the init.yaml.in template.

  • The @INIT_<program name>_ENTITY_CONNECTIONS@ and @INIT_<program name>_ENTITY_CONNECTIONS+@ macros also add the list of connections for each program defined in the EXTRA_CONNECTIONS property when building this program.
  • If you need to pass main() function arguments defined in the EXTRA_ARGS property to a program when building this program, you need to use the following macros:
    • @INIT_<program name>_ENTITY_ARGS@ – during the build, this is replaced with the list of arguments of the main() function defined in the EXTRA_ARGS property. This macro adds the root args key.
    • @INIT_<program name>_ENTITY_ARGS+@ – during the build, this macro adds the list of main() function arguments defined in the EXTRA_ARGS property to the list of manually defined arguments. This macro does not add the root args key.
  • If you need to pass the values of environment variables defined in the EXTRA_ENV property to a program when building this program, you need to use the following macros:
    • @INIT_<program name>_ENTITY_ENV@ – during the build, this is replaced with the dictionary of environment variables and their values defined in the EXTRA_ENV property. This macro adds the root env key.
    • @INIT_<program name>_ENTITY_ENV+@ – during the build, this macro adds the dictionary of environment variables and their values defined in the EXTRA_ENV property to the manually defined variables. This macro does not add the root env key.
  • @INIT_EXTERNAL_ENTITIES@ – during the build, this macro is replaced with the list of system programs linked to the application and their IPC channels, main() function arguments, and values of environment variables.

Example init.yaml.in template

init.yaml.in

entities: - name: ping.Client connections: # The "Client" program can query the "Server". - target: ping.Server id: server_connection @INIT_Client_ENTITY_CONNECTIONS+@ @INIT_Client_ENTITY_ARGS@ @INIT_Client_ENTITY_ENV@ - name: ping.Server @INIT_Server_ENTITY_CONNECTIONS@ @INIT_EXTERNAL_ENTITIES@

When building the Einit program from this template, the following init.yaml file will be generated:

init.yaml

entities: - name: ping.Client connections: # The "Client" program can query the "Server" - target: ping.Server id: server_connection - target: kl.VfsEntity id: {var: _VFS_CONNECTION_ID, include: vfs/defs.h} args: - "-v" env: VAR1: VALUE1 - name: ping.Server connections: - target: kl.VfsEntity id: {var: _VFS_CONNECTION_ID, include: vfs/defs.h} - name: kl.VfsEntity path: VFS args: - "-f" - "fstab" env: ROOTFS: ramdisk0,0 / ext2
Page top
[Topic cmake_yaml_templates]

security.psl.in template

The security.psl.in template is used to automatically generate a part of the security.psl file prior to building the Einit program using CMake tools.

The security.psl file contains part of the solution security policy description.

When using the security.psl.in template, you do not have to manually add EDL descriptions of system programs to the security.psl file.

The security.psl.in template must contain a manually created solution security policy description, including the following declarations:

  • Set the global parameters of a solution security policy
  • Include PSL files in a solution security policy description
  • Include EDL files of application software in a solution security policy description
  • Create security model objects
  • Bind methods of security models to security events
  • Create security audit profiles

To automatically include system programs, the @INIT_EXTERNAL_ENTITIES@ macro must be used.

Example security.psl.in template

security.psl.in

execute: kl.core.Execute use nk.base._ use EDL Einit use EDL kl.core.Core use EDL Client use EDL Server @INIT_EXTERNAL_ENTITIES@ /* Startup of programs is allowed */ execute { grant () } /* Sending and receiving requests, responses and errors is allowed. */ request { grant () } response { grant () } error { grant () } /* Queries via the security interface are ignored. */ security { grant () }
Page top
[Topic cmake_psl_templates]

CMake libraries in KasperskyOS Community Edition

This section contains a description of the libraries that are provided in KasperskyOS Community Edition for automatically building a KasperskyOS-based solution.

In this section

platform library

nk library

image library

Page top
[Topic cmake_libs]

platform library

The platform library contains the following commands:

  • initialize_platform() is the command for initializing the platform library.

    The initialize_platform() command can be called with the FORCE_STATIC parameter, which enables forced static linking of executable files:

    • By default, if the toolchain in the KasperskyOS SDK supports dynamic linking, the initialize_platform() command causes the -rdynamic flag to be used automatically for building all executable files defined via CMake add_executable() commands.
    • When calling initialize_platform (FORCE_STATIC) in the CMakeLists.txt root file, the toolchain supporting dynamic linking performs static linking of executable files.

    The initialize_platform() command can be called with the NO_NEW_VERSION_CHECK parameter, which disables the check for SDK updates and transmission of the SDK version to the Kaspersky server.

    To disable the check for SDK updates and transmission of SDK version data to the Kaspersky server, use the following call during the solution build: initialize_platform(NO_NEW_VERSION_CHECK). For more details about the data provision policy, see Data provision.

  • project_static_executable_header_default() is the command for enabling forced static linking of executable files defined via subsequent CMake add_executable() commands in one CMakeLists.txt file. The toolchain that supports dynamic linking performs static linking of these executable files.
  • platform_target_force_static() is the command for enabling forced static linking of an executable file defined via the CMake add_executable() command. The toolchain that supports dynamic linking performs static linking of this executable file. For example, if the CMake commands add_executable(client "src/client.c") and platform_target_force_static(client) are called, static linking is performed for the client program.
  • project_header_default() is the command for setting compile flags.

    Command parameters are defined in pairs consisting of a compile flag and its value: "FLAG_1:VALUE_1" "FLAG_2:VALUE_2" ... "FLAG_N:VALUE_N". The CMake platform library converts these pairs into compiler parameters. Frequently used compile flags for C and C++ compilers from the GCC set and the values of these flags are presented in the table below.

    Compile flags

    YES value

    NO value

    Default value

    STANDARD_ANSI

    The ISO C90 and 1998 ISO C++ standards are used.

    For C and C++ compilers, the value is converted into the parameter -ansi.

    The ISO C90 and 1998 ISO C++ standards are not used.

    STANDARD_ANSI:NO

    STANDARD_C99

    The ISO C99 standard is used.

    For a C compiler, the value is converted into the parameter -std=c99.

    The ISO C99 standard is not used.

    STANDARD_C99:NO

    STANDARD_GNU_C99

    The ISO C99 standard with GNU extensions is used.

    For a C compiler, the value is converted into the parameter -std=gnu99.

    The ISO C99 standard with GNU extensions is not used.

    STANDARD_GNU_C99:NO

    STANDARD_11

    The ISO C11 and 2011 ISO C++ standards are used.

    For a C compiler, the value is converted into the parameter -std=c11 or -std=c1x depending on the compiler version.

    For a C++ compiler, the value is converted into the parameter -std=c++11 or -std=c++0x depending on the compiler version.

    The ISO C11 and 2011 ISO C++ standards are not used.

    STANDARD_11:NO

    STANDARD_GNU_11

    The ISO C11 and 2011 ISO C++ standards with GNU extensions are used.

    For a C compiler, the value is converted into the parameter -std=gnu1x or -std=gnu11 depending on the compiler version.

    For a C++ compiler, the value is converted into the parameter -std=gnu++0x or -std=gnu++11 depending on the compiler version.

    The ISO C11 and 2011 ISO C++ standards with GNU extensions are not used.

    STANDARD_GNU_11:NO

    STANDARD_14

    The 2014 ISO C++ standard is used.

    For a C++ compiler, the value is converted into the parameter -std=c++14.

    The 2014 ISO C++ standard is not used.

    STANDARD_14:NO

    STANDARD_GNU_14

    The 2014 ISO C++ standard with GNU extensions is used.

    For a C++ compiler, the value is converted into the parameter -std=gnu++14.

    The 2014 ISO C++ standard with GNU extensions is not used.

    STANDARD_GNU_14:NO

    STANDARD_17

    The ISO C17 and 2017 ISO C++ standards are used.

    For a C compiler, the value is converted into the parameter -std=c17.

    For a C++ compiler, the value is converted into the parameter -std=c++17.

    The ISO C17 and 2017 ISO C++ standards are not used.

    STANDARD_17:NO

    STANDARD_GNU_17

    The ISO C17 and 2017 ISO C++ standards with GNU extensions are used.

    For a C compiler, the value is converted into the parameter -std=gnu17.

    For a C++ compiler, the value is converted into the parameter -std=gnu++17.

    The ISO C17 and 2017 ISO C++ standards with GNU extensions are not used.

    STANDARD_GNU_17:NO

    STRICT_WARNINGS

    Warnings are enabled for the detection of potential issues and errors in code written in C and C++.

    For C and C++ compilers, the value is converted into the following parameters: -Wcast-qual, -Wcast-align, -Wundef.

    For a C compiler, the parameter -Wmissing-prototypes is additionally used.

    Warnings are disabled.

    STRICT_WARNINGS:YES

    If compiler flags in the format STANDART_* are not defined through command parameters, the parameter STANDARD_GNU_17:YES is used by default.

When using the initialize_platform(FORCE_STATIC), project_static_executable_header_default() and platform_target_force_static() commands, you may encounter linking errors if the static variants of the required libraries are missing (for example, if they were not built or are not included in the KasperskyOS SDK). Even if the static variants of the required libraries are available, these errors may still occur because the build system searches for the dynamic variants of required libraries by default instead of the expected static variants when using the initialize_platform(FORCE_STATIC), project_static_executable_header_default() and platform_target_force_static() commands. To avoid errors, first make sure that the static variants are available. Then configure the build system to search for static libraries (although this capability may not be available for some libraries), or explicitly define linking with static libraries.

Examples of configuring the build system to search for static libraries:

set (fmt_USE_STATIC ON) find_package (fmt REQUIRED) set (fdn_USE_STATIC ON) find_package (fdn REQUIRED) set (sqlite_wrapper_USE_STATIC ON) find_package (sqlite_wrapper REQUIRED)

Example that explicitly defines linking with a static library:

target_link_libraries(${PROJECT_NAME} PUBLIC logger::logger-static)

For more details about using dynamic libraries, see "Using dynamic libraries".

These commands are used in CMakeLists.txt files for the Einit program and application software.

Page top
[Topic cmake_platform_lib]

nk library

This section contains a description of the commands and macros of the CMake library for working with the NK compiler.

In this section

generate_edl_file()

nk_build_idl_files()

nk_build_cdl_files()

nk_build_edl_files()

Generating transport code for development in C++

Page top
[Topic cmake_nk_lib]

generate_edl_file()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/nk2.cmake.

generate_edl_file(NAME ...)

This command generates an EDL file containing a description of the process class.

Parameters:

  • NAME – name of the EDL file being created. Required parameter.
  • PREFIX – parameter in which you need to specify the name of the process class, excluding the name of the EDL file. For example, if the name of the process class for which the EDL file is being created is defined as kl.core.NameServer, the PREFIX parameter must pass the value kl.core.
  • EDL_COMPONENTS – name of the component and its instance that will be included in the EDL file. For example: EDL_COMPONENTS "env: kl.Env". To include multiple components, you need to use multiple EDL_COMPONENTS parameters.
  • SECURITY – qualified name of the security interface method that will be included in the EDL file.
  • OUTPUT_DIR – directory in which the EDL file will be created. The default directory is ${CMAKE_CURRENT_BINARY_DIR}.

As a result of this command, the EDL_FILE variable is exported and contains the path to the generated EDL file.

Example call:

generate_edl_file(${ENTITY_NAME} EDL_COMPONENTS "env: kl.Env")

For an example of using this command, see the article titled "CMakeLists.txt files for building application software".

Page top
[Topic cmake_generate_edl]

nk_build_idl_files()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/nk2.cmake.

nk_build_idl_files(NAME ...)

This command creates a CMake target for generating .idl.h files for one or more defined IDL files using the NK compiler.

Parameters:

  • NAME – name of the CMake target for building .idl.h files. If a target has not yet been created, it will be created by using add_library() with the specified name. Required parameter.
  • NOINSTALL – if this option is specified, files will only be generated in the working directory and will not be installed in global directories: ${CMAKE_BINARY_DIR}/_headers_ ${CMAKE_BINARY_DIR}/_headers_/${PROJECT_NAME}.
  • NK_MODULE – parameter in which you need to specify the package name, excluding the name of the IDL file. For example, if the package name in the IDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • WORKING_DIRECTORY – working directory for calling the NK compiler, which is ${CMAKE_CURRENT_BINARY_DIR} by default.
  • DEPENDS – additional build targets on which the IDL file depends.

    To add multiple targets, you need to use multiple DEPENDS parameters.

  • IDL – path to the IDL file for which the idl.h file is being generated. Required parameter.

    To add multiple IDL files, you need to use multiple IDL parameters.

    If one IDL file imports another IDL file, idl.h files need to be generated in the order necessary for compliance with dependencies (with the most deeply nested first).

  • NK_FLAGS – additional flags for the NK compiler.

Example call:

nk_build_idl_files (echo_idl_files NK_MODULE "echo" IDL "resources/Ping.idl")

For an example of using this command, see the article titled "CMakeLists.txt files for building application software".

Page top
[Topic cmake_build_idl]

nk_build_cdl_files()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/nk2.cmake.

nk_build_cdl_files(NAME ...)

This command creates a CMake target for generating .cdl.h files for one or more defined CDL files using the NK compiler.

Parameters:

  • NAME – name of the CMake target for building .cdl.h files. If a target has not yet been created, it will be created by using add_library() with the specified name. Required parameter.
  • NOINSTALL – if this option is specified, files will only be generated in the working directory and are not installed in global directories: ${CMAKE_BINARY_DIR}/_headers_ ${CMAKE_BINARY_DIR}/_headers_/${PROJECT_NAME}.
  • IDL_TARGET – target when building .idl.h files for IDL files containing descriptions of endpoints provided by components described in CDL files.
  • NK_MODULE – parameter in which you need to specify the component name, excluding the name of the CDL file. For example, if the component name in the CDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • WORKING_DIRECTORY – working directory for calling the NK compiler, which is ${CMAKE_CURRENT_BINARY_DIR} by default.
  • DEPENDS – additional build targets on which the CDL file depends.

    To add multiple targets, you need to use multiple DEPENDS parameters.

  • CDL – path to the CDL file for which the .cdl.h file is being generated. Required parameter.

    To add multiple CDL files, you need to use multiple CDL parameters.

  • NK_FLAGS – additional flags for the NK compiler.

Example call:

nk_build_cdl_files (echo_cdl_files IDL_TARGET echo_idl_files NK_MODULE "echo" CDL "resources/Ping.cdl")

For an example of using this command, see the article titled "CMakeLists.txt files for building application software".

Page top
[Topic cmake_build_cdl]

nk_build_edl_files()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/nk2.cmake.

nk_build_edl_files(NAME ...)

This command creates a CMake target for generating an .edl.h file for one defined EDL file using the NK compiler.

Parameters:

  • NAME – name of the CMake target for building an .edl.h file. If a target has not yet been created, it will be created by using add_library() with the specified name. Required parameter.
  • NOINSTALL – if this option is specified, files will only be generated in the working directory and are not installed in global directories: ${CMAKE_BINARY_DIR}/_headers_ ${CMAKE_BINARY_DIR}/_headers_/${PROJECT_NAME}.
  • CDL_TARGET – target when building .cdl.h files for CDL files containing descriptions of components of the EDL file for which the build is being performed.
  • IDL_TARGET – target when building .idl.h files for IDL files containing descriptions of interfaces of the EDL file for which the build is being performed.
  • NK_MODULE – parameter in which you need to specify the name of the process class, excluding the name of the EDL file. For example, if the process class name in the EDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • WORKING_DIRECTORY – working directory for calling the NK compiler, which is ${CMAKE_CURRENT_BINARY_DIR} by default.
  • DEPENDS – additional build targets on which the EDL file depends.

    To add multiple targets, you need to use multiple DEPENDS parameters.

  • EDL – path to the EDL file for which the edl.h file is being generated. Required parameter.
  • NK_FLAGS – additional flags for the NK compiler.

Example calls:

nk_build_edl_files (echo_server_edl_files CDL_TARGET echo_cdl_files NK_MODULE "echo" EDL "resources/Server.edl") nk_build_edl_files (echo_client_edl_files NK_MODULE "echo" EDL "resources/Client.edl")

For an example of using this command, see the article titled "CMakeLists.txt files for building application software".

Page top
[Topic cmake_build_edl]

Generating transport code for development in C++

The CMake commands add_nk_idl(), add_nk_cdl() and add_nk_edl() are used to generate transport proxy objects and stubs using the nkppmeta compiler when building a solution.

In this section

add_nk_idl()

add_nk_cdl()

add_nk_edl()

Page top
[Topic cmake_cpp]

add_nk_idl()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>/toolchain/share/cmake/Modules/platform/nk2.cmake.

add_nk_idl(NAME IDL_FILE ...)

This command creates a CMake target for generating a *.idl.cpp.h header file for a defined IDL file using the nkppmeta compiler. The command also creates a library containing the transport code for the defined interface. To link to this library, use the bind_nk_targets() command.

The generated header files contain a C++ representation for the interface and data types described in the IDL file, and the methods required for use of proxy objects and stubs.

Parameters:

  • NAME — name of the CMake target. Required parameter.
  • IDL_FILE — path to the IDL file. Required parameter.
  • NK_MODULE – parameter in which you need to specify the package name, excluding the name of the IDL file. For example, if the package name in the IDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • LANG – parameter in which you need to specify the CXX value.

Example call:

add_nk_idl (ANIMAL_IDL "${CMAKE_SOURCE_DIR}/resources/Animal.idl" NK_MODULE "example" LANG "CXX")
Page top
[Topic add_nk_idl]

add_nk_cdl()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>/toolchain/share/cmake/Modules/platform/nk2.cmake.

add_nk_cdl(NAME CDL_FILE ...)

This command creates a CMake target for generating a *.cdl.cpp.h file for a defined CDL file using the nkppmeta compiler. The command also creates a library containing the transport code for the defined component. To link to this library, use the bind_nk_targets() command.

The *.cdl.cpp.h file contains the tree of embedded components and endpoints provided by the component described in the CDL file.

Parameters:

  • NAME — name of the CMake target. Required parameter.
  • CDL_FILE — path to the CDL file. Required parameter.
  • NK_MODULE – parameter in which you need to specify the component name, excluding the name of the CDL file. For example, if the component name in the CDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • LANG – parameter in which you need to specify the CXX value.

Example call:

add_nk_cdl (CAT_CDL "${CMAKE_SOURCE_DIR}/resources/Cat.cdl" NK_MODULE "example" LANG "CXX")
Page top
[Topic add_nk_cdl]

add_nk_edl()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>/toolchain/share/cmake/Modules/platform/nk2.cmake.

add_nk_edl(NAME EDL_FILE ...)

This command creates a CMake target for generating a *.edl.cpp.h file for a defined EDL file using the nkppmeta compiler. The command also creates a library containing the transport code for the server or client program. To link to this library, use the bind_nk_targets() command.

The *.edl.cpp.h file contains the tree of embedded components and endpoints provided by the process class described in the EDL file.

Parameters:

  • NAME — name of the CMake target. Required parameter.
  • EDL_FILE — path to the EDL file. Required parameter.
  • NK_MODULE – parameter in which you need to specify the name of the process class, excluding the name of the EDL file. For example, if the process class name in the EDL description is defined as kl.core.NameServer, the kl.core value must be passed in the NK_MODULE parameter.
  • LANG – parameter in which you need to specify the CXX value.

Example call:

add_nk_edl (SERVER_EDL "${CMAKE_SOURCE_DIR}/resources/Server.edl" NK_MODULE "example" LANG "CXX")
Page top
[Topic add_nk_edl]

image library

This section contains a description of the commands and macros of the CMake library named image that is included in KasperskyOS Community Edition and contains solution image build scripts.

In this section

build_kos_qemu_image()

build_kos_hw_image()

Page top
[Topic cmake_image_lib]

build_kos_qemu_image()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/image.cmake.

build_kos_qemu_image(NAME ...)

The command creates a CMake target for building a solution image for QEMU.

Parameters:

  • NAME – name of the CMake target for building a solution image. Required parameter.
  • PERFCNT_KERNEL – use the kernel with performance counters if it is available in KasperskyOS Community Edition.
  • EINIT_ENTITY – name of the executable file that will be used to start the Einit program.
  • EXTRA_XDL_DIR – additional directories to include when building the Einit program.
  • CONNECTIONS_CFG – path to the init.yaml file or init.yaml.in template.
  • SECURITY_PSL – path to the security.psl file or security.psl.in template.
  • KLOG_ENTITY – target for building the Klog system program, which is responsible for the security audit. If the target is not specified, the audit is not performed.
  • QEMU_FLAGS – additional flags for running QEMU.
  • IMAGE_BINARY_DIR_BIN – directory for the final image and other artifacts. It matches CMAKE_CURRENT_BINARY_DIR by default.
  • NO_AUTO_BLOB_CONTAINER – solution image will not include the BlobContainer program that is required for working with dynamic libraries in shared memory. For more details, refer to "Including the BlobContainer system program in a KasperskyOS-based solution".
  • PACK_DEPS, PACK_DEPS_COPY_ONLY, PACK_DEPS_LIBS_PATH, and PACK_DEPS_COPY_TARGET – parameters that define the method used to add dynamic libraries to the solution image.
  • IMAGE_FILES – executable files of applications and system programs (except the Einit program) and any other files to be added to the ROMFS image.

    To add multiple applications or files, you can use multiple IMAGE_FILES parameters.

  • <path to files> – free parameters like IMAGE_FILES.

Example call:

build_kos_qemu_image ( kos-qemu-image EINIT_ENTITY EinitQemu CONNECTIONS_CFG "src/init.yaml.in" SECURITY_CFG "src/security.cfg.in" IMAGE_FILES ${ENTITIES})

For an example of using this command, see the article titled "CMakeLists.txt files for building the Einit program".

Page top
[Topic cmake_build_qemu]

build_kos_hw_image()

This command is declared in the file /opt/KasperskyOS-Community-Edition-<version>toolchain/share/cmake/Modules/platform/image.cmake.

build_kos_hw_image(NAME ...)

The command creates a CMake target for building a solution image for the hardware platform.

Parameters:

  • NAME – name of the CMake target for building a solution image. Required parameter.
  • PERFCNT_KERNEL – use the kernel with performance counters if it is available in KasperskyOS Community Edition.
  • EINIT_ENTITY – name of the executable file that will be used to start the Einit program.
  • EXTRA_XDL_DIR – additional directories to include when building the Einit program.
  • CONNECTIONS_CFG – path to the init.yaml file or init.yaml.in template.
  • SECURITY_PSL – path to the security.psl file or security.psl.in template.
  • KLOG_ENTITY – target for building the Klog system program, which is responsible for the security audit. If the target is not specified, the audit is not performed.
  • IMAGE_BINARY_DIR_BIN – directory for the final image and other artifacts. The default directory is CMAKE_CURRENT_BINARY_DIR.
  • NO_AUTO_BLOB_CONTAINER – solution image will not include the BlobContainer program that is required for working with dynamic libraries in shared memory. For more details, refer to "Including the BlobContainer system program in a KasperskyOS-based solution".
  • PACK_DEPS, PACK_DEPS_COPY_ONLY, PACK_DEPS_LIBS_PATH, and PACK_DEPS_COPY_TARGET – parameters that define the method used to add dynamic libraries to the solution image.
  • IMAGE_FILES – executable files of applications and system programs (except the Einit program) and any other files to be added to the ROMFS image.

    To add multiple applications or files, you can use multiple IMAGE_FILES parameters.

  • <path to files> – free parameters like IMAGE_FILES.

Example call:

build_kos_hw_image ( kos-image EINIT_ENTITY EinitHw CONNECTIONS_CFG "src/init.yaml.in" SECURITY_CFG "src/security.cfg.in" IMAGE_FILES ${ENTITIES})

For an example of using this command, see the article titled "CMakeLists.txt files for building the Einit program".

Page top
[Topic cmake_build_hw]

Building without CMake

This section contains a description of the scripts, tools, compilers and build templates provided in KasperskyOS Community Edition.

These tools can be used:

  • In other build systems.
  • To perform individual steps of the build.
  • To analyze the build specifications and write a custom build system.

The general scenario for building a solution image is described in the article titled Build process overview.

In this section

Tools for building a solution

Example build without using CMake

Page top
[Topic cmake_no_cmake_build]

Tools for building a solution

This section contains a description of the scripts, tools, compilers and build templates provided in KasperskyOS Community Edition.

In this section

Build scripts and tools

Cross compilers

Page top
[Topic solution_build_tools]

Build scripts and tools

KasperskyOS Community Edition includes the following build scripts and tools:

  • nk-gen-c

    The NK compiler (nk-gen-c) generates transport code based on the IDL, CDL, and EDL descriptions. Transport code is needed for generating, sending, receiving, and processing IPC messages.

  • nk-psl-gen-c

    The nk-psl-gen-c compiler generates the C-language source code of the Kaspersky Security Module based on the solution security policy description and the IDL, CDL, and EDL descriptions. The nk-psl-gen-c compiler also generates the C-language source code of solution security policy tests based on solution security policy tests in PAL.

  • einit

    The einit tool automates the creation of code for the Einit initializing program. This program is the first to start when KasperskyOS is loaded. Then it starts all other programs and creates IPC channels between them.

  • makekss

    The makekss script creates the Kaspersky Security Module.

  • makeimg

    The makeimg script creates the final boot image of the KasperskyOS-based solution with all programs to be started and the Kaspersky Security Module.

Page top
[Topic build_utilities_and_scripts]

nk-gen-c

The NK compiler (nk-gen-c) generates transport code based on the IDL, CDL, and EDL descriptions.

The nk-gen-c compiler receives the IDL, CDL or EDL file and creates the following files:

  • A *.*dl.h file containing the transport code.
  • A *.*dl.nk.d file that lists the created *.*dl.h file's dependencies on the IDL and CDL files. The *.*dl.nk.d file is created for the build system.

Syntax of the shell command for starting the nk-gen-c compiler:

nk-gen-c [-I <PATH>]... [-o <PATH>] [--types] [--interface] [--endpoints] [--client] [--server] [--extended-errors] [--trace-client-ipc {headers|dump}] [--trace-server-ipc {headers|dump}] [--ipc-trace-method-filter <METHOD>[,METHOD]...] [-h|--help] [--version] <FILE>

Basic parameters:

  • FILE

    Path to the IDL, CDL, or EDL file for which you need to generate transport code.

  • -I <PATH>

    These parameters are used to define the paths to directories containing the auxiliary files required for generating transport code. (The auxiliary files are located in the sysroot-*-kos/include directory from the KasperskyOS SDK.) These parameters can also be used to define the paths to directories containing IDL and CDL files that are referenced by the file defined via the FILE parameter.

  • -o <PATH>

    Path to an existing directory where the created files will be placed. If this parameter is not specified, the created files will be put into the current directory.

  • -h|--help

    Prints the Help text.

  • --version

    Prints the version of the nk-gen-c compiler.

  • --extended-errors

    This parameter provides the capability to use interface methods with one or more error parameters of user-defined IDL types. (The client works with error parameters like it works with output parameters.)

    If the --extended-errors parameter is not specified, you can use interface methods only with one status error parameter of the IDL type UInt16 whose value is passed to the client via return code of the interface method. This mechanism is obsolete and will no longer be supported in the future, so you are advised to always specify the --extended-errors parameter.

Selective generation of transport code

To reduce the volume of generated transport code, you can use flags for selective generation of transport code. For example, you can use the --server flag for programs that implement endpoints, and use the --client flag for programs that utilize the endpoints.

If no selective generation flag for transport code is specified, the nk-gen-c compiler generates transport code with all possible methods and types for the defined IDL, CDL, or EDL file.

Flags for selective generation of transport code for an IDL file:

  • --types

    The transport code includes the types corresponding to the IDL types from the defined IDL file, and the types corresponding to this file's imported IDL types that are used in IDL types of the defined IDL file. However, the types corresponding to imported IDL constants and to the aliases of imported IDL types are not included in the *.idl.h file. To use the types corresponding to imported IDL constants and to the aliases of imported IDL types, you must separately generate the transport code for the IDL files from which you are importing.

  • --interface

    The transport code corresponds to the --types flag, and includes the types of structures of the constant part of IPC requests and IPC responses for interface methods whose signatures are specified in the defined IDL file. In addition, the transport code contains constants indicating the sizes of IPC message arenas.

  • --client

    The transport code corresponds to the --interface flag, and includes the proxy object type, proxy object initialization method, and the interface methods specified in the defined IDL file.

  • --server

    The transport code corresponds to the --interface flag, and includes the types and dispatcher (dispatch method) used to process IPC requests corresponding to the interface methods specified in the defined IDL file.

Flags for selective generation of transport code for a CDL or EDL file:

  • --types

    The transport code includes the types corresponding to the IDL types that are used in the method parameters of endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file).

  • --endpoints

    The transport code corresponds to the --types flag, and includes the types of structures of the constant part of IPC requests and IPC responses for the methods of endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file). In addition, the transport code contains constants indicating the sizes of IPC message arenas.

  • --client

    The transport code corresponds to the --types flag, and includes the types of structures of the constant part of IPC requests and IPC responses for the methods of endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file). In addition, the transport code contains constants indicating the sizes of IPC message arenas, and the proxy object types, proxy object initialization methods, and methods of endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file).

  • --server

    The transport code corresponds to the --types flag, and includes the types and dispatchers (dispatch methods) used to process IPC requests corresponding to the endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file). In addition, the transport code contains constants indicating the sizes of IPC message arenas, and the stub types, stub initialization methods, and the types of structures of the constant part of IPC requests and IPC responses for the methods of endpoints provided by the component (for the defined CDL file) or process class (for the defined EDL file).

Printing diagnostic information about sending and receiving IPC messages

Transport code can generate diagnostic information about sending and receiving IPC messages and print this data via standard error. To generate transport code with these capabilities, use the following parameters:

  • --trace-client-ipc {headers|dump}

    The code for printing diagnostic information is executed directly before the Call() system call is executed and immediately after it is executed. If the headers value is specified, the diagnostic information includes the endpoint method ID (MID), the endpoint ID (RIID), the size of the constant part of the IPC message (in bytes), the contents of the IPC message arena handle, the size of the IPC message arena (in bytes), and the size of the utilized part of the IPC message arena (in bytes). If the dump value is specified, the diagnostic information additionally includes the contents of the constant part and arena of the IPC message in hexadecimal format.

    When using this parameter, you must either specify the selective generation flag for transport code --client or refrain from specifying a selective generation flag for transport code.

  • --trace-server-ipc {headers|dump}

    The code for printing diagnostic information is executed directly before calling the function that implements the interface method, and immediately after the completion of this function. In other words, it is executed when the dispatcher (dispatch method) is called in the interval between execution of the Recv() and Reply() system calls. If the headers value is specified, the diagnostic information includes the endpoint method ID (MID), the endpoint ID (RIID), the size of the constant part of the IPC message (in bytes), the contents of the IPC message arena handle, the size of the IPC message arena (in bytes), and the size of the utilized part of the IPC message arena (in bytes). If the dump value is specified, the diagnostic information additionally includes the contents of the constant part and arena of the IPC message in hexadecimal format.

    When using this parameter, you must either specify the selective generation flag for transport code --server or refrain from specifying a selective generation flag for transport code.

  • --ipc-trace-method-filter <METHOD>[,METHOD]...

    Diagnostic information is printed if only the defined interface methods are called. For the METHOD value, you can use the interface method name or the construct <package name>:<interface method name>. The package name and interface method name are specified in the IDL file.

    If this parameter is not specified, diagnostic information is printed when any interface method is called.

    This parameter can be specified multiple times. For example, you can specify all required interface methods in one parameter or specify each required interface method in a separate parameter.

Page top
[Topic nkgenc]

nk-psl-gen-c

The nk-psl-gen-c compiler generates the C-language source code of the Kaspersky Security Module based on the solution security policy description and the IDL, CDL, and EDL descriptions. This code is used by the makekss script.

The nk-psl-gen-c compiler can also generate the C-language source code of solution security policy tests based on solution security policy tests in PAL.

Syntax of the shell command for starting the nk-psl-gen-c compiler:

nk-psl-gen-c [{-I|--include-dir} <DIR>]... [{-o|--output} <FILE>] [--out-tests <FILE>] [{-t|--tests} <ARG>] [{-a|--audit} <FILE>] [-h|--help] [--version] <INPUT>

Parameters:

  • INPUT

    Path to the top-level file of the solution security policy description. This is normally the security.psl file.

  • {-I|--include-dir} <DIR>

    These parameters are used to define the paths to directories containing IDL, CDL, and EDL files pertaining to the solution, and the paths to directories containing auxiliary files from the KasperskyOS SDK (common, sysroot-*-kos/include, toolchain/include).

  • {-o|--output} <FILE>

    Path to the file that will save the source code of the Kaspersky Security Module and (optionally) the source code of solution security policy tests. The path must include existing directories.

  • --out-tests <FILE>

    Path to the file that will save the source code of the solution security policy tests.

  • {-t|--tests} <ARG>

    Defines whether the source code of solution security policy tests must be generated. ARG can take the following values:

    • skip: – source code of tests is not generated. This value is used by default if the -t, --tests <ARG> parameter is not specified.
    • generate: – source code of tests is generated. If the source code of tests is generated, you are advised to use the --out-tests <FILE> parameter. Otherwise, the source code of tests will be saved in the same file containing the source code of the Kaspersky Security Module, which may lead to errors during the build.
  • {-a|--audit} <FILE>

    Path to the file that will save the C-language source code of the audit decoder.

  • -h|--help

    Prints the Help text.

  • --version

    Prints the version of the nk-psl-gen-c compiler.

Page top
[Topic nkpslgenc]

einit

The einit tool automates the creation of code for the Einit initializing program.

The einit tool receives the solution initialization description (the init.yaml file by default) and EDL, CDL and IDL descriptions, and creates a file containing the source code of the Einit initializing program. Then the Einit program must be built using the C-language cross compiler that is provided in KasperskyOS Community Edition.

Syntax for using the einit tool:

einit -I PATH -o PATH [--help] FILE

Parameters:

  • FILE

    Path to the init.yaml file.

  • -I PATH

    Path to the directory containing the auxiliary files (including EDL, CDL and IDL descriptions) required for generating the initializing program. By default, these files are located in the directory /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos/include.

  • -o, --out-file PATH

    Path to the created .c file containing the code of the initializing program.

  • -h, --help

    Displays the Help text.

Page top
[Topic einit_tool]

makekss

The makekss script creates the Kaspersky Security Module.

The script calls the nk-psl-gen-c compiler to generate the source code of the security module, then compiles the resulting code by calling the C compiler that is provided in KasperskyOS Community Edition.

The script creates the security module from the solution security policy description.

Syntax for using the makekss script:

makekss --target=ARCH --module=PATH --with-nk="PATH" --with-nktype="TYPE" --with-nkflags="FLAGS" [--output="PATH"][--help][--with-cc="PATH"][--with-cflags="FLAGS"] FILE

Parameters:

  • FILE

    Path to the top-level file of the solution security policy description.

  • --target=ARCH

    Processor architecture for which the build is intended.

  • --module=-lPATH

    Path to the ksm_kss library. This key is passed to the C compiler for linking to this library.

  • --with-nk=PATH

    Path to the nk-psl-gen-c compiler that will be used to generate the source code of the security module. By default, the compiler is located in /opt/KasperskyOS-Community-Edition-<version>/toolchain/bin/nk-psl-gen-c.

  • --with-nktype="TYPE"

    Indicates the type of NK compiler that will be used. To use the nk-psl-gen-c compiler, indicate the psl type.

  • --with-nkflags="FLAGS"

    Parameters used when calling the nk-psl-gen-c compiler.

    The nk-psl-gen-c compiler will require access to all EDL, CDL and IDL descriptions. To enable the nk-psl-gen-c compiler to find these descriptions, you need to pass the paths to these descriptions in the --with-nkflags parameter by using the -I switch of the nk-psl-gen-c compiler.

  • --output=PATH

    Path to the created security module file.

  • --with-cc=PATH

    Path to the C compiler that will be used to build the security module. The compiler provided in KasperskyOS Community Edition is used by default.

  • --with-cflags=FLAGS

    Parameters used when calling the C compiler.

  • -h, --help

    Displays the Help text.

Page top
[Topic makekss]

makeimg

The makeimg script creates the final boot image of the KasperskyOS-based solution with all executable files of programs and the Kaspersky Security Module.

The script receives a list of files, including the executable files of all applications that need to be added to ROMFS of the loaded image, and creates the following files:

  • Solution image
  • Solution image without character tables (.stripped)
  • Solution image with debug character tables (.dbg.syms)

Syntax for using the makeimg script:

makeimg --target=ARCH --sys-root=PATH --with-toolchain=PATH --ldscript=PATH --img-src=PATH --img-dst=PATH --with-init=PATH [--with-extra-asflags=FLAGS][--with-extra-ldflags=FLAGS][--help] FILES

Parameters:

  • FILES

    List of paths to files, including the executable files of all applications that need to be added to ROMFS.

    The security module (ksm.module) must be explicitly specified, or else it will not be included in the solution image. The Einit application does not need to be indicated because it will be automatically included in the solution image.

  • --target=ARCH

    Architecture for which the build is intended.

  • --sys-root=PATH

    Path to the root directory sysroot. By default, this directory is located in /opt/KasperskyOS-Community-Edition-version/sysroot-aarch64-kos/.

  • --with-toolchain=PATH

    Path to the set of auxiliary tools required for the solution build. By default, these tools are located in /opt/KasperskyOS-Community-Edition-<version>/toolchain/.

  • --ldscript=PATH

    Path to the linker script required for the solution build. By default, this script is located in /opt/KasperskyOS-Community-Edition-<version>/libexec/aarch64-kos/.

  • --img-src=PATH

    Path to the precompiled KasperskyOS kernel. By default, the kernel is located in /opt/KasperskyOS-Community-Edition-<version>/libexec/aarch64-kos/.

  • --img-dst=PATH

    Path to the created image file.

  • --with-init=PATH

    Path to the executable file of the Einit initializing program.

  • --with-extra-asflags=FLAGS

    Additional flags for the AS Assembler.

  • --with-extra-ldflags=FLAGS

    Additional flags for the LD Linker.

  • -h, --help

    Displays the Help text.

Page top
[Topic makeimg]

Cross compilers

The toolchain provided in the KasperskyOS SDK includes one or more GCC compilers. The toolchain/bin directory contains the following files:

  • Executable files of compilers (for example, x86_64-pc-kos-gcc, arm-kos-g++)
  • Executable files of linkers (for example, x86_64-pc-kos-ld, arm-kos-ld)
  • Executable files of assemblers (for example, x86_64-pc-kos-as, arm-kos-as)

In addition to standard macros, an additional macro __KOS__=1 is defined in GCC. Use of this macro lets you simplify porting of the software code to KasperskyOS, and also simplifies development of platform-independent programs.

To view the list of standard macros of GCC, run the following command:

echo '' | aarch64-kos-gcc -dM -E -

Linker operation specifics

When building the executable file of an application, by default the linker links the following libraries in the specified order:

  1. libc is the standard C library.
  2. libm is the library that implements the mathematical functions of the standard C language library.
  3. libvfs_stubs is the library that contains stubs of I/O functions (for example, open, socket, read, write).
  4. libkos is the library for accessing the KasperskyOS core endpoints.
  5. libenv is the library of the subsystem for configuring the environment of applications (environment variables, arguments of the main function, and custom configurations).
  6. libsrvtransport-u is the library that supports IPC between processes and the kernel.
Page top
[Topic crosscompliers]

Example build without using CMake

Below is an example of a script for building a basic example. This example contains a single application called Hello, which does not provide any endpoints.

The provided script is intended only for demonstrating the build commands being used.

build.sh

#!/bin/sh # The SDK variable should specify the path to the KasperskyOS Community Edition installation directory. SDK=/opt/KasperskyOS-Community-Edition-<version> TOOLCHAIN=$SDK/toolchain SYSROOT=$SDK/sysroot-aarch64-kos PATH=$TOOLCHAIN/bin:$PATH # Create the Hello.edl.h file from Hello.edl # (The Hello program does not implement any endpoints, so there are no CDL or IDL files.) nk-gen-c -I $SYSROOT/include Hello.edl # Compile and build the Hello program aarch64-kos-gcc -o hello hello.c # Create the Kaspersky Security Module (ksm.module) makekss --target=aarch64-kos \ --module=-lksm_kss \ --with-nkflags="-I $SDK/examples/common -I $SYSROOT/include" \ security.psl # Create code of the Einit initializing program einit -I $SYSROOT/include -I . init.yaml -o einit.c # Compile and build the Einit program aarch64-kos-gcc -I . -o einit einit.c # Create loadable solution image (kos-qemu-image) makeimg --target=aarch64-kos \ --sys-root=$SYSROOT \ --with-toolchain=$TOOLCHAIN \ --ldscript=$SDK/libexec/aarch64-kos/kos-qemu.ld \ --img-src=$SDK/libexec/aarch64-kos/kos-qemu \ --img-dst=kos-qemu-image \ Hello ksm.module # Run solution under QEMU qemu-system-aarch64 -m 1024 -serial stdio -kernel kos-qemu-image
Page top
[Topic cmake_no_cmake_build_example]

Using dynamic libraries

Dynamic libraries (*.so files) can be used in a KasperskyOS-based solution. Compared to static libraries (*.a files), dynamic libraries provide the following advantages:

  • Efficient use of RAM.

    Multiple processes can use the same instance of a dynamic library. Also, a program and dynamic libraries in one process can use the same instance of a dynamic library.

    Dynamic libraries can be loaded into memory and unloaded from memory on the initiative of the programs that use them.

  • Convenient software updates.

    A dynamic library update is applied to all programs and dynamic libraries dependent on this dynamic library without having to rebuild them.

  • Capability to implement a mechanism for plug-ins.

    Plug-ins for solution components consist of dynamic libraries.

  • Shared use of code and data.

    One instance of a dynamic library can be concurrently used by multiple processes, and by a program and dynamic libraries in one process. This enables centralized management of multi-access to resources or storage of shared data, for example.

Dynamic libraries are provided in the KasperskyOS SDK, and can also be created by a KasperskyOS-based solution developer. Normal operation of third-party dynamic libraries cannot be guaranteed.

Due to current technical limitations, libc.so and libpthread.so cannot be used in a KasperskyOS-based solution.

In this section

Prerequisites for using dynamic libraries

Life cycle of a dynamic library

Including the BlobContainer system program in a KasperskyOS-based solution

Building dynamic libraries

Adding dynamic libraries to a KasperskyOS-based solution image

Page top
[Topic shared_libraries]

Prerequisites for using dynamic libraries

To use dynamic libraries in a KasperskyOS-based solution, the following conditions must be met:

  1. Processes that use dynamic libraries must have access to the file systems in which the files of the dynamic libraries are stored. Access to file systems is provided by VFS, which may be implemented in the context of the processes using the dynamic libraries, or may be a separate process. The dynamic libraries must not be used by VFS or other software that is used by VFS to work with storage (such as a storage driver).
  2. The toolchain must support dynamic linking.

    The KasperskyOS SDK comes with a separate toolchain for each supported processor architecture. A required toolchain may not support dynamic linking. To check whether dynamic linking is supported, you need to use the CMake get_property() command in the CMakeLists.txt root file as follows:

    get_property(CAN_SHARED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) if(CAN_SHARED) message(STATUS "Dynamic linking is supported.") endif()
  3. The executable code of programs that use dynamic libraries must be built with the -rdynamic flag (with dynamic linking).

    If the toolchain supports dynamic linking, the CMake initialize_platform() command causes this flag to be used automatically for building all executable files defined via CMake add_executable() commands.

If the CMake initialize_platform(FORCE_STATIC) command is called in the CMakeLists.txt root file, the toolchain supporting dynamic linking performs static linking of executable files.

The CMake project_static_executable_header_default() command affects the build of executable files defined via subsequent CMake add_executable() commands in one CMakeLists.txt file. The toolchain that supports dynamic linking performs static linking of these executable files.

The CMake platform_target_force_static() command affects the build of one executable file defined via the CMake add_executable() command. The toolchain that supports dynamic linking performs static linking of this executable file.

The executable code of programs that is built with the -rdynamic flag is linked to a static library if a dynamic library is not found. For example, if the CMake target_link_libraries(client -lm) command is being used, the client program is linked to the static library libm.a if the dynamic library libm.so is not found.

Page top
[Topic shared_libraries_use_conditions]

Life cycle of a dynamic library

The life cycle of a dynamic library includes the following phases:

  1. Loading into memory.

    A dynamic library linked to a program is loaded into memory upon startup of the process in whose context this program is executed. A running process can load a dynamic library into memory by calling the dlopen() function of the POSIX interface. A dynamic library may be linked to other dynamic libraries, so a program depends not only on the dynamic library directly linked to it, but also depends on the entire dependency graph of this library. A dynamic library is loaded into memory together with all of the dynamic libraries that it depends on.

    If the BlobContainer system program is included in a KasperskyOS-based solution, one instance of a dynamic library is loaded into shared memory regardless of how many processes are using this library. (More specifically, only the part of the dynamic library that includes code and read-only data is loaded into shared memory. The other part of the dynamic library is loaded into the memory of each process that uses this library.) If the BlobContainer system program is not included in a solution, separate instances of a dynamic library are loaded into the memory of processes that are using this library. A dynamic library on which several other dynamic libraries depend is loaded into shared memory or into the memory of a process in a single instance.

    If a list of dynamic libraries is defined through the LD_PRELOAD environment variable, these dynamic libraries will be loaded into memory even if the program is not dependent on them. (List items must be absolute or relative paths to dynamic libraries separated by a colon, for example: LD_PRELOAD=libmalloc.so:libfree.so:/usr/somepath/lib/libfoo.so.) The functions that are exported by the dynamic libraries specified in LD_PRELOAD replace the identically named functions that are exported by other dynamic libraries loaded into shared memory or process memory. This can be used for debugging purposes if you need to replace functions imported from dynamic libraries.

    The dynamic library loader searches for program-dependent dynamic libraries in the following order:

    1. Absolute paths defined through the LD_LIBRARY_PATH environment variable.

      Paths must be separated by a colon, for example: LD_LIBRARY_PATH=/usr/lib:/home/user/lib.

    2. Absolute paths defined in the DT_RUNPATH or DT_RPATH field of the .dynamic section of executable files and dynamic libraries.

      Linking of executable files and dynamic libraries may include defined paths that the dynamic library loader will search. (For example, this can be done through the INSTALL_RPATH property in the CMake command set_target_properties().) Paths used to search for dynamic libraries are stored in the DT_RUNPATH or DT_RPATH field of the .dynamic section. This field may be in executable files linked to dynamic libraries and in dynamic libraries linked to other dynamic libraries.

    3. Path /lib.

    The dynamic library loader searches in this same order if a relative path to a dynamic library is specified in the filename parameter of the dlopen() function or in the LD_PRELOAD environment variable. If the absolute path is specified, the loader puts the dynamic library into memory without performing a search.

  2. Use by a process (or processes).
  3. Unloading from memory.

    A dynamic library is unloaded from shared memory when all processes using this library have terminated or called the dlclose() function of the POSIX interface. A dynamic library that was loaded into process memory by calling the dlopen() function is unloaded by calling the dlclose() function. A dynamic library that is linked to a program cannot be unloaded from memory until termination of the process in whose context this program is executed. A dynamic library that is linked to other dynamic libraries is unloaded from memory after all libraries that depend on it are unloaded, or after the process is terminated.

Page top
[Topic shared_libraries_lifecycle]

Including the BlobContainer system program in a KasperskyOS-based solution

If the BlobContainer program is provided in the KasperskyOS SDK, it must be included into a solution in which dynamic libraries are used. To check whether the BlobContainer program is included in the KasperskyOS SDK, you need to make sure that the sysroot-*-kos/bin/BlobContainer executable file is available.

The BlobContainer program can be included in a solution either automatically or manually. This program is automatically included in a solution by running the CMake commands build_kos_qemu_image() and build_kos_hw_image() if at least one program in the solution is linked to a dynamic library. (To disable automatic inclusion of the BlobContainer program in a solution, you need to add the NO_AUTO_BLOB_CONTAINER value to the parameters of the CMake commands build_kos_qemu_image() and build_kos_hw_image().) If programs in a solution work with dynamic libraries using only a POSIX interface (the dlopen(), dlsym(), dlerror(), and dlclose() functions), the BlobContainer program needs to be manually included in the solution.

When using the BlobContainer program, you must create IPC channels from the processes using dynamic libraries to the process of the BlobContainer program. These IPC channels can be created statically or dynamically. If a statically created IPC channel is not available, the client and server parts of the BlobContainer program attempt to dynamically create an IPC channel using the name server.

If the BlobContainer program is automatically included in a solution, the @INIT_EXTERNAL_ENTITIES@, @INIT_<program name>_ENTITY_CONNECTIONS@ and @INIT_<program name>_ENTITY_CONNECTIONS+@ macros used in the init.yaml.in file automatically create within the init description dictionaries of IPC channels that enable static creation of IPC channels between processes of programs linked to dynamic libraries and the process of the BlobContainer program. (The process of the BlobContainer program receives the name kl.bc.BlobContainer, while the IPC channels receive the name kl.BlobContainer.) However, dictionaries of IPC channels to the BlobContainer program process are not automatically created for processes that work with dynamic libraries using only a POSIX interface. To ensure that the required IPC channels are statically created, these dictionaries must be manually created (these IPC channels must have the name kl.BlobContainer).

If the BlobContainer program is manually included in the solution and you need to statically create IPC channels from processes using dynamic libraries to the BlobContainer program process, you must manually create dictionaries of the required IPC channels in the init description. By default, the IPC channel to the BlobContainer program process has the name kl.BlobContainer. However, this name can be changed through the environment variable _BLOB_CONTAINER_BACKEND. This variable must be defined for the BlobContainer process and for processes using dynamic libraries.

The environment variable _BLOB_CONTAINER_BACKEND defines not only the name of statically created IPC channels to the BlobContainer program process, but also defines the endpoint name that is published on the name server and used to dynamically create IPC channels to the BlobContainer program process. This is convenient when multiple processes of the BlobContainer program are running simultaneously (for example, to isolate its own dynamic libraries from external ones), and when different processes using dynamic libraries must interact over IPC with different processes of the BlobContainer program. In this case, you need to define different values for the environment variable _BLOB_CONTAINER_BACKEND for different processes of the BlobContainer program, and then use these values for the environment variable _BLOB_CONTAINER_BACKEND for processes using dynamic libraries. The specific value must be selected depending on the specific process of the BlobContainer program that requires the dynamically created IPC channel.

Example use of the environment variable _BLOB_CONTAINER_BACKEND in the init.yaml.in file:

entities: - name: example.BlobContainer path: example_blob_container args: - "-v" env: _BLOB_CONTAINER_BACKEND: kl.custombc @INIT_example_blob_container_ENTITY_CONNECTIONS@ - name: client.Client path: client env: _BLOB_CONTAINER_BACKEND: kl.custombc @INIT_client_ENTITY_CONNECTIONS@ @INIT_EXTERNAL_ENTITIES@

Example use of the environment variable _BLOB_CONTAINER_BACKEND in CMake commands:

set_target_properties (ExecMgrEntity PROPERTIES EXTRA_ENV " _BLOB_CONTAINER_BACKEND: kl.custombc") set_target_properties (dump_collector::entity PROPERTIES EXTRA_ENV " _BLOB_CONTAINER_BACKEND: kl.custombc")

If the BlobContainer program is being used, the VFS working with files of dynamic libraries must be a separate process. An IPC channel must also be created from the process of the BlobContainer program to the VFS process.

Page top
[Topic shared_libraries_blobcontainer]

Building dynamic libraries

When building dynamic libraries, you must use a toolchain that supports dynamic linking.

To build a dynamic library, you need to use the following CMake command:

add_library(<build target name> SHARED [list of paths to files of the library source code])

Use of this CMake command results in an error if the toolchain does not support dynamic linking.

You can also build a dynamic library by using the following CMake command:

add_library(<build target name> [list of paths to files of the library source code])

The cmake shell command must be called with the -D BUILD_SHARED_LIBS=YES parameter. (If the cmake shell command is called without the -D BUILD_SHARED_LIBS=YES parameter, a static library will be built.)

Example:

#!/bin/bash ... cmake -G "Unix Makefiles" \ -D CMAKE_BUILD_TYPE:STRING=Debug \ -D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \ -D BUILD_SHARED_LIBS=YES \ -B build \ && cmake --build build --target kos-image

By default, the library file name matches the name of the build target defined via the parameter of the CMake add_library() command. The library file name can be changed by using the CMake set_target_properties() command. This can be done to make the library file name identical for its dynamic and static variants.

Example:

# Build the static library add_library(somelib_static STATIC src/somesrc.cpp) set_target_properties(somelib_static PROPERTIES OUTPUT_NAME "somelib") # The PLATFORM_SUPPORTS_DYNAMIC_LINKING variable has the # value "true" when using dynamic # linking. If initialize_platform(FORCE_STATIC) is called, # this variable has the value "false". if(PLATFORM_SUPPORTS_DYNAMIC_LINKING) # Build the dynamic library add_library(somelib_shared SHARED src/somesrc.cpp) set_target_properties(somelib_shared PROPERTIES OUTPUT_NAME "somelib") endif()

A dynamic library can be linked to other static and dynamic libraries by using the CMake target_link_libraries() command. In this case, static libraries must be built with the -fPIC flag. This flag is applied when building a static library if the following CMake command is used:

set_property(TARGET <list of names of build targets> PROPERTY POSITION_INDEPENDENT_CODE ON)
Page top
[Topic shared_libraries_building]

Adding dynamic libraries to a KasperskyOS-based solution image

To add dynamic libraries to the KasperskyOS-based solution image, use PACK_DEPS_COPY_ONLY ON, PACK_DEPS_LIBS_PATH, and PACK_DEPS_COPY_TARGET parameters in the CMake commands build_kos_qemu_image() and build_kos_hw_image().

Example:

set(RESOURCES ${CMAKE_SOURCE_DIR}/resources) set(FSTAB ${RESOURCES}/fstab) set(DISK_IMG ${CMAKE_CURRENT_BINARY_DIR}/ramdisk0.img) set(RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../resources) set(EXT4_PART_DIR ${CMAKE_CURRENT_BINARY_DIR}/../system_hdd) set_target_properties(${vfs_ENTITY} PROPERTIES EXTRA_ARGS " - \"-f\" - \"fstab\"" EXTRA_ENV " ROOTFS: ramdisk0 / ext4 0" ${blkdev_ENTITY}_REPLACEMENT "${ramdisk_ENTITY};${sdcard_ENTITY}") add_custom_target(copy-so) add_custom_command(OUTPUT ${DISK_IMG} COMMAND ${CMAKE_COMMAND} -E copy_directory ${RESOURCES_DIR}/rootdir ${EXT4_PART_DIR} COMMAND mke2fs -v -d ${EXT4_PART_DIR} -t ext4 ${DISK_IMG} 40M DEPENDS copy-so COMMENT "Creating disk image '${DISK_IMG}' from files in '${EXT4_PART_DIR}' ...") build_kos_hw_image(kos-image ... IMAGE_FILES ${ENTITIES_LIST} ${FSTAB} ${DISK_IMG} PACK_DEPS_COPY_ONLY ON PACK_DEPS_LIBS_PATH ${EXT4_PART_DIR}/lib PACK_DEPS_COPY_TARGET copylibs) if(PLATFORM_SUPPORTS_DYNAMIC_LINKING) add_dependencies(copy-so copylibs) endif()

The solution program-dependent dynamic libraries are added to a storage device image (for example, one with an ext4 file system) that will be included into the solution image.

Dynamic libraries that are loaded into memory by calling the dlopen() function of the POSIX interface are not added to the solution image.

The build system does the following:

  • Searches for dynamic libraries and copies these libraries to the directory whose path is specified in the PACK_DEPS_LIBS_PATH parameter of the CMake commands build_kos_qemu_image() and build_kos_hw_image(). (To ensure that the found dynamic libraries are included in the storage device image, this directory must reside in the file system that will be put into the storage device image.)
  • Creates a storage device image that includes the directory containing the dynamic libraries.

    To create a storage device image, use the CMake command add_custom_command(). The target specified in the DEPENDS parameter of the CMake command add_custom_command(), indicates that a storage device image is created. The target specified in the PACK_DEPS_COPY_TARGET parameter of the CMake commands build_kos_qemu_image() and build_kos_hw_image(), indicates that dynamic libraries are copied. To make sure that the storage device image is created only after the dynamic libraries are fully copied, use the CMake command add_dependencies().

  • Adds the storage device image to the solution image.

    To add the storage device image to the solution image, specify the full path to the storage device image in the IMAGE_FILES parameter of the CMake commands build_kos_qemu_image() and build_kos_hw_image().

Page top
[Topic shared_libraries_adding_to_image]