Contents
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 to simplify the use of CMake
scripts:
- In the project root, create a CMakeLists.txt boot file containing the general build instructions for the entire solution.
- The source code of each program being developed should be placed into a separate directory within the
src
subdirectory. - Create CMakeLists.txt files for building each application in the corresponding directories.
- To generate the source code of the
Einit
program, you should create a separateeinit
directory containing thesrc
subdirectory in which you should put the init.yaml.in and security.psl.in templates.Any other files that need to be included in the solution image can also be put into this directory.
- Create a CMakeLists.txt file for building the
Einit
program in theeinit
directory. - The files of EDL, CDL and IDL descriptions should be put into the
resources
directory in the project root. - [Optional] Create a
cross-build.sh
build script containing the commands to start generating build files (cmake
command), to build the solution (make
command), and to start the solution.
Example structure of project directories
example$ tree
.
├── CMakeLists.txt
├── cross-build.sh
├── hello
│ ├── CMakeLists.txt
│ ├── src
│ │ ├── hello.c
├── einit
│ ├── CMakeLists.txt
│ ├── src
│ │ ├── init.yaml.in
│ │ ├── security.psl.in
│ │ ├── fstab
├── resources
│ ├── Hello.idl
│ ├── Hello.cdl
│ ├── Hello.edl
Building a project
To prepare for a build using the CMake
build system, the following is required:
- Prepare a CMakeLists.txt boot file containing the general build instructions for the entire solution.
- Prepare CMakeLists.txt files for each application to be built.
- Prepare a CMakeLists.txt file for the Einit program.
- Prepare the
init.yaml.in
andsecurity.psl.in
templates.
To perform cross-compilation using the CMake
build automation system, the following is required:
- Create a subdirectory for the build.
BUILD=$PWD/.build
mkdir -p $BUILD && cd $BUILD
- Prior to starting generation of build scripts (
cmake
command), set the following values for environment variables:export LANG=C
export PKG_CONFIG=""
export SDK_PREFIX="/opt/KasperskyOS-Community-Edition-<version>"
export PATH="$SDK_PREFIX/toolchain/bin:$PATH"
export INSTALL_PREFIX=$BUILD/../install
export TARGET="aarch64-kos"
- When starting generation of build scripts (
cmake
command), specify the following:-G "Unix Makefiles"
parameter- Path to the file with the build system extension (
toolchain.cmake
) in theCMAKE_TOOLCHAIN_FILE
variable.The file with the build system extension is located in the following directory:
/opt/KasperskyOS-Community-Edition-<version>/toolchain/share/toolchain-aarch64-kos.cmake
- Value of the
CMAKE_BUILD_TYPE:STRING=Debug
variable - Value of the
CMAKE_INSTALL_PREFIX:STRING=$INSTALL_PREFIX
variable - Path to the CMakeLists.txt boot file
- When starting the build (
make
command), specify one of the build targets.The target name must match the build target name passed to the solution build command in the CMakeLists.txt file for the Einit program.
Example cross-build.sh build script
cross-build.sh
#!/bin/bash
# Create a subdirectory for the build
BUILD=$PWD/.build
mkdir -p $BUILD && cd $BUILD
# Set the values of environment variables
export LANG=C
export PKG_CONFIG=""
export SDK_PREFIX="/opt/KasperskyOS-Community-Edition-<version>"
export PATH="$SDK_PREFIX/toolchain/bin:$PATH"
export INSTALL_PREFIX=$BUILD/../install
export TARGET="aarch64-kos"
# Start generating files for the build. The current directory is $BUILD,
# so the CMakeLists.txt boot file is in the parent directory
cmake -G "Unix Makefiles" \
-D CMAKE_BUILD_TYPE:STRING=Debug \
-D CMAKE_INSTALL_PREFIX:STRING=$BUILD/../.install \
-D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \
../
# Start the build. Include the VERBOSE flag for Make and redirect the output to the build.log file
VERBOSE=1 make kos-qemu-image 2>&1 | tee build.log
# Run the built solution image in QEMU.
# -kernel $BUILD/einit/kos-qemu-image path to the built kernel image
$SDK_PREFIX/toolchain/bin/qemu-system-aarch64 \
-m 1024 \
-cpu core2duo \
-serial stdio \
-kernel $BUILD/einit/kos-qemu-image
CMakeLists.txt boot 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.12)
indicates the minimum supported version ofCMake
.For a KasperskyOS-based solution build,
CMake
version 3.12 or later is required.The required version of
CMake
is provided in KasperskyOS Community Edition and is used by default.include (platform)
connects theplatform
library ofCMake
.initialize_platform()
initializes theplatform
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
- A package is connected by using the
- The
Einit
initializing program must be built using theadd_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)
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)
CMakeLists.txt files for building applications
The CMakeLists.txt
file for building an application must contain the following commands:
include (platform/nk)
connects theCMake
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:
- idl.h files are generated by the
nk_build_idl_files()
command - cdl.h files are generated by the
nk_build_cdl_files()
command - edl.h files are generated by the
nk_build_edl_files()
command
- idl.h files are generated by the
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 theEXTRA_CONNECTIONS
property and assign it a value with descriptions of the relevant IPC channels.Example of creating an IPC channel between a
Client
process and aServer
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 theinit.yaml
file when building a solution, you must define theEXTRA_ARGS
andEXTRA_ENV
properties and assign the appropriate values to them.Example of sending the
Client
program the"-v"
argument of themain()
function and the environment variableVAR1
set toVALUE1
: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 theinit.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
)
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 theCMake
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
- A package is connected by using the
- 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 theEXTRA_CONNECTIONS
property for the corresponding programs.For example, the
VFS
program does not have a channel for connecting to theEnv
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 theCMakeLists.txt
file for building theEinit
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 theinit.yaml
file when building a solution, you must define theEXTRA_ARGS
andEXTRA_ENV
properties and assign the appropriate values to them.
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 theENTITIES
variable containing a list of executable files of all programs included in the solution.- One or both commands for building the solution image:
- build_kos_hw_image() creates the build target that can then be used to build the image for the hardware platform using
make
. - build_kos_qemu_image() creates the build target that can then be used to build the image for running in QEMU using
make
.
- build_kos_hw_image() creates the build target that can then be used to build the image for the hardware platform using
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
)
# Solution image for target hardware platform.
# Create the build target named kos-image that can then be used
# to build the image for the hardware platform using make kos-image.
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}
)
# Solution image for the QEMU hardware platform.
# Create the build target named kos-qemu-image that can then be used
# to build a QEMU image using make kos-qemu-image.
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}
)
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. Thetarget
andid
fields are filled according to theconnect.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 rootconnections
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 theEXTRA_CONNECTIONS
property when building this program. - If you need to pass
main()
function arguments defined in theEXTRA_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 themain()
function defined in theEXTRA_ARGS
property. This macro adds the rootargs
key.@INIT_<program name>_ENTITY_ARGS+@
– during the build, this macro adds the list ofmain()
function arguments defined in theEXTRA_ARGS
property to the list of manually defined arguments. This macro does not add the rootargs
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 theEXTRA_ENV
property. This macro adds the rootenv
key.@INIT_<program name>_ENTITY_ENV+@
– during the build, this macro adds the dictionary of environment variables and their values defined in theEXTRA_ENV
property to the manually defined variables. This macro does not add the rootenv
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
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:
- Describing the global parameters of a solution security policy
- Including PSL files
- Including EDL files of application software
- Creating security model objects
- Binding methods of security models to security events
- Describing 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 ()
}