How to define build Environments¶
In order for the Hermetic aspect of Hermetic FetchContent to work as expected, it is mandatory
to extract some information that we consider to be environment specific from the project's
CMakeLists.txt
files and to unify this as part of a "Hermetic Environment Definition".
At its core, this approach utilizes CMake's TOOLCHAIN_FILE
concept, but does so in a way that enables
more benefits once used in conjunction with cmake-re
and/or tipi.build
.
Environment structure¶
In your project, the location for environment specifications would usually be under <project-root>/toolchains
.
Here's what the typical structure of a Hermetic FetchContent build environment looks like:
<environment-folder>/<name>.cmake
<environment-folder>/environment/*
The <name>.cmake
file is the -DCMAKE_TOOLCHAIN_FILE
argument used in your
configure settings and should contain basic toolchain settings (an example is provided below).
The environment/
sub-folder is meant to contain toolchain fragments that can be included by
the toolchain file.
Additionally, for tipi support, you may want to add the following entries:
<environment-folder>/cmake/test-injector.cmake
<environment-folder>/<name>.pkr.js/<name>.pkr.js
More details on these components are provided below.
Example¶
Below a simple example of a toolchain using the system-provided GCC-13 installation:
In file example/example-gcc13.cmake
include("${CMAKE_CURRENT_LIST_DIR}/environment/base.cmake")
# Refine behaviour by giving CMAKE_FIND_ROOT_PATH priority to our install_prefix
get_filename_component(current_source_absolute_path "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE)
list(INSERT CMAKE_FIND_ROOT_PATH 0 "${current_source_absolute_path}/toolchains/" )
list(APPEND CMAKE_PREFIX_PATH "${current_source_absolute_path}/toolchains/" )
# configure find_* behavior to get to a hermetic state
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
In file example/environment/base.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_HOST_SYSTEM_NAME Linux)
set(CMAKE_CROSSCOMPILING FALSE)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_HOST_SYSTEM_PROCESSOR x86_64)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
include("${CMAKE_CURRENT_LIST_DIR}/gcc-13.cmake")
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_STANDARD "17" CACHE STRING "" FORCE)
In file example/environment/gcc-13.cmake
find_program(CMAKE_C_COMPILER gcc PATHS "/usr/bin/;/usr/local/bin/" NO_DEFAULT_PATH)
find_program(CMAKE_CXX_COMPILER g++ PATHS "/usr/bin/;/usr/local/bin/" NO_DEFAULT_PATH)
if(NOT CMAKE_C_COMPILER)
message(FATAL_ERROR "gcc not found")
endif()
if(NOT CMAKE_CXX_COMPILER)
message(FATAL_ERROR "g++ not found")
endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 13)
message(FATAL_ERROR "Wrong version of g++ found (expected 13.x found ${CMAKE_CXX_COMPILER_VERSION})")
endif()
set(CMAKE_C_COMPILER "${CMAKE_C_COMPILER}" CACHE STRING "C compiler" FORCE)
set(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER}" CACHE STRING "C++ compiler" FORCE)
CMake-RE and tipi remote build support¶
To make these environments compatible with remote builds using cmake-re and the tipi.build cloud, additional configurations are required.
By adding a specific cmake module to <environment-folder>/cmake/test-injector.cmake
, you can enable
support for cmake-re's --test
option (and related parameters).
include_guard(GLOBAL) #!important!
macro(add_test)
separate_arguments(separated_args NATIVE_COMMAND $ENV{TIPI_TESTS_ARGUMENTS})
set(tat_params ${ARGV})
list(APPEND tat_params ${separated_args})
_add_test(${tat_params})
endmacro()
This macro allows cmake-re to inject test arguments into the ctest call chain.
Additionally, you can specify the Docker image used as the host environment for remote cmake-re builds.
To do this, replace the <container URL> placeholder in the template below with the appropriate Docker
image URL. It's important to place this file at <environment-folder>/<name>.pkr.js/<name>.pkr.js
.
Ensure that <name> matches exactly with the name of the environment or toolchain file.
{
"variables": { },
"builders": [
{
"type": "docker",
"image": "<container URL>",
"commit": true
}
],
"post-processors": [
{
"type": "docker-tag",
"repository": "linux",
"tag": "latest"
}
],
"_tipi_version":"{{tipi_version_hash}}"
}
The container URL should be a docker registry image URL including its tag or hash.