Integration into the build process¶
Code generation has to be invoked as part of the build process of a project.
CMake¶
Projects that use CMake to manage building the project can add the following CMake code to the CMake scripts.
By this a file that contains inline code generation can be added to the project
using the target_sources_cogeno command in the respective CMakeList.txt
file.
-
target_sources_cogeno
(file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
find_program(COGENO_EXECUTABLE cogeno)
if(EXISTS "${COGENO_EXECUTABLE}")
# We do not need the Python 3 interpreter
set(COGENO_EXECUTABLE_OPTION)
else()
# Cogeno is not installed.
# Maybe the cogeno repository was cloned
# or the Zephyr copy is available.
find_file(COGENO_PY cogeno.py
PATHS $ENV{HOME}/cogeno/cogeno
$ENV{ZEPHYR_BASE}/../cogeno/cogeno
$ENV{ZEPHYR_BASE}/scripts/cogeno/cogeno)
if(NOT EXISTS "${COGENO_PY}")
message(FATAL_ERROR "Cogeno not found - '${COGENO_PY}'.")
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.12")
set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5)
find_package(PythonInterp)
set(Python3_Interpreter_FOUND ${PYTHONINTERP_FOUND})
set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
set(Python3_VERSION ${PYTHON_VERSION_STRING})
else()
# CMake >= 3.12
find_package(Python3 COMPONENTS Interpreter)
endif()
if(NOT ${Python3_Interpreter_FOUND})
message(FATAL_ERROR "Python 3 not found")
endif()
set(COGENO_EXECUTABLE "${Python3_EXECUTABLE}")
set(COGENO_EXECUTABLE_OPTION "${COGENO_PY}")
message(STATUS "Found cogeno: '${COGENO_PY}'.")
endif()
# --config
if(COGENO_CONFIG)
set(COGENO_CONFIG_OPTION "--config" "${COGENO_CONFIG}")
else()
set(COGENO_CONFIG_OPTION)
endif()
# --dts
# --bindings
# --edts
if(COGENO_DTS)
set(COGENO_DTS_OPTION "--dts" "${COGENO_DTS}")
if(COGENO_BINDINGS)
set(COGENO_BINDINGS_OPTION "--bindings" ${COGENO_BINDINGS})
else()
set(COGENO_BINDINGS_OPTION)
endif()
if(COGENO_EDTS)
set(COGENO_EDTS_OPTION "--edts" "${COGENO_EDTS}")
else()
set(COGENO_EDTS_OPTION "--edts" "${CMAKE_BINARY_DIR}/edts.json")
endif()
else()
set(COGENO_DTS_OPTION)
set(COGENO_BINDINGS_OPTION)
if(COGENO_EDTS)
set(COGENO_EDTS_OPTION "--edts" "${COGENO_EDTS}")
else()
set(COGENO_EDTS_OPTION)
endif()
endif()
# --modules
if(COGENO_MODULES)
set(COGENO_MODULES_OPTION "--modules" ${COGENO_MODULES})
else()
set(COGENO_MODULES_OPTION)
endif()
# --modules
if(COGENO_TEMPLATES)
set(COGENO_TEMPLATES_OPTION "--templates" ${COGENO_TEMPLATES})
else()
set(COGENO_TEMPLATES_OPTION)
endif()
function(target_sources_cogeno
target # The CMake target that depends on the generated file
)
set(options)
set(oneValueArgs)
set(multiValueArgs COGENO_DEFINES DEPENDS)
cmake_parse_arguments(COGENO "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})
# prepend -D to all defines
string(REGEX REPLACE "([^;]+)" "-D;\\1"
COGENO_COGENO_DEFINES "${COGENO_COGENO_DEFINES}")
message(STATUS "Will generate for target ${target}")
# Generated file must be generated to the current binary directory.
# Otherwise this would trigger CMake issue #14633:
# https://gitlab.kitware.com/cmake/cmake/issues/14633
foreach(arg ${COGENO_UNPARSED_ARGUMENTS})
if(IS_ABSOLUTE ${arg})
set(template_file ${arg})
get_filename_component(generated_file_name ${arg} NAME)
set(generated_file ${CMAKE_CURRENT_BINARY_DIR}/${generated_file_name})
else()
set(template_file ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
set(generated_file ${CMAKE_CURRENT_BINARY_DIR}/${arg})
endif()
get_filename_component(template_dir ${template_file} DIRECTORY)
get_filename_component(generated_dir ${generated_file} DIRECTORY)
if(IS_DIRECTORY ${template_file})
message(FATAL_ERROR "target_sources_cogeno() was called on a directory")
endif()
# Generate file from template
message(STATUS " from '${template_file}'")
message(STATUS " to '${generated_file}'")
add_custom_command(
COMMENT "cogeno ${generated_file}"
OUTPUT ${generated_file}
MAIN_DEPENDENCY ${template_file}
DEPENDS
${COGENO_DEPENDS}
COMMAND
${COGENO_EXECUTABLE}
${COGENO_EXECUTABLE_OPTION}
${COGENO_COGENO_DEFINES}
-D "\"APPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR}\""
-D "\"APPLICATION_BINARY_DIR=${APPLICATION_BINARY_DIR}\""
-D "\"PROJECT_NAME=${PROJECT_NAME}\""
-D "\"PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}\""
-D "\"PROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}\""
-D "\"CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}\""
-D "\"CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}\""
-D "\"CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}\""
-D "\"CMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}\""
-D "\"CMAKE_CURRENT_LIST_DIR=${CMAKE_CURRENT_LIST_DIR}\""
-D "\"CMAKE_FILES_DIRECTORY=${CMAKE_FILES_DIRECTORY}\""
-D "\"CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}\""
-D "\"CMAKE_SYSTEM=${CMAKE_SYSTEM}\""
-D "\"CMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}\""
-D "\"CMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}\""
-D "\"CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}\""
-D "\"CMAKE_C_COMPILER=${CMAKE_C_COMPILER}\""
-D "\"CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\""
-D "\"CMAKE_COMPILER_IS_GNUCC=${CMAKE_COMPILER_IS_GNUCC}\""
-D "\"CMAKE_COMPILER_IS_GNUCXX=${CMAKE_COMPILER_IS_GNUCXX}\""
--cmakecache "${CMAKE_BINARY_DIR}/CMakeCache.txt"
${COGENO_CONFIG_OPTION}
${COGENO_DTS_OPTION}
${COGENO_BINDINGS_OPTION}
${COGENO_EDTS_OPTION}
${COGENO_MODULES_OPTION}
${COGENO_TEMPLATES_OPTION}
--input "${template_file}"
--output "${generated_file}"
--log "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cogeno.log"
--lock "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cogeno.lock"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
target_sources(${target} PRIVATE ${generated_file})
# Add template directory to include path to allow includes with
# relative path in generated file to work
target_include_directories(${target} PRIVATE ${template_dir})
# Add directory of generated file to include path to allow includes
# of generated header file with relative path.
target_include_directories(${target} PRIVATE ${generated_dir})
endforeach()
endfunction()
Zephyr¶
Cogeno can be integrated into Zephyr by applying the cogeno pull request.
In Zephyr the processing of source files is controlled by the CMake extension functions:
zephyr_sources_cogeno(..)
or zephyr_library_sources_cogeno(..)
. The generated
source files are added to the Zephyr sources. During build the source files are
processed by cogeno and the generated source files are written to the CMake
binary directory. Zephyr uses CMake as the tool to manage building
the project. A file that contains inline code generation has to be added to the project
by one of the following commands in a CMakeList.txt
file:
-
zephyr_sources_cogeno
(file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_sources_cogeno_ifdef
(ifguard file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_sources_cogeno
(file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
-
zephyr_library_sources_cogeno_ifdef
(ifguard file [COGENO_DEFINES defines..] [DEPENDS target.. file..])¶
The arguments given by the COGENO_DEFINES
keyword have to be of the form
define_name=define_value
. The arguments become globals in the python
snippets and can be accessed by define_name
.
Dependencies given by the DEPENDS
key word are added to the dependencies
of the generated file.