Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter

- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
This commit is contained in:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,18 @@
# Trailbook Extension for Everest
This CMake package is an extension for the Trailbook CMake package
that provides additional functionality specifically for building
documentation for the Everest project.
The following additional features are provided:
* cmake function: `trailbook_ev_add_module_explanation()`
* cmake function: `trailbook_ev_create_snapshot()`
* cmake function: `trailbook_ev_generate_api_doc()`
* cmake function: `trailbook_ev_generate_rst_from_manifest()`
* cmake function: `trailbook_ev_generate_rst_from_interface()`
* cmake function: `trailbook_ev_generate_rst_from_types()`
Check out the inline documentation of the functions for more details
on how to use them. Each function is defined in its own CMake file
located in this package directory.

View File

@@ -0,0 +1,214 @@
# This macro is for internal use only
#
# It is used in the function trailbook_ev_add_module_handwritten_doc().
# It adds a custom command to copy the handwritten module files to the reference modules directory.
macro(_trailbook_ev_add_module_reference_copy_handwritten_command)
file(
GLOB_RECURSE
MODULE_HANDWRITTEN_SOURCE_FILES
RELATIVE "${args_HANDWRITTEN_DIR}"
CONFIGURE_DEPENDS
"${args_HANDWRITTEN_DIR}/*"
)
set(EXPECTED_DEST_FILES "")
set(COPY_DEPENDENCIES "")
foreach(SOURCE_FILE IN LISTS MODULE_HANDWRITTEN_SOURCE_FILES)
set(SRC_FILE_PATH "${args_HANDWRITTEN_DIR}/${SOURCE_FILE}")
if(IS_DIRECTORY "${SRC_FILE_PATH}")
continue()
endif()
get_filename_component(RELATIVE_SUBDIR "${SOURCE_FILE}" DIRECTORY)
get_filename_component(FILE_NAME "${SOURCE_FILE}" NAME)
# when copying 'index.rst' then rename it
if("${FILE_NAME}" STREQUAL "index.rst")
set(DEST_FILENAME "index.inc")
else()
set(DEST_FILENAME "${FILE_NAME}")
endif()
if("${RELATIVE_SUBDIR}" STREQUAL "")
set(DEST_FILE_PATH "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/${DEST_FILENAME}")
set(DEST_DIR "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}")
else()
set(DEST_FILE_PATH "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/${RELATIVE_SUBDIR}/${DEST_FILENAME}")
set(DEST_DIR "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/${RELATIVE_SUBDIR}")
endif()
list(APPEND EXPECTED_DEST_FILES "${DEST_FILE_PATH}")
# One command per file
add_custom_command(
OUTPUT "${DEST_FILE_PATH}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEST_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy "${SRC_FILE_PATH}" "${DEST_FILE_PATH}"
DEPENDS "${SRC_FILE_PATH}"
COMMENT "Processing doc file: ${SOURCE_FILE} -> ${RELATIVE_SUBDIR}/${DEST_FILENAME}"
VERBATIM
)
list(APPEND COPY_DEPENDENCIES "${DEST_FILE_PATH}")
endforeach()
# Remove files if they were deleted in the source tree
if(EXISTS "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}")
file(GLOB_RECURSE EXISTING_DEST_FILES "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/*")
foreach(EXISTING_FILE IN LISTS EXISTING_DEST_FILES)
if(IS_DIRECTORY "${EXISTING_FILE}")
continue()
endif()
list(FIND EXPECTED_DEST_FILES "${EXISTING_FILE}" FILE_INDEX)
if(FILE_INDEX EQUAL -1)
message(STATUS " Removing orphaned doc file: ${EXISTING_FILE}")
file(REMOVE "${EXISTING_FILE}")
endif()
endforeach()
endif()
if(COPY_DEPENDENCIES)
set(ASSET_TARGET "${TARGET_NAME_PREFIX}_assets")
# Guard against multiple definitions
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME}_handwritten_doc_module_${args_MODULE_NAME})
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_handwritten_doc_module_${args_MODULE_NAME}
DEPENDS
${COPY_DEPENDENCIES}
COMMENT
"Handwritten documentation of module ${args_MODULE_NAME} for trailbook ${args_TRAILBOOK_NAME} is available."
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${COPY_DEPENDENCIES}
trailbook_${args_TRAILBOOK_NAME}_handwritten_doc_module_${args_MODULE_NAME}
)
endif()
endif()
# set(MODULE_HANDWRITTEN_TARGET_FILES "")
# foreach(source_file IN LISTS MODULE_HANDWRITTEN_SOURCE_FILES)
# file(RELATIVE_PATH rel_path "${args_HANDWRITTEN_DIR}" "${source_file}")
# set(target_file "${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/${rel_path}")
# list(APPEND MODULE_HANDWRITTEN_TARGET_FILES "${target_file}")
# endforeach()
# add_custom_command(
# OUTPUT
# ${MODULE_HANDWRITTEN_TARGET_FILES}
# DEPENDS
# ${MODULE_HANDWRITTEN_SOURCE_FILES}
# ${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
# COMMENT
# "Copying handwritten documentation files of module ${args_MODULE_NAME} to: ${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/"
# COMMAND
# ${CMAKE_COMMAND} -E rm -rf
# ${MODULE_HANDWRITTEN_TARGET_FILES}
# COMMAND
# ${CMAKE_COMMAND} -E make_directory
# ${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/
# COMMAND
# ${CMAKE_COMMAND} -E copy_directory
# ${args_HANDWRITTEN_DIR}
# ${TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY}/
# )
endmacro()
# This function adds a handwritten module documentation to a trailbook.
# It takes the following parameters:
# TRAILBOOK_NAME (required): The name of the trailbook to add the
# documentation to.
# MODULE_NAME (required): The name of the module.
# HANDWRITTEN_DIR (required): The absolute path to the directory
# containing the module's handwritten files.
#
# Usage:
# trailbook_ev_add_module_handwritten_doc(
# TRAILBOOK_NAME <trailbook_name>
# MODULE_NAME <module_name>
# HANDWRITTEN_DIR <absolute_path_to_handwritten_docs_directory>
# )
function(trailbook_ev_add_module_handwritten_doc)
set(options)
set(one_value_args
TRAILBOOK_NAME
MODULE_NAME
HANDWRITTEN_DIR
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ev_add_module_handwritten_doc: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ev_add_module_handwritten_doc: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter MODULE_NAME
# - is required
if(NOT args_MODULE_NAME)
message(FATAL_ERROR "trailbook_ev_add_module_handwritten_doc: MODULE_NAME argument is required")
endif()
# Parameter HANDWRITTEN_DIR
# - is required
# - must be a absolute path
# - must exist
if(NOT args_HANDWRITTEN_DIR)
message(FATAL_ERROR "trailbook_ev_add_module_handwritten_doc: HANDWRITTEN_DIR argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_HANDWRITTEN_DIR}")
message(FATAL_ERROR "trailbook_ev_add_module_handwritten_doc: HANDWRITTEN_DIR must be an absolute path")
endif()
if(NOT EXISTS "${args_HANDWRITTEN_DIR}")
message(FATAL_ERROR "trailbook_ev_add_module_handwritten_doc: HANDWRITTEN_DIR does not exist")
endif()
get_target_property(
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
)
get_target_property(
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
trailbook_${args_TRAILBOOK_NAME}
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
)
file(RELATIVE_PATH RELATIVE_PATH_HANDWRITTEN_DIR
"${CMAKE_SOURCE_DIR}/modules"
"${args_HANDWRITTEN_DIR}"
)
get_filename_component(RELATIVE_PATH_MODULE "${RELATIVE_PATH_HANDWRITTEN_DIR}" DIRECTORY)
set(TRAILBOOK_EV_REFERENCE_DIRECTORY "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/reference")
set(TRAILBOOK_EV_HANDWRITTEN_MODULE_DOC_DIRECTORY "${TRAILBOOK_EV_REFERENCE_DIRECTORY}/modules/${RELATIVE_PATH_MODULE}")
_trailbook_ev_add_module_reference_copy_handwritten_command()
endfunction()

View File

@@ -0,0 +1,140 @@
if(NOT DEFINED _TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SETUP)
if(NOT DEFINED everest-utils_SOURCE_DIR)
message(FATAL_ERROR "everest-utils not found. Did you forget to add it to your dependencies.yaml?")
endif()
set(_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SCRIPT
"${everest-utils_SOURCE_DIR}/scripts/create_snapshot.py"
)
if(NOT EXISTS "${_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SCRIPT}")
message(FATAL_ERROR "everest-utils found, but create_snapshot.py script is missing at ${_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SCRIPT}")
endif()
set(_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SETUP TRUE)
endif()
# This function creates a snapshot file and adds it
# to the given trailbook
# Parameters:
# EVEREST_WORKSPACE_DIRECTORY (required): Absolute path to the EVerest workspace
# directory
# TRAILBOOK_NAME (required): Name of the trailbook (the
# target must exist)
# OUTPUT_FILE (required): Absolute path to the output
# snapshot file
# Usage:
# trailbook_ev_create_snapshot(
# EVEREST_WORKSPACE_DIRECTORY <path_to_everest_workspace_directory>
# TRAILBOOK_NAME <trailbook_name>
# OUTPUT_FILE <absolute_path_to_output_snapshot_file>
# )
function(trailbook_ev_create_snapshot)
set(options)
set(one_value_args
EVEREST_WORKSPACE_DIRECTORY
TRAILBOOK_NAME
OUTPUT_FILE
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter EVEREST_WORKSPACE_DIRECTORY
# - is required
# - must be a absolute path
# - must exist
if(NOT EVEREST_WORKSPACE_DIRECTORY)
message(FATAL_ERROR "trailbook_ev_create_snapshot: EVEREST_WORKSPACE_DIRECTORY argument is required")
endif()
if(NOT IS_ABSOLUTE "${EVEREST_WORKSPACE_DIRECTORY}")
message(FATAL_ERROR "trailbook_ev_create_snapshot: EVEREST_WORKSPACE_DIRECTORY must be an absolute path")
endif()
if(NOT EXISTS "${EVEREST_WORKSPACE_DIRECTORY}")
message(FATAL_ERROR "trailbook_ev_create_snapshot: EVEREST_WORKSPACE_DIRECTORY must exist")
endif()
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ev_create_snapshot: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ev_create_snapshot: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter OUTPUT_FILE
# - is required
# - must be a absolute path
if(NOT args_OUTPUT_FILE)
message(FATAL_ERROR "trailbook_ev_create_snapshot: OUTPUT_FILE argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_OUTPUT_FILE}")
message(FATAL_ERROR "trailbook_ev_create_snapshot: OUTPUT_FILE must be an absolute path")
endif()
get_target_property(
TRAILBOOK_CURRENT_BINARY_DIR
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_CURRENT_BINARY_DIR
)
get_target_property(
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
trailbook_${args_TRAILBOOK_NAME}
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
)
set(CREATE_SNAPSHOT_TEMP_DIR "${TRAILBOOK_CURRENT_BINARY_DIR}/create_snapshot_temp")
add_custom_command(
OUTPUT
${args_OUTPUT_FILE}
DEPENDS
${_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SCRIPT}
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
USES_TERMINAL
COMMAND
${CMAKE_COMMAND} -E rm -rf
${CREATE_SNAPSHOT_TEMP_DIR}
COMMAND
${Python3_EXECUTABLE}
${_TRAILBOOK_EXT_EVEREST_CREATE_SNAPSHOT_SCRIPT}
--working-dir ${args_EVEREST_WORKSPACE_DIRECTORY}
--temp-dir ${CREATE_SNAPSHOT_TEMP_DIR}
--allow-relative-to-working-dir
--exclude-dir build/
--exclude-dir .vscode/
--exclude-dir dist/
--exclude-dir cache/
--exclude-dir scripts/
COMMAND
${CMAKE_COMMAND} -E copy
${CREATE_SNAPSHOT_TEMP_DIR}/snapshot.yaml
${args_OUTPUT_FILE}
)
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_create_snapshot
DEPENDS
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
${args_OUTPUT_FILE}
COMMENT
"Target to create snapshot file ${args_OUTPUT_FILE} for trailbook ${args_TRAILBOOK_NAME}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${args_OUTPUT_FILE}
trailbook_${args_TRAILBOOK_NAME}_create_snapshot
)
endfunction()

View File

@@ -0,0 +1,41 @@
if(asyncapi-cli_DIR)
message(STATUS "Using asyncapi-cli at this location: ${asyncapi-cli_DIR}")
else()
message(STATUS "Retrieving asyncapi-cli using FetchContent")
include(FetchContent)
FetchContent_Declare(
asyncapi-cli
GIT_REPOSITORY https://github.com/asyncapi/cli.git
GIT_TAG v2.7.1
)
FetchContent_MakeAvailable(asyncapi-cli)
set(asyncapi-cli_DIR "${asyncapi-cli_SOURCE_DIR}")
set(asyncapi-cli_FIND_COMPONENTS "bundling")
endif()
set(ASYNCAPI_CLI_INSTALL_SENTINEL_PATH "${CMAKE_CURRENT_BINARY_DIR}/generated")
set(ASYNCAPI_CLI_INSTALL_SENTINEL "${ASYNCAPI_CLI_INSTALL_SENTINEL_PATH}/asyncapi_cli_install_done")
if(NOT TARGET asyncapi_cli_install_target)
add_custom_command(
OUTPUT ${ASYNCAPI_CLI_INSTALL_SENTINEL}
# Do installation
COMMAND ${CMAKE_COMMAND} -E chdir ${asyncapi-cli_DIR} npm install
COMMAND ${CMAKE_COMMAND} -E chdir ${asyncapi-cli_DIR} npm run build
# Create sentinel file
COMMAND ${CMAKE_COMMAND} -E make_directory ${ASYNCAPI_CLI_INSTALL_SENTINEL_PATH}
COMMAND ${CMAKE_COMMAND} -E touch ${ASYNCAPI_CLI_INSTALL_SENTINEL}
COMMENT "AsyncApi/cli Install once only"
)
add_custom_target(asyncapi_cli_install_target
DEPENDS ${ASYNCAPI_CLI_INSTALL_SENTINEL}
)
else()
message(STATUS "Skipping definition of 'asyncapi_cli_install_target'; already exists.")
endif()
set(ASYNCAPI_CMD ${asyncapi-cli_DIR}/bin/run)

View File

@@ -0,0 +1,45 @@
if(asyncapi-html-template_DIR)
message(STATUS "Using existing asyncapi-html-template location: ${asyncapi-html-template_DIR}")
else()
find_package(asyncapi-html-template
COMPONENTS bundling
PATHS ../asyncapi-html-template
)
if(NOT asyncapi-html-template_FOUND)
message(STATUS "Retrieving asyncapi-html-template using FetchContent")
include(FetchContent)
FetchContent_Declare(
asyncapi-html-template
GIT_REPOSITORY https://github.com/asyncapi/html-template.git
GIT_TAG v3.0.0
)
FetchContent_MakeAvailable(asyncapi-html-template)
set(asyncapi-html-template_DIR "${asyncapi-html-template_SOURCE_DIR}")
set(asyncapi-html-template_FIND_COMPONENTS "bundling")
endif()
endif()
set(ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL_PATH "${CMAKE_CURRENT_BINARY_DIR}/generate")
set(ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL "${ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL_PATH}/asyncapi_html_template_install_done")
if(NOT TARGET asyncapi_html_template_install_target)
add_custom_command(
OUTPUT ${ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL}
# Do installation
COMMAND ${CMAKE_COMMAND} -E chdir ${asyncapi-html-template_DIR} npm install
# Create sentinel file
COMMAND ${CMAKE_COMMAND} -E make_directory ${ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL_PATH}
COMMAND ${CMAKE_COMMAND} -E touch ${ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL}
COMMENT "AsyncApi/html-template Install once only"
)
add_custom_target(asyncapi_html_template_install_target
DEPENDS ${ASYNCAPI_HTML_TEMPLATE_INSTALL_SENTINEL}
)
else()
message(STATUS "Skipping definition of 'asyncapi_html_template_install_target'; already exists.")
endif()

View File

@@ -0,0 +1,231 @@
include(${CMAKE_CURRENT_LIST_DIR}/fetch_async_api_html_template.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/fetch_async_api.cmake)
function(_trailbook_ev_generate_html_from_api)
set(options)
set(one_value_args
TRAILBOOK_NAME
API_FILE
HTML_PATH
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ev_generate_rst_from_api: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ev_generate_rst_from_api: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter API_FILE
# - is required
# - must be a absolute path
# - must exist
if(NOT args_API_FILE)
message(FATAL_ERROR "trailbook_ev_generate_rst_from_api: API_FILE argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_API_FILE}")
message(FATAL_ERROR "trailbook_ev_generate_rst_from_api: API_FILE must be an absolute path")
endif()
if(NOT EXISTS "${args_API_FILE}")
message(FATAL_ERROR "trailbook_ev_generate_rst_from_api: API_FILE must exist")
endif()
# Parameter HTML_PATH
# - is required
# - must be a relative path
if(NOT args_HTML_PATH)
message(FATAL_ERROR "trailbook_ev_generate_html_from_api: HTML_PATH argument is required")
endif()
if(IS_ABSOLUTE "${args_HTML_PATH}")
message(FATAL_ERROR "trailbook_ev_generate_html_from_api: HTML_PATH must be an relative path: ${args_HTML_PATH}")
endif()
get_target_property(
TRAILBOOK_INSTANCE_BUILD_DIRECTORY
trailbook_everest
TRAILBOOK_INSTANCE_BUILD_DIRECTORY
)
get_target_property(
TRAILBOOK_BUILD_DIRECTORY
trailbook_everest
TRAILBOOK_BUILD_DIRECTORY
)
get_filename_component(API_NAME ${args_API_FILE} NAME_WE)
set(ASYNC_TARGET_NAME ${API_NAME}_AsyncApi)
set(GENERATED_HTML_PATH ${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}/${args_HTML_PATH}/${API_NAME})
set(PREVIEW_HTML_PATH ${TRAILBOOK_BUILD_DIRECTORY}/latest/reference/api/${API_NAME})
set(COPY_FOR_PREVIEW_SENTINEL ${GENERATED_HTML_PATH}/copy_for_preview_sentinel)
add_custom_command(
OUTPUT
${GENERATED_HTML_PATH}/index.html
COMMAND
${ASYNCAPI_CMD} generate fromTemplate ${args_API_FILE} ${asyncapi-html-template_SOURCE_DIR} --force-write --use-new-generator --output=${GENERATED_HTML_PATH}
DEPENDS
${args_API_FILE}
COMMENT
"${API_NAME}: Generate AsyncApi HTML documentation"
)
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_html_from_api_${ASYNC_TARGET_NAME}
DEPENDS
${GENERATED_HTML_PATH}/index.html
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
asyncapi_cli_install_target
asyncapi_html_template_install_target
COMMENT
"Target to generate HTML files in ${GENERATED_HTML_PATH} from api definition ${args_API_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${GENERATED_HTML_PATH}/index.html
trailbook_${args_TRAILBOOK_NAME}_generate_html_from_api_${ASYNC_TARGET_NAME}
)
add_custom_command(
OUTPUT ${COPY_FOR_PREVIEW_SENTINEL}
COMMAND ${CMAKE_COMMAND} -E remove_directory "${PREVIEW_HTML_PATH}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PREVIEW_HTML_PATH}"
COMMAND ${CMAKE_COMMAND} -E copy_directory "${GENERATED_HTML_PATH}" "${PREVIEW_HTML_PATH}"
COMMAND ${CMAKE_COMMAND} -E touch ${COPY_FOR_PREVIEW_SENTINEL}
DEPENDS
${GENERATED_HTML_PATH}/index.html
COMMENT "Copy autogenerated AsyncAPI HTML files to a path where it is available for preview"
)
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_copy_asyncapi_html_to_preview_${ASYNC_TARGET_NAME}
DEPENDS ${COPY_FOR_PREVIEW_SENTINEL}
)
add_dependencies(trailbook_${args_TRAILBOOK_NAME}_copy_asyncapi_html_to_preview_${ASYNC_TARGET_NAME} trailbook_${args_TRAILBOOK_NAME}_generate_html_from_api_${ASYNC_TARGET_NAME})
add_dependencies(trailbook_${args_TRAILBOOK_NAME}_preview trailbook_${args_TRAILBOOK_NAME}_copy_asyncapi_html_to_preview_${ASYNC_TARGET_NAME})
endfunction()
function(trailbook_ev_generate_api_doc)
set(options)
set(one_value_args
TRAILBOOK_NAME
)
set(multi_value_args
API_FILES)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ev_generate_api_dock: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ev_generate_api_dock: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter API_FILES
# - is required
if(NOT API_FILES)
message(FATAL_ERROR "trailbook_ev_generate_api_dock: API_FILES argument is required")
endif()
get_target_property(
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
trailbook_everest
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
)
# Make a list of all API's names
set(API_NAMES "")
foreach(API_FILE ${API_FILES})
get_filename_component(API_NAME ${API_FILE} NAME_WE)
set(DESTINATION_SUBFOLDER "reference/api/")
list(APPEND API_NAMES "${API_NAME}")
_trailbook_ev_generate_html_from_api(
TRAILBOOK_NAME "everest"
API_FILE "${API_FILE}"
HTML_PATH "${DESTINATION_SUBFOLDER}"
)
endforeach()
list(JOIN API_NAMES "," CSV_API_NAMES)
set(INDEX_RST_FILE "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/${DESTINATION_SUBFOLDER}/autogenerated_api_index.rst")
set(PYTHON_SCRIPT "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_api_template.py")
set(TEMPLATES_DIRECTORY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/templates")
set(TEMPLATES_FILE "${TEMPLATES_DIRECTORY}/api_index.rst.jinja")
add_custom_command(
OUTPUT ${INDEX_RST_FILE}
COMMAND ${Python3_EXECUTABLE}
${PYTHON_SCRIPT}
--template-dir "${TEMPLATES_DIRECTORY}"
--template-file "${TEMPLATES_FILE}"
--apis "${CSV_API_NAMES}"
--target-file "${INDEX_RST_FILE}"
DEPENDS
${PYTHON_SCRIPT}
${TEMPLATES_FILE}
${TEMPLATES_DIRECTORY}/macros.jinja
${API_FILES}
COMMENT
"Generating RST index for API doc"
)
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_rst_api_index
DEPENDS
${INDEX_RST_FILE}
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Target to generate RST file ${INDEX_RST_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${INDEX_RST_FILE}
trailbook_${args_TRAILBOOK_NAME}_generate_rst_api_index
)
endfunction()

View File

@@ -0,0 +1,128 @@
# This macro is for internal use only
#
# It is used in the function trailbook_ev_generate_rst_from_interface().
# It adds an custom command to generate the RST file from the interface definition file
macro(_trailbook_ev_generate_rst_from_interface_generate_command)
get_filename_component(INTERFACE_NAME ${args_INTERFACE_FILE} NAME_WE)
set(GENERATED_FILE "${TRAILBOOK_EV_REFERENCE_INTERFACES_DIRECTORY}/${INTERFACE_NAME}.rst")
set(TEMPLATES_DIRECTORY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/templates")
add_custom_command(
OUTPUT
${GENERATED_FILE}
DEPENDS
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
${args_INTERFACE_FILE}
${TEMPLATES_DIRECTORY}/interface.rst.jinja
${TEMPLATES_DIRECTORY}/macros.jinja
COMMENT
"Generating RST file ${GENERATED_FILE} from interface definition ${args_INTERFACE_FILE}"
COMMAND
${Python3_EXECUTABLE}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
--template-dir "${TEMPLATES_DIRECTORY}"
--template-file "${TEMPLATES_DIRECTORY}/interface.rst.jinja"
--name "${INTERFACE_NAME}"
--data-file "${args_INTERFACE_FILE}"
--errors-yaml-path "${CMAKE_SOURCE_DIR}/errors/"
--target-file "${GENERATED_FILE}"
)
endmacro()
# This function generates an RST file from an interface definition file.
#
# Arguments:
# TRAILBOOK_NAME (required): Name of the trailbook instance.
# INTERFACE_FILE (required): Path to the interface definition file
# Usage:
# trailbook_ev_generate_rst_from_interface(
# TRAILBOOK_NAME <trailbook_name>
# INTERFACE_FILE <path_to_interface_definition_file>
# )
function(trailbook_ev_generate_rst_from_interface)
set(options)
set(one_value_args
TRAILBOOK_NAME
INTERFACE_FILE
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_interface: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ext_ev_generate_rst_from_interface: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter INTERFACE_FILE
# - is required
# - must be a absolute path
# - must exist
if(NOT args_INTERFACE_FILE)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_interface: INTERFACE_FILE argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_INTERFACE_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_interface: INTERFACE_FILE must be an absolute path")
endif()
if(NOT EXISTS "${args_INTERFACE_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_interface: INTERFACE_FILE must exist")
endif()
get_target_property(
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
)
get_target_property(
TRAILBOOK_CURRENT_BINARY_DIR
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_CURRENT_BINARY_DIR
)
get_target_property(
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
trailbook_${args_TRAILBOOK_NAME}
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
)
set(TRAILBOOK_EV_REFERENCE_DIRECTORY "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/reference")
set(TRAILBOOK_EV_REFERENCE_INTERFACES_DIRECTORY "${TRAILBOOK_EV_REFERENCE_DIRECTORY}/interfaces")
_trailbook_ev_generate_rst_from_interface_generate_command()
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_interface_${INTERFACE_NAME}
DEPENDS
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Target to generate RST file ${GENERATED_FILE} from interface definition ${args_INTERFACE_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_interface_${INTERFACE_NAME}
)
endfunction()

View File

@@ -0,0 +1,212 @@
# This macro is for internal use only
#
# It is used in the function trailbook_ev_generate_rst_from_manifest().
# It adds an custom command to generate the RST file from the manifest file
macro(_trailbook_ev_generate_rst_from_manifest_generate_command)
string(REPLACE "/manifest.yaml" ".rst" GENERATED_FILE "${TRAILBOOK_EV_REFERENCE_MODULES_DIRECTORY}/${RELATIVE_PATH_MANIFEST}")
get_filename_component(RELATIVE_PATH ${RELATIVE_PATH_MANIFEST} DIRECTORY)
set(GENERATED_FILE "${TRAILBOOK_EV_REFERENCE_MODULES_DIRECTORY}/${RELATIVE_PATH}/autogenerated.rst")
get_filename_component(GENERATED_PATH ${GENERATED_FILE} DIRECTORY)
set(TEMPLATES_DIRECTORY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/templates")
if(EXISTS "${MODULE_DIR}/docs/")
set(HANDWRITTEN_MODULE_DOC "--module-handwritten-doc" "index.inc")
endif()
add_custom_command(
OUTPUT
${GENERATED_FILE}
DEPENDS
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
${args_MANIFEST_FILE}
${TEMPLATES_DIRECTORY}/module.rst.jinja
${TEMPLATES_DIRECTORY}/macros.jinja
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Generating RST file ${GENERATED_FILE} from manifest ${args_MANIFEST_FILE}"
COMMAND
${CMAKE_COMMAND} -E make_directory "${GENERATED_PATH}"
COMMAND
${Python3_EXECUTABLE}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
--template-dir "${TEMPLATES_DIRECTORY}"
--template-file "${TEMPLATES_DIRECTORY}/module.rst.jinja"
--name "${MODULE_NAME}"
--data-file "${args_MANIFEST_FILE}"
--target-file "${GENERATED_FILE}"
${HANDWRITTEN_MODULE_DOC}
)
set(TOP_LEVEL_MODULE_DIRECTORY "${CMAKE_SOURCE_DIR}")
get_filename_component(CURRENT_RELATIVE_FOLDER_TMP "${RELATIVE_PATH_MANIFEST}" DIRECTORY)
get_filename_component(CURRENT_RELATIVE_FOLDER "modules/${CURRENT_RELATIVE_FOLDER_TMP}" DIRECTORY)
while(NOT CURRENT_RELATIVE_FOLDER STREQUAL "modules")
set(CURRENT_INDEX_DIRECTORY_CONCAT "${CMAKE_SOURCE_DIR}/${CURRENT_RELATIVE_FOLDER}")
get_filename_component(CURRENT_INDEX_DIRECTORY "${CURRENT_INDEX_DIRECTORY_CONCAT}" ABSOLUTE)
set(CURRENT_DEST_DIRECTORY_CONCAT "${TRAILBOOK_EV_REFERENCE_DIRECTORY}/${CURRENT_RELATIVE_FOLDER}")
get_filename_component(CURRENT_DEST_DIRECTORY "${CURRENT_DEST_DIRECTORY_CONCAT}" ABSOLUTE)
set(INDEX_FILE "${CURRENT_DEST_DIRECTORY}/autogenerated.rst")
get_filename_component(CURRENT_FOLDER_NAME "${CURRENT_INDEX_DIRECTORY}" NAME)
string(REPLACE "/" "_" INDEX_TARGET_SUFFIX "${CURRENT_RELATIVE_FOLDER}")
get_property(is_create_index_cmd_added DIRECTORY "${CURRENT_INDEX_DIRECTORY}" PROPERTY did_add_create_index_cmd SET)
if (NOT ${is_create_index_cmd_added})
message(VERBOSE "ADDING DEFINITION OF add_custom_command FOR THE INDEX FILE OF ${CURRENT_DEST_DIRECTORY} FOR ${INDEX_FILE}")
set(INDEX_TEMPLATE_FILE "${TEMPLATES_DIRECTORY}/module_ref_index.rst.jinja")
set(CUSTOM_TEMPLATE_SUBSTITUTION_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/DOCS_process_index_template_${INDEX_TARGET_SUFFIX}.py")
configure_file(
"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_index_template.py.in"
"${CUSTOM_TEMPLATE_SUBSTITUTION_SCRIPT}"
@ONLY
)
add_custom_command(
OUTPUT
"${INDEX_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CURRENT_DEST_DIRECTORY}"
COMMAND ${Python3_EXECUTABLE} "${CUSTOM_TEMPLATE_SUBSTITUTION_SCRIPT}"
DEPENDS
"${INDEX_TEMPLATE_FILE}"
"${CUSTOM_TEMPLATE_SUBSTITUTION_SCRIPT}"
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT "Rendering Jinja2 template for ${INDEX_TARGET_SUFFIX}"
VERBATIM
)
set_property(
DIRECTORY "${CURRENT_INDEX_DIRECTORY}"
PROPERTY did_add_create_index_cmd
"TRUE"
)
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_reference_index_for_module_${INDEX_TARGET_SUFFIX}
DEPENDS
"${INDEX_FILE}"
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Target to generate RST file ${INDEX_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
"${INDEX_FILE}"
trailbook_${args_TRAILBOOK_NAME}_generate_reference_index_for_module_${INDEX_TARGET_SUFFIX}
)
else()
message(VERBOSE "SKIPPING DEFINITION OF add_custom_command FOR THE INDEX FILE OF ${CURRENT_FOLDER_NAME}")
endif()
# go up one level
get_filename_component(CURRENT_RELATIVE_FOLDER "${CURRENT_RELATIVE_FOLDER}" DIRECTORY)
endwhile()
endmacro()
# This function generates an RST file from a manifest definition file.
# It takes the following arguments:
# TRAILBOOK_NAME (required): The name of the trailbook.
# MANIFEST_FILE (required): The absolute path to the manifest
# definition file.
# Usage:
# trailbook_ev_generate_rst_from_manifest(
# TRAILBOOK_NAME <trailbook_name>
# MANIFEST_FILE <path_to_manifest_definition_file>
# )
function(trailbook_ev_generate_rst_from_manifest)
set(options)
set(one_value_args
TRAILBOOK_NAME
MANIFEST_FILE
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_manifest: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ext_ev_generate_rst_from_manifest: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter MANIFEST_FILE
# - is required
# - must be a absolute path
# - must exist
if(NOT args_MANIFEST_FILE)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_manifest: MANIFEST_FILE argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_MANIFEST_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_manifest: MANIFEST_FILE must be an absolute path")
endif()
if(NOT EXISTS "${args_MANIFEST_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_manifest: MANIFEST_FILE must exist")
endif()
get_target_property(
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
)
get_target_property(
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
trailbook_${args_TRAILBOOK_NAME}
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
)
set(TRAILBOOK_EV_REFERENCE_DIRECTORY "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/reference")
set(TRAILBOOK_EV_REFERENCE_MODULES_DIRECTORY "${TRAILBOOK_EV_REFERENCE_DIRECTORY}/modules")
get_filename_component(MODULE_DIR ${args_MANIFEST_FILE} DIRECTORY)
get_filename_component(MODULE_NAME ${MODULE_DIR} NAME_WE)
file(RELATIVE_PATH RELATIVE_PATH_MANIFEST
"${CMAKE_SOURCE_DIR}/modules"
"${args_MANIFEST_FILE}"
)
_trailbook_ev_generate_rst_from_manifest_generate_command()
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_manifest_${MODULE_NAME}
DEPENDS
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Target to generate RST file ${GENERATED_FILE} from manifest definition ${args_MANIFEST_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_manifest_${MODULE_NAME}
)
endfunction()

View File

@@ -0,0 +1,117 @@
# This macro is for internal use only
#
# It is used in the function trailbook_ev_generate_rst_from_types().
# It adds an custom command to generate the RST file from the types definition file
macro(_trailbook_ev_generate_rst_from_types_generate_command)
get_filename_component(TYPES_NAME ${args_TYPES_FILE} NAME_WE)
set(GENERATED_FILE "${TRAILBOOK_EV_REFERENCE_TYPES_DIRECTORY}/${TYPES_NAME}.rst")
set(TEMPLATES_DIRECTORY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/templates")
add_custom_command(
OUTPUT
${GENERATED_FILE}
DEPENDS
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
${args_TYPES_FILE}
${TEMPLATES_DIRECTORY}/types.rst.jinja
${TEMPLATES_DIRECTORY}/macros.jinja
COMMENT
"Generating RST file ${GENERATED_FILE} from types definition ${args_TYPES_FILE}"
COMMAND
${Python3_EXECUTABLE}
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/process_template.py
--template-dir "${TEMPLATES_DIRECTORY}"
--template-file "${TEMPLATES_DIRECTORY}/types.rst.jinja"
--name "${TYPES_NAME}"
--data-file "${args_TYPES_FILE}"
--target-file "${GENERATED_FILE}"
)
endmacro()
# This function generates an RST file from a types definition file.
# It takes the following arguments:
# TRAILBOOK_NAME (required): The name of the trailbook.
# TYPES_FILE (required): The absolute path to the types definition file.
# Usage:
# trailbook_ev_generate_rst_from_types(
# TRAILBOOK_NAME <trailbook_name>
# TYPES_FILE <absolute_path_to_types_definition_file>
# )
function(trailbook_ev_generate_rst_from_types)
set(options)
set(one_value_args
TRAILBOOK_NAME
TYPES_FILE
)
set(multi_value_args)
cmake_parse_arguments(
"args"
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN}
)
# Parameter TRAILBOOK_NAME
# - is required
# - there should be a target named trailbook_<TRAILBOOK_NAME>
if(NOT args_TRAILBOOK_NAME)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_types: TRAILBOOK_NAME argument is required")
endif()
if(NOT TARGET trailbook_${args_TRAILBOOK_NAME})
message(
FATAL_ERROR
"trailbook_ext_ev_generate_rst_from_types: No target named trailbook_${args_TRAILBOOK_NAME} found."
" Did you forget to call add_trailbook() first?"
)
endif()
# Parameter TYPES_FILE
# - is required
# - must be a absolute path
# - must exist
if(NOT args_TYPES_FILE)
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_types: TYPES_FILE argument is required")
endif()
if(NOT IS_ABSOLUTE "${args_TYPES_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_types: TYPES_FILE must be an absolute path")
endif()
if(NOT EXISTS "${args_TYPES_FILE}")
message(FATAL_ERROR "trailbook_ext_ev_generate_rst_from_types: TYPES_FILE must exist")
endif()
get_target_property(
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
trailbook_${args_TRAILBOOK_NAME}
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY
)
get_target_property(
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
trailbook_${args_TRAILBOOK_NAME}
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
)
set(TRAILBOOK_EV_REFERENCE_DIRECTORY "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/reference")
set(TRAILBOOK_EV_REFERENCE_TYPES_DIRECTORY "${TRAILBOOK_EV_REFERENCE_DIRECTORY}/types")
_trailbook_ev_generate_rst_from_types_generate_command()
add_custom_target(
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_types_${TYPES_NAME}
DEPENDS
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_stage_prepare_sphinx_source_after
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
COMMENT
"Target to generate RST file ${GENERATED_FILE} from types definition ${args_TYPES_FILE}"
)
set_property(
TARGET
trailbook_${args_TRAILBOOK_NAME}
APPEND
PROPERTY
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
${GENERATED_FILE}
trailbook_${args_TRAILBOOK_NAME}_generate_rst_from_types_${TYPES_NAME}
)
endfunction()

View File

@@ -0,0 +1,112 @@
import argparse
import jinja2
from pathlib import Path
def rst_indent(input):
lines = input.splitlines()
lines = [f"| {line}\r\n" for line in lines]
return "".join(lines)
def make_rst_ref(input):
output = input.replace("/", "")
output = output.replace("#", "-")
return output
def main():
parser = argparse.ArgumentParser(description="Generate RST index from file list")
parser.add_argument(
'--template-dir',
type=Path,
dest='template_dir',
action='store',
required=True,
help='Directory containing the Jinja2 template files'
)
parser.add_argument(
'--template-file',
type=Path,
dest='template_file',
action='store',
required=True,
help='Jinja2 template file to process'
)
parser.add_argument(
'--apis',
type=str,
dest='apis',
action='store',
required=True,
help='Comma separated list of api names'
)
parser.add_argument(
'--target-file',
type=Path,
dest='target_file',
action='store',
required=True,
help='Output file for the processed template'
)
args = parser.parse_args()
if not args.template_dir.is_absolute():
raise ValueError("Template directory path must be absolute")
if not args.template_dir.exists():
raise ValueError("Template directory does not exist")
if not args.template_dir.is_dir():
raise ValueError("Template directory path is not a directory")
if not args.template_file.is_absolute():
raise ValueError("Template file path must be absolute")
if not args.template_file.exists():
raise ValueError("Template file does not exist")
if not args.template_file.is_file():
raise ValueError("Template file path is not a file")
if not args.template_file.is_relative_to(args.template_dir):
raise ValueError("Template file path is not relative to template directory")
if not args.target_file.is_absolute():
raise ValueError("Target file path must be absolute")
if args.target_file.suffix != '.rst':
raise ValueError("Target file must have a .rst extension")
if not args.target_file.parent.exists():
args.target_file.parent.mkdir(parents=True, exist_ok=True)
# Split comma-separated string back into a list
api_list = args.apis.split(',')
# turn list into dict
apis = []
for api_name in api_list:
if not api_name:
continue # Skip empty strings
apis.append({"name": api_name, "path": api_name})
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(args.template_dir),
trim_blocks=True,
lstrip_blocks=True
)
env.filters['rst_indent'] = rst_indent
env.filters['make_rst_ref'] = make_rst_ref
template_file_name = args.template_file.relative_to(args.template_dir)
template = env.get_template(str(template_file_name))
output = template.render(
apis=apis
)
args.target_file.write_text(output)
if __name__ == "__main__":
try:
main()
except Exception as e:
print(f"Error: {e}")
exit(1)

View File

@@ -0,0 +1,14 @@
import jinja2
template_file = r"@INDEX_TEMPLATE_FILE@"
output_file = r"@INDEX_FILE@"
substitutions = {
"HEADLINE": "@CURRENT_FOLDER_NAME@",
}
with open(template_file, 'r') as f:
template = jinja2.Template(f.read())
with open(output_file, 'w') as f:
f.write(template.render(**substitutions))

View File

@@ -0,0 +1,192 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# SPDX-License-Identifier: Apache-2.0
# Copyright Pionix GmbH and Contributors to EVerest
#
"""
author: andreas.heinrich@pionix.de
This script processes a template file with Jinja2 and YAML data.
"""
import argparse
import jinja2
import yaml
from pathlib import Path
def rst_indent(input):
lines = input.splitlines()
lines = [f"| {line}\r\n" for line in lines]
return "".join(lines)
def make_rst_ref(input):
output = input.replace("/", "")
output = output.replace("#", "-")
return output
def literal_rst_filter(value):
"""Wraps a string in double backticks to treat it as a literal in RST."""
str_value = str(value)
has_trailing_whitespace = (str_value != str_value.rstrip())
cleaned_value = str_value.rstrip()
parts = cleaned_value.split(':', 1)
if len(parts) == 2 and parts[0] == "pattern":
formatted_value = f"{parts[0]}:``{parts[1].lstrip()}``"
else:
formatted_value = cleaned_value
if has_trailing_whitespace:
return formatted_value + '\r\n'
else:
return formatted_value
def main():
parser = argparse.ArgumentParser(description='Processes a template file with Jinja2 and YAML data.')
parser.add_argument(
'--template-dir',
type=Path,
dest='template_dir',
action='store',
required=True,
help='Directory containing the Jinja2 template files'
)
parser.add_argument(
'--template-file',
type=Path,
dest='template_file',
action='store',
required=True,
help='Jinja2 template file to process'
)
parser.add_argument(
'--name',
type=str,
dest='name',
action='store',
required=True,
help='Name to be used in the template rendering'
)
parser.add_argument(
'--data-file',
type=Path,
dest='data_file',
action='store',
required=True,
help='YAML file containing data for the template'
)
parser.add_argument(
'--module-handwritten-doc',
type=Path,
dest='module_handwritten_doc',
action='store',
help='Path to the handwritten module documentation if it exists'
)
parser.add_argument(
'--errors-yaml-path',
type=Path,
dest='errors_path',
action='store',
help='Path to the error definition yaml files'
)
parser.add_argument(
'--target-file',
type=Path,
dest='target_file',
action='store',
required=True,
help='Output file for the processed template'
)
args = parser.parse_args()
if not args.template_dir.is_absolute():
raise ValueError("Template directory path must be absolute")
if not args.template_dir.exists():
raise ValueError("Template directory does not exist")
if not args.template_dir.is_dir():
raise ValueError("Template directory path is not a directory")
if not args.template_file.is_absolute():
raise ValueError("Template file path must be absolute")
if not args.template_file.exists():
raise ValueError("Template file does not exist")
if not args.template_file.is_file():
raise ValueError("Template file path is not a file")
if not args.template_file.is_relative_to(args.template_dir):
raise ValueError("Template file path is not relative to template directory")
if not args.data_file.is_absolute():
raise ValueError("Data file path must be absolute")
if not args.data_file.exists():
raise ValueError("Data file does not exist")
if not args.data_file.is_file():
raise ValueError("Data file path is not a file")
if args.data_file.suffix not in ['.yml', '.yaml']:
raise ValueError("Data file must have a .yml or .yaml extension")
if not args.target_file.is_absolute():
raise ValueError("Target file path must be absolute")
if args.target_file.suffix != '.rst':
raise ValueError("Target file must have a .rst extension")
if args.errors_path:
if not args.errors_path.is_absolute():
raise ValueError("Errors yaml directory path must be absolute")
if not args.errors_path.exists():
raise ValueError(f"Errors yaml directory '{args.errors_path}' does not exist")
if not args.errors_path.is_dir():
raise ValueError("Errors yaml directory path is not a directory")
if not args.target_file.parent.exists():
args.target_file.parent.mkdir(parents=True, exist_ok=True)
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(args.template_dir),
trim_blocks=True,
lstrip_blocks=True
)
env.filters['rst_indent'] = rst_indent
env.filters['make_rst_ref'] = make_rst_ref
env.filters['literal_rst'] = literal_rst_filter
template_file_name = args.template_file.relative_to(args.template_dir)
template = env.get_template(str(template_file_name))
data=yaml.safe_load(args.data_file.read_text())
data["errors_sanitized"] = {}
data['error_definitions'] = {}
if args.errors_path and "errors" in data.keys():
for err in data["errors"]:
error_path = err['reference'].split('#')[0]
filename = Path(args.errors_path, error_path.split('/')[-1])
with open(filename.with_suffix(".yaml")) as f:
text = f.read()
yaml_content = yaml.safe_load(text)
data['error_definitions'][error_path] = {}
for err_def in yaml_content['errors']:
data['error_definitions'][error_path][err_def['name']] = err_def['description']
if not error_path in data["errors_sanitized"]:
data["errors_sanitized"][error_path] = []
if len(err['reference'].split('#')) > 1:
data["errors_sanitized"][error_path].append(err['reference'].split('#')[1][1:])
else:
for error in data['error_definitions'][error_path].keys():
data["errors_sanitized"][error_path].append(error)
output = template.render(
name=args.name,
handwritten_module_doc=args.module_handwritten_doc,
data=data,
)
args.target_file.write_text(output)
if __name__ == "__main__":
try:
main()
except Exception as e:
print(f"Error: {e}")
exit(1)

View File

@@ -0,0 +1,12 @@
{% import 'macros.jinja' as funcs %}
.. toctree::
:maxdepth: 1
:glob:
{{ funcs.explicit_target('everest_api') }}
{{ funcs.h1("EVerest API Specification") }}
{% for item in apis %}
* `{{ item.name }} <{{ item.path }}/index.html>`_
{% endfor %}

View File

@@ -0,0 +1,24 @@
{% import 'macros.jinja' as funcs %}
:orphan:
{{ funcs.explicit_target('everest_interfaces_' + name) }}
{{ funcs.h1(name) }}
{{ data.description | rst_indent() }}
{% if 'documentation' in interface %}
{{ funcs.documentation(data.documentation) | rst_indent() -}}
{% endif %}
{% if data.vars %}
{{ funcs.h2('Variables') -}}
{{ funcs.vars(data.vars.items(), False) | rst_indent() -}}
{% endif %}
{% if data.cmds %}
{{ funcs.h2('Commands') -}}
{{ funcs.cmds(data.cmds.items()) | rst_indent() -}}
{% endif %}
{% if data.errors %}
{{ funcs.h2('Errors') -}}
{{ funcs.error_categories(data.errors_sanitized, data.error_definitions) | rst_indent() -}}
{% endif %}

View File

@@ -0,0 +1,359 @@
{#################################}
{### General json macros ###}
{#################################}
{### Renders a key-value-pair ###}
{% macro keyvalue(key, value) %}
{{ key }}:{{ value }}
{% endmacro %}
{### Renders a sequence ###}
{% macro sequence(key, data) %}
{{ key }}:
{% for entry in data %}
- {{ entry }}
{% endfor %}
{% endmacro %}
{### Renders a mapping ###}
{% macro mapping(key, data, ignore_keys, render_key) %}
{% set indent_width = 0 %}
{% if render_key %}
{% set indent_width = 1 %}
{{ key }}:
{% endif %}
{% for sub_key, sub_data in data %}
{% if not sub_key in ignore_keys %}
{% if sub_data is mapping %}
{{ mapping(sub_key, sub_data.items(), [], True) | indent(indent_width, True) -}}
{% elif sub_data is string %}
{{ keyvalue(sub_key, sub_data) | indent(indent_width, True) -}}
{% elif sub_data is sequence %}
{{ sequence(sub_key, sub_data) | indent(indent_width, True) -}}
{% endif %}
{% endif %}
{% endfor %}
{% endmacro %}
{#################################}
{### General RST macros ###}
{#################################}
{### Make H1 headline ###}
{% macro h1(title) %}
{% set title_length = title|length %}
{{ '#' * title_length }}
{{ title }}
{{ '#' * title_length }}
{% endmacro %}
{### Make H2 headline ###}
{% macro h2(title) %}
{% set title_length = title|length %}
{{ '*' * title_length }}
{{ title }}
{{ '*' * title_length }}
{% endmacro %}
{### Make H3 headline ###}
{% macro h3(title) %}
{% set title_length = title|length %}
{{ title }}
{{ '=' * title_length }}
{% endmacro %}
{### Make H4 headline ###}
{% macro h4(title) %}
{% set title_length = title|length %}
{{ title }}
{{ '-' * title_length }}
{% endmacro %}
{### Make H5 headline ###}
{% macro h5(title) %}
{% set title_length = title|length %}
{{ title }}
{{ '^' * title_length }}
{% endmacro %}
{### Make H6 headline ###}
{% macro h6(title) %}
{% set title_length = title|length %}
{{ title }}
{{ '"' * title_length }}
{% endmacro %}
{### Make explicit target ###}
{% macro explicit_target(target_name) %}
.. _{{ target_name | make_rst_ref() }}:
{% endmacro %}
{### References an explicit target ###}
{% macro ref(target_name, text) %}
:ref:`{{ text }} <{{ target_name | make_rst_ref() }}>`
{%- endmacro %}
{#################################}
{### Interface.json macros ###}
{#################################}
{### Renders a multiline documentation ###}
{% macro documentation(lines) %}
{% for line in lines %}
{{ line }}
{% endfor %}
{% endmacro %}
{### Renders a single var ###}
{% macro var(var_name, var_data, show_required=true, required=None) %}
{% if required == None %}
{% set required = 'default' not in var_data %}
{% endif %}
{% set optional = '' %}
{% if show_required == true %}
{% if required == true %}
{% set optional = '<required>' %}
{% elif required == false %}
{% set optional = '<optional>' %}
{% else %}
{% include "required needs to be set" %}
{% endif %}
{% endif %}
{% set var_type = var_data.type %}
{% if not var_data.type %}
{% set var_type = "string/object" %}
{% endif %}
**{{ var_name }}**: *{{ var_type }}* {{ optional }}
{%- if '$ref' in var_data %}{{ ' (' + ref(var_data['$ref'], var_data['$ref'] | make_rst_ref()) + ')' }}{% endif +%}
{# Add default value for config entries #}
{% if 'default' in var_data %}
{% if var_data.default is string %}
{% set var_default = "\"" + var_data.default + "\"" %}
{% else %}
{% set var_default = var_data.default %}
{% endif %}
*default: {{ var_default }}*
{% endif %}
{% if var_data.description %}
{% for line in var_data.description.split('\n') %}
{% if line != '' %}
{{ line }}
{% endif %}
{% endfor %}
{% endif %}
{% if 'documentation' in var_data %}
{{ documentation(var_data['documentation']) | indent(1, True) -}}
{% endif %}
{% set ignore_keys = ['default', 'description', 'type', 'properties', 'documentation', '$ref', 'required', 'items'] %}
{% set mapping_result = mapping( var_name, var_data.items(), ignore_keys, False) %}
{% if mapping_result != '' %}
{{ mapping_result | literal_rst | indent(1, True) -}}
{% endif %}
{% if var_data.type == 'object' and 'properties' in var_data %}
properties:
{% if not 'required' in var_data %}
{% set all_required = True %}
{% set required_array = [] %}
{% else %}
{% set all_required = False %}
{% set required_array = var_data.required %}
{% endif %}
{{ vars(var_data.properties.items(), True, required_array, all_required) | indent(2, True) -}}
{% endif %}
{% if var_data.type == 'array' and 'items' in var_data %}
{{ var('array_item', var_data['items'], False, True) | indent(1, True) -}}
{% endif %}
{% endmacro %}
{### Renders a list of vars ###}
{% macro vars(vars, show_required=true, required=[], all_required=False) %}
{% for var_name, var_data in vars %}
{% if show_required == true %}
{% if all_required %}
{% set is_required = True %}
{% else %}
{% set is_required = var_name in required %}
{% endif %}
{% else %}
{% set is_required = None %}
{% endif %}
{{ var(var_name, var_data, show_required, is_required) -}}
{% endfor %}
{% endmacro %}
{### Renders cmd result ###}
{% macro cmd_result(result_data) %}
{{ var('Result', result_data, False) -}}
{% endmacro %}
{### Renders single cmd argument ###}
{% macro cmd_argument(arg_name, arg_data) %}
{{ var(arg_name, arg_data, True) -}}
{% endmacro %}
{### Renders cmd arguments ###}
{% macro cmd_arguments(args) %}
{% for arg_name, arg_data in args %}
{{ cmd_argument(arg_name, arg_data) -}}
{% endfor %}
{% endmacro %}
{### Renders a single cmd ###}
{% macro cmd(cmd_name, cmd_data) %}
{% if 'result' in cmd_data %}
{% set type_string = cmd_data.result.type %}
{% else %}
{% set type_string = 'void' %}
{% endif %}
**{{ cmd_name }}**: *{{ type_string }}*
{{ cmd_data.description }}
{% if 'arguments' in cmd_data %}
{{ cmd_arguments(cmd_data.arguments.items()) | indent(1, True) -}}
{% endif %}
{% if 'result' in cmd_data %}
{{ cmd_result(cmd_data['result']) | indent(1, True) -}}
{% endif %}
{% if 'documentation' in cmd_data %}
{{ documentation(cmd_data['documentation']) | indent(1, True) -}}
{% endif %}
{% endmacro %}
{### Renders a list of cmds ###}
{% macro cmds(cmds) %}
{% for cmd_name, cmd_data in cmds %}
{{ cmd(cmd_name, cmd_data) -}}
{% endfor %}
{% endmacro %}
{### Renders a list of errors ###}
{% macro errors(errs, definitions) %}
{% for err in errs %}
**{{ err }}** : {{ definitions[err] }}
{% endfor %}
{% endmacro %}
{### Renders a list of error_categories ###}
{% macro error_categories(categories, error_definitions) %}
{% for cat in categories %}
**{{ cat }}** :
{{ errors(categories[cat], error_definitions[cat]) | indent(1, True) -}}
{% endfor %}
{% endmacro %}
{#################################}
{### types.json macros ###}
{#################################}
{### Renders a single type ###}
{% macro type(type_name, type_data, file_name) %}
{% set target_name = '/' + file_name + '#/' + type_name %}
{{ explicit_target(target_name) -}}
{{ var(type_name, type_data, False) | rst_indent() -}}
{% endmacro %}
{### Renders a list of types ###}
{% macro types(types, file_name) %}
{% for type_name, type_data in types %}
{{ type(type_name, type_data, file_name) -}}
{% endfor %}
{% endmacro %}
{#################################}
{### manifest.json macros ###}
{#################################}
{### Renders a single config entry ###}
{% macro config_entry(name, data) %}
{{ var(name, data, True) -}}
{% endmacro %}
{### Renders a list of config entries ###}
{% macro config(config_data) %}
{% for entry_name, entry_data in config_data %}
{{ config_entry(entry_name, entry_data) -}}
{% endfor %}
{% endmacro %}
{### Renders a single impl ###}
{% macro impl(name, data) %}
{% set interface_target = 'everest_interfaces_' + data.interface %}
**{{ name }}**: {{ ref(interface_target, data.interface) }}
{{ data.description }}
{% if 'documentation' in data %}
{{ documentation(data['documentation']) | indent(1, True) -}}
{% endif %}
{% set ignore_keys = ['description', 'interface', 'documentation', 'config'] %}
{% set mapping_result = mapping( name, data.items(), ignore_keys, False) %}
{% if mapping_result != '' %}
X
{{ mapping_result | indent(1, True) -}}
Y
{% endif %}
{% if 'config' in data %}
**config:**
{{ config(data.config.items()) | indent(2, True) -}}
{% endif %}
{% endmacro %}
{### Renders a list of impls ###}
{% macro impls(impls) %}
{% for impl_name, impl_data in impls %}
{{ impl(impl_name, impl_data) -}}
{% endfor %}
{% endmacro %}
{### Renders a single requirement ###}
{% macro req(name, data) %}
{% if not 'min_connections' in data %}
{% set min_conns = 1 %}
{% else %}
{% set min_conns = data.min_connections %}
{% endif %}
{% if not 'max_connections' in data %}
{% set max_conns = 1 %}
{% else %}
{% set max_conns = data.max_connections %}
{% endif %}
{% set conns = min_conns|string + ".." + max_conns|string %}
{% if min_conns == max_conns %}
{% set conns = min_conns|string %}
{% endif %}
{% set interface_target = 'everest_interfaces_' + data.interface %}
**{{ name }}**: {{ ref(interface_target, data.interface) }} {{conns}}
{% set ignore_keys = ['interface'] %}
{% set mapping_result = mapping( name, data.items(), ignore_keys, False) %}
{% if mapping_result != '' %}
{{ mapping_result | indent(1, True) -}}
{% endif %}
{% endmacro %}
{### Renders a list of requirements ###}
{% macro reqs(reqs) %}
{% for req_name, req_data in reqs %}
{{ req(req_name, req_data) -}}
{% endfor %}
{% endmacro %}
{### Renders metadata ###}
{% macro metadata(data) %}
{{ h2('Metadata') -}}
{{ h3('Authors') -}}
{% for author in data['authors'] %}
| {{ author }}
{% endfor %}
{{ h3('License') -}}
| {{ data['license'] }}
{% set ignore_keys = ['authors', 'license'] %}
{% set mapping_result = mapping('metadata', data.items(), ignore_keys, False) %}
{% if mapping_result != '' %}
{{ h3('Misc') -}}
{{ mapping_result | indent(1, True) | rst_indent() -}}
{% endif %}
{% endmacro %}

View File

@@ -0,0 +1,32 @@
{% import 'macros.jinja' as funcs %}
{{ funcs.explicit_target('everest_modules_' + name) -}}
{{ funcs.h1(name) -}}
{{ data.description | rst_indent() }}
{% if 'documentation' in manifest %}
{{ funcs.documentation(data.documentation) | rst_indent() -}}
{% endif %}
{% if handwritten_module_doc %}
{{ funcs.h2("Handwritten Documentation") }}
.. include:: {{ handwritten_module_doc }}
{% endif %}
{{ funcs.h2("Auto-Generated Reference") }}
{% if data.config %}
{{ funcs.h3('Module Configuration') -}}
{{ funcs.config(data.config.items()) | rst_indent() -}}
{% endif %}
{% if data.provides %}
{{ funcs.h3('Provides') -}}
{{ funcs.impls(data.provides.items()) | rst_indent() -}}
{% endif %}
{% if data.requires %}
{{ funcs.h3('Requirements') -}}
{{ funcs.reqs(data.requires.items()) | rst_indent() -}}
{% endif %}
{{ funcs.metadata(data.metadata) -}}

View File

@@ -0,0 +1,9 @@
=========================================================
{{ HEADLINE }}
=========================================================
.. toctree::
:maxdepth: 1
:glob:
*/autogenerated

View File

@@ -0,0 +1,10 @@
{% import 'macros.jinja' as funcs %}
:orphan:
{{ funcs.explicit_target('everest_types_' + name) }}
{{ funcs.h1(name) }}
{{ data.description}}
{% if 'documentation' in types %}
{{ funcs.documentation(data.documentation) -}}
{% endif %}
{{ funcs.types(data.types.items(), name) }}

View File

@@ -0,0 +1,13 @@
set(PACKAGE_VERSION 0.1.0)
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
elseif(PACKAGE_FIND_VERSION_MAJOR STREQUAL "0")
if(PACKAGE_FIND_VERSION_MINOR GREATER "1")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
endif()
else()
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

View File

@@ -0,0 +1,13 @@
find_package(
trailbook
0.1.0
REQUIRED
PATHS "${CMAKE_SOURCE_DIR}/cmake"
)
include("${CMAKE_CURRENT_LIST_DIR}/add-module-handwritten-doc.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/generate-api-docs.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/generate-rst-from-interface.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/generate-rst-from-types.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/generate-rst-from-manifest.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/create-snapshot.cmake")