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:
105
tools/EVerest-main/cmake/CheckAtomic.cmake
Normal file
105
tools/EVerest-main/cmake/CheckAtomic.cmake
Normal file
@@ -0,0 +1,105 @@
|
||||
# SPDX-FileCopyrightText: 2003-2018 University of Illinois at Urbana-Champaign.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
CheckAtomic
|
||||
-----------
|
||||
|
||||
Check if the compiler supports std:atomic out of the box or if libatomic is
|
||||
needed for atomic support. If it is needed, ``HAVE_CXX_ATOMICS_WITH_LIB``
|
||||
or ``HAVE_CXX_ATOMICS64_WITH_LIB`` set to ``ON``.
|
||||
|
||||
Since 5.75.0.
|
||||
#]=======================================================================]
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
|
||||
check_cxx_source_compiles("
|
||||
#include <atomic>
|
||||
std::atomic<int> x;
|
||||
std::atomic<short> y;
|
||||
std::atomic<char> z;
|
||||
int main() {
|
||||
++z;
|
||||
++y;
|
||||
return ++x;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction()
|
||||
|
||||
function(check_working_cxx_atomics64 varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
|
||||
check_cxx_source_compiles("
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<uint64_t> x (0);
|
||||
int main() {
|
||||
uint64_t i = x.load(std::memory_order_relaxed);
|
||||
x.is_lock_free();
|
||||
return 0;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction()
|
||||
|
||||
# Check for (non-64-bit) atomic operations.
|
||||
if(MSVC)
|
||||
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)
|
||||
else()
|
||||
# First check if atomics work without the library.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
endif()
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if(HAVE_LIBATOMIC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for 64 bit atomic operations.
|
||||
if(MSVC)
|
||||
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
|
||||
else()
|
||||
# First check if atomics work without the library.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"
|
||||
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
endif()
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
|
||||
if(HAVE_CXX_LIBATOMICS64)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
24
tools/EVerest-main/cmake/CreateAuxSymlink.cmake
Normal file
24
tools/EVerest-main/cmake/CreateAuxSymlink.cmake
Normal file
@@ -0,0 +1,24 @@
|
||||
list(APPEND AUX_DIRS interfaces)
|
||||
|
||||
foreach(IT IN LISTS AUX_DIRS)
|
||||
set(IT_DST "${CMAKE_INSTALL_PREFIX}/${IT}")
|
||||
|
||||
if(IS_DIRECTORY ${IT_DST} AND NOT IS_SYMLINK ${IT_DST})
|
||||
message(
|
||||
FATAL_ERROR "\
|
||||
I won't be able create the symlink, because the link target ${IT_DST} \
|
||||
already exists and I don't want to delete it. Probably you executed \
|
||||
the INSTALL target already without symlinks. Please remove the \
|
||||
directory manually.\
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
install(
|
||||
CODE "
|
||||
execute_process(COMMAND cmake -E create_symlink
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${IT}
|
||||
${IT_DST})
|
||||
"
|
||||
)
|
||||
endforeach()
|
||||
20
tools/EVerest-main/cmake/CreateModuleSymlink.cmake
Normal file
20
tools/EVerest-main/cmake/CreateModuleSymlink.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
set(MODULE_LINK_PATH "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}")
|
||||
|
||||
if(IS_DIRECTORY ${MODULE_LINK_PATH} AND NOT IS_SYMLINK ${MODULE_LINK_PATH})
|
||||
message(
|
||||
FATAL_ERROR "\
|
||||
I won't be able create the symlink, because the link target \
|
||||
${MODULE_LINK_PATH} already exists and I don't want to delete \
|
||||
it. Probably you executed the INSTALL target already without \
|
||||
symlinks. Please remove the directory manually.\
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
install(
|
||||
CODE "
|
||||
execute_process(COMMAND cmake -E create_symlink
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${MODULE_LINK_PATH})
|
||||
"
|
||||
)
|
||||
2
tools/EVerest-main/cmake/assets/BUILD.bazel
Normal file
2
tools/EVerest-main/cmake/assets/BUILD.bazel
Normal file
@@ -0,0 +1,2 @@
|
||||
exports_files(["logging.ini"])
|
||||
|
||||
24
tools/EVerest-main/cmake/assets/logging.ini
Normal file
24
tools/EVerest-main/cmake/assets/logging.ini
Normal file
@@ -0,0 +1,24 @@
|
||||
# for documentation on this file format see:
|
||||
# https://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.setup.filter_formatter
|
||||
|
||||
[Core]
|
||||
DisableLogging=false
|
||||
|
||||
# To get debug logs of only one module, add the "%Process% contains" filter, e.g.:
|
||||
#
|
||||
# "(%Process% contains OCPP201 and %Severity% >= DEBG)"
|
||||
#
|
||||
# whereas "OCPP201" is the value of the field `active_modules.NAME.module` in the respective /config/config-*.yaml.
|
||||
Filter="%Severity% >= INFO"
|
||||
|
||||
[Sinks.Console]
|
||||
Destination=Console
|
||||
# Filter="%Target% contains \"MySink1\""
|
||||
Format="%TimeStamp% [%Severity%] \033[1;32m%Process%\033[0m \033[1;36m%function%\033[0m \033[1;30m%file%:\033[0m\033[1;32m%line%\033[0m: %Message%"
|
||||
Asynchronous=false
|
||||
AutoFlush=true
|
||||
SeverityStringColorDebug="\033[1;30m"
|
||||
SeverityStringColorInfo="\033[1;37m"
|
||||
SeverityStringColorWarning="\033[1;33m"
|
||||
SeverityStringColorError="\033[1;31m"
|
||||
SeverityStringColorCritical="\033[1;35m"
|
||||
17
tools/EVerest-main/cmake/assets/run_nodered_template.sh.in
Executable file
17
tools/EVerest-main/cmake/assets/run_nodered_template.sh.in
Executable file
@@ -0,0 +1,17 @@
|
||||
# In the following a volume is created to contain the nodered config, this is done to
|
||||
# allow starting the nodered container from inside a devcontainer
|
||||
|
||||
# Create docker volume to contain nodered config
|
||||
docker volume create everest-nodered-config-volume
|
||||
|
||||
# Create temporarily container to copy nodered config into the created volume
|
||||
docker run --name everest-nodered-config-container -v everest-nodered-config-volume:/data debian:12-slim chown -R 1000:1000 /data
|
||||
|
||||
# Copy nodered config to the created volume with the temporarily created container
|
||||
docker cp @FLOW_FILE@ everest-nodered-config-container:/data/flows.json
|
||||
|
||||
# Remove temporarily container
|
||||
docker rm everest-nodered-config-container
|
||||
|
||||
# Start nodered container with the volume mounted to /data
|
||||
docker run -it --rm --network host --name everest_nodered --mount type=volume,source=everest-nodered-config-volume,target=/data ghcr.io/everest/everest-dev-environment/nodered:docker-images-v0.1.0
|
||||
7
tools/EVerest-main/cmake/assets/run_template.sh.in
Executable file
7
tools/EVerest-main/cmake/assets/run_template.sh.in
Executable file
@@ -0,0 +1,7 @@
|
||||
LD_LIBRARY_PATH=@LD_LIBRARY_VAR@:$LD_LIBRARY_PATH \
|
||||
PATH=@PATH_VAR@:$PATH \
|
||||
manager \
|
||||
--prefix @CMAKE_INSTALL_PREFIX@ \
|
||||
--conf @CONFIG_FILE@ \
|
||||
@ADDITIONAL_ARGUMENTS@
|
||||
$@
|
||||
2
tools/EVerest-main/cmake/assets/run_tmux_template.sh.in
Executable file
2
tools/EVerest-main/cmake/assets/run_tmux_template.sh.in
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
@HELPER_PREFIX@/run_tmux_helper.sh @CONFIG_FILE@ @CMAKE_INSTALL_PREFIX@
|
||||
25
tools/EVerest-main/cmake/compatibility/boost.cmake
Normal file
25
tools/EVerest-main/cmake/compatibility/boost.cmake
Normal file
@@ -0,0 +1,25 @@
|
||||
# compatibility for Boost >= 1.89 while keeping backwards compatibility with existing code
|
||||
if(Boost_VERSION_STRING VERSION_LESS "1.69.0")
|
||||
# Boost.System is a header only library only from 1.69.0
|
||||
find_package(Boost
|
||||
COMPONENTS
|
||||
system
|
||||
REQUIRED
|
||||
)
|
||||
endif()
|
||||
|
||||
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL "1.89.0")
|
||||
# starting from Boost 1.89.0 the included compatibility layer is removed
|
||||
# here we re-introduce a very simplified version of it
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/compatibility/boost_systemConfig.cmake"
|
||||
${CMAKE_BINARY_DIR}/boost_system/boost_systemConfig.cmake
|
||||
COPYONLY
|
||||
)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/compatibility/boost_systemConfigVersion.cmake"
|
||||
${CMAKE_BINARY_DIR}/boost_system/boost_systemConfigVersion.cmake
|
||||
COPYONLY
|
||||
)
|
||||
set(boost_system_DIR ${CMAKE_BINARY_DIR}/boost_system CACHE PATH "")
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
if(NOT TARGET Boost::system)
|
||||
add_library(everest_boost_system_target INTERFACE)
|
||||
add_library(Boost::system ALIAS everest_boost_system_target)
|
||||
endif()
|
||||
@@ -0,0 +1,4 @@
|
||||
set(boost_system_VERSION "${Boost_VERSION_STRING}")
|
||||
set(PACKAGE_VERSION "${Boost_VERSION_STRING}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
37
tools/EVerest-main/cmake/config-run-nodered-script.cmake
Normal file
37
tools/EVerest-main/cmake/config-run-nodered-script.cmake
Normal file
@@ -0,0 +1,37 @@
|
||||
function(generate_nodered_run_script)
|
||||
|
||||
if (NOT EVEREST_ENABLE_RUN_SCRIPT_GENERATION)
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
set(options "")
|
||||
set(one_value_args
|
||||
FLOW
|
||||
OUTPUT
|
||||
)
|
||||
set(multi_value_args "")
|
||||
|
||||
cmake_parse_arguments(OPTNS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
if (OPTNS_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} got unknown argument(s): ${OPTNS_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (NOT OPTNS_FLOW)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} requires FLOW parameter for the flow name")
|
||||
endif()
|
||||
|
||||
set(FLOW_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config-${OPTNS_FLOW}-flow.json")
|
||||
if (NOT EXISTS ${FLOW_FILE})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: flow file '${FLOW_FILE}' does not exist")
|
||||
endif()
|
||||
|
||||
set(SCRIPT_OUTPUT_PATH "${CMAKE_BINARY_DIR}/run-scripts")
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/nodered-${OPTNS_FLOW}.sh")
|
||||
if (OPTNS_OUTPUT)
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/nodered-${OPTNS_OUTPUT}.sh")
|
||||
endif()
|
||||
|
||||
configure_file("${EVEREST_CONFIG_ASSET_DIR}/run_nodered_template.sh.in" ${SCRIPT_OUTPUT_FILE})
|
||||
|
||||
endfunction()
|
||||
61
tools/EVerest-main/cmake/config-run-script.cmake
Normal file
61
tools/EVerest-main/cmake/config-run-script.cmake
Normal file
@@ -0,0 +1,61 @@
|
||||
set(EVEREST_CONFIG_ASSET_DIR "${CMAKE_CURRENT_LIST_DIR}/assets" CACHE INTERNAL "")
|
||||
|
||||
function(generate_config_run_script)
|
||||
|
||||
if (NOT EVEREST_ENABLE_RUN_SCRIPT_GENERATION)
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
set(options "")
|
||||
set(one_value_args
|
||||
CONFIG
|
||||
LOGGING_CONFIG
|
||||
OUTPUT
|
||||
)
|
||||
set(multi_value_args
|
||||
ADDITIONAL_ARGUMENTS
|
||||
)
|
||||
|
||||
cmake_parse_arguments(OPTNS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
if (OPTNS_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} got unknown argument(s): ${OPTNS_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (NOT OPTNS_CONFIG)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} requires CONFIG parameter for the config name")
|
||||
endif()
|
||||
|
||||
set(CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config-${OPTNS_CONFIG}.yaml")
|
||||
if (NOT EXISTS ${CONFIG_FILE})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: config file '${CONFIG_FILE}' does not exist")
|
||||
endif()
|
||||
|
||||
set(LOGGING_CONFIG_FILE "${EVEREST_CONFIG_ASSET_DIR}/logging.ini")
|
||||
if (OPTNS_LOGGING_CONFIG)
|
||||
set(LOGGING_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${OPTNS_LOGGING_CONFIG}.ini")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS ${LOGGING_CONFIG_FILE})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: logging config file '${LOGGING_CONFIG_FILE}' does not exist")
|
||||
endif()
|
||||
|
||||
foreach (ARG ${OPTNS_ADDITIONAL_ARGUMENTS})
|
||||
string(APPEND ADDITIONAL_ARGUMENTS "${ARG} ")
|
||||
endforeach()
|
||||
|
||||
string(APPEND ADDITIONAL_ARGUMENTS "\\")
|
||||
|
||||
set(SCRIPT_OUTPUT_PATH "${CMAKE_BINARY_DIR}/run-scripts")
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/run-${OPTNS_CONFIG}.sh")
|
||||
if (OPTNS_OUTPUT)
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/run-${OPTNS_OUTPUT}.sh")
|
||||
endif()
|
||||
|
||||
# other necessary variables
|
||||
set(LD_LIBRARY_VAR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
set(PATH_VAR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
configure_file("${EVEREST_CONFIG_ASSET_DIR}/run_template.sh.in" ${SCRIPT_OUTPUT_FILE})
|
||||
|
||||
endfunction()
|
||||
60
tools/EVerest-main/cmake/config-tmux-run-script.cmake
Normal file
60
tools/EVerest-main/cmake/config-tmux-run-script.cmake
Normal file
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
|
||||
set(EVEREST_CONFIG_ASSET_DIR "${CMAKE_CURRENT_LIST_DIR}/assets" CACHE INTERNAL "")
|
||||
|
||||
function(generate_config_tmux_run_script)
|
||||
|
||||
if (NOT EVEREST_ENABLE_RUN_SCRIPT_GENERATION)
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
set(options "")
|
||||
set(one_value_args
|
||||
CONFIG
|
||||
LOGGING_CONFIG
|
||||
OUTPUT
|
||||
)
|
||||
set(multi_value_args
|
||||
ADDITIONAL_ARGUMENTS
|
||||
)
|
||||
|
||||
cmake_parse_arguments(OPTNS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
if (OPTNS_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} got unknown argument(s): ${OPTNS_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (NOT OPTNS_CONFIG)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} requires CONFIG parameter for the config name")
|
||||
endif()
|
||||
|
||||
set(HELPER_PREFIX ${CMAKE_INSTALL_PREFIX}/etc/everest)
|
||||
|
||||
set(CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config-${OPTNS_CONFIG}.yaml")
|
||||
if (NOT EXISTS ${CONFIG_FILE})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: config file '${CONFIG_FILE}' does not exist")
|
||||
endif()
|
||||
|
||||
set(LOGGING_CONFIG_FILE "${EVEREST_CONFIG_ASSET_DIR}/logging.ini")
|
||||
if (OPTNS_LOGGING_CONFIG)
|
||||
set(LOGGING_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${OPTNS_LOGGING_CONFIG}.ini")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS ${LOGGING_CONFIG_FILE})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: logging config file '${LOGGING_CONFIG_FILE}' does not exist")
|
||||
endif()
|
||||
|
||||
set(SCRIPT_OUTPUT_PATH "${CMAKE_BINARY_DIR}/run-scripts")
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/run-tmux-${OPTNS_CONFIG}.sh")
|
||||
if (OPTNS_OUTPUT)
|
||||
set(SCRIPT_OUTPUT_FILE "${SCRIPT_OUTPUT_PATH}/run-tmux-${OPTNS_OUTPUT}.sh")
|
||||
endif()
|
||||
|
||||
# other necessary variables
|
||||
set(LD_LIBRARY_VAR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
set(PATH_VAR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
configure_file("${EVEREST_CONFIG_ASSET_DIR}/run_tmux_template.sh.in" ${SCRIPT_OUTPUT_FILE})
|
||||
|
||||
endfunction()
|
||||
101
tools/EVerest-main/cmake/ev-cli.cmake
Normal file
101
tools/EVerest-main/cmake/ev-cli.cmake
Normal file
@@ -0,0 +1,101 @@
|
||||
function(setup_ev_cli)
|
||||
if(NOT TARGET ev-cli)
|
||||
add_custom_target(ev-cli)
|
||||
endif()
|
||||
if(NOT ${${PROJECT_NAME}_USE_PYTHON_VENV})
|
||||
message(STATUS "Using system ev-cli instead of installing it in the build venv.")
|
||||
find_program(EV_CLI ev-cli REQUIRED)
|
||||
else()
|
||||
ev_is_python_venv_active(
|
||||
RESULT_VAR IS_PYTHON_VENV_ACTIVE
|
||||
)
|
||||
if(NOT ${IS_PYTHON_VENV_ACTIVE})
|
||||
message(FATAL_ERROR "Python venv is not active. Please activate the python venv before running this command.")
|
||||
endif()
|
||||
|
||||
get_target_property(SOURCE_DIRECTORY ev_pip_package_ev-dev-tools SOURCE_DIRECTORY)
|
||||
message(STATUS "Installing ev-cli from: ${SOURCE_DIRECTORY}")
|
||||
ev_pip_install_local(
|
||||
PACKAGE_NAME "ev-dev-tools"
|
||||
PACKAGE_SOURCE_DIRECTORY "${SOURCE_DIRECTORY}"
|
||||
)
|
||||
unset(EV_CLI CACHE)
|
||||
find_program(EV_CLI ev-cli HINTS ${EV_ACTIVATE_PYTHON_VENV_PATH_TO_VENV}/bin REQUIRED)
|
||||
message(STATUS "Using ev-cli from: ${EV_CLI}")
|
||||
endif()
|
||||
|
||||
get_property(EVEREST_REQUIRED_EV_CLI_VERSION
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_REQUIRED_EV_CLI_VERSION
|
||||
)
|
||||
require_ev_cli_version(${EVEREST_REQUIRED_EV_CLI_VERSION})
|
||||
|
||||
set_ev_cli_template_properties()
|
||||
endfunction()
|
||||
|
||||
function(require_ev_cli_version EV_CLI_VERSION_REQUIRED)
|
||||
execute_process(
|
||||
COMMAND ${EV_CLI} --version
|
||||
OUTPUT_VARIABLE EV_CLI_VERSION_FULL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
string(REPLACE "ev-cli " "" EV_CLI_VERSION "${EV_CLI_VERSION_FULL}")
|
||||
|
||||
if ("${EV_CLI_VERSION}" STREQUAL "")
|
||||
message(FATAL_ERROR "Could not determine a ev-cli version from the provided version '${EV_CLI_VERSION_FULL}'")
|
||||
endif()
|
||||
if("${EV_CLI_VERSION}" VERSION_GREATER_EQUAL "${EV_CLI_VERSION_REQUIRED}")
|
||||
message("Found ev-cli version '${EV_CLI_VERSION}' which satisfies the requirement of ev-cli version '${EV_CLI_VERSION_REQUIRED}'")
|
||||
else()
|
||||
message(FATAL_ERROR "ev-cli version ${EV_CLI_VERSION_REQUIRED} or higher is required. However your ev-cli version is '${EV_CLI_VERSION}'. Please upgrade ev-cli.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(set_ev_cli_template_properties)
|
||||
message(STATUS "Setting template properties for ev-cli target")
|
||||
get_target_property(EVEREST_SCHEMA_DIR generate_cpp_files EVEREST_SCHEMA_DIR)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${EV_CLI} interface get-templates --separator=\; --schemas-dir "${EVEREST_SCHEMA_DIR}"
|
||||
OUTPUT_VARIABLE INTERFACE_TEMPLATES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE
|
||||
INTERFACE_TEMPLATES_RESULT
|
||||
)
|
||||
|
||||
if(INTERFACE_TEMPLATES_RESULT)
|
||||
message(FATAL_ERROR "Could not get interface templates from ev-cli.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${EV_CLI} module get-templates --separator=\; --schemas-dir "${EVEREST_SCHEMA_DIR}"
|
||||
OUTPUT_VARIABLE MODULE_TEMPLATES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE
|
||||
MODULE_TEMPLATES_RESULT
|
||||
)
|
||||
|
||||
if(MODULE_TEMPLATES_RESULT)
|
||||
message(FATAL_ERROR "Could not get module loader templates from ev-cli.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${EV_CLI} types get-templates --separator=\; --schemas-dir "${EVEREST_SCHEMA_DIR}"
|
||||
OUTPUT_VARIABLE TYPES_TEMPLATES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE
|
||||
TYPES_TEMPLATES_RESULT
|
||||
)
|
||||
|
||||
if(TYPES_TEMPLATES_RESULT)
|
||||
message(FATAL_ERROR "Could not get module loader templates from ev-cli.")
|
||||
endif()
|
||||
|
||||
set_target_properties(ev-cli
|
||||
PROPERTIES
|
||||
INTERFACE_TEMPLATES "${INTERFACE_TEMPLATES}"
|
||||
MODULE_TEMPLATES "${MODULE_TEMPLATES}"
|
||||
TYPES_TEMPLATES "${TYPES_TEMPLATES}"
|
||||
)
|
||||
endfunction()
|
||||
103
tools/EVerest-main/cmake/ev-define-dependency.cmake
Normal file
103
tools/EVerest-main/cmake/ev-define-dependency.cmake
Normal file
@@ -0,0 +1,103 @@
|
||||
function(_everest_exclude_modules_loop EVEREST_INTERNAL_DEPENDENT_MODULES_LIST OUTPUT_VARIABLE)
|
||||
# iterate over the provided list of dependent modules and check if all of these modules are included in EVEREST_EXCLUDE_MODULES
|
||||
set(EVEREST_INTERNAL_DEPENDENCY_EXCLUDE_COUNT 0)
|
||||
foreach(EVEREST_INTERNAL_DEPENDENT_MODULE IN LISTS EVEREST_INTERNAL_DEPENDENT_MODULES_LIST)
|
||||
if("${EVEREST_INTERNAL_DEPENDENT_MODULE}" IN_LIST EVEREST_EXCLUDE_MODULES)
|
||||
# a dependent module is excluded, exclude the dependency
|
||||
math(EXPR EVEREST_INTERNAL_DEPENDENCY_EXCLUDE_COUNT "${EVEREST_INTERNAL_DEPENDENCY_EXCLUDE_COUNT}+1")
|
||||
endif()
|
||||
endforeach()
|
||||
list(LENGTH EVEREST_EXCLUDE_MODULES EVEREST_INTERNAL_EXCLUDE_MODULES_LEN)
|
||||
if(EVEREST_INTERNAL_DEPENDENCY_EXCLUDE_COUNT GREATER 0 AND EVEREST_INTERNAL_DEPENDENCY_EXCLUDE_COUNT EQUAL EVEREST_INTERNAL_EXCLUDE_MODULES_LEN)
|
||||
# all modules that need this dependency are excluded
|
||||
set("${OUTPUT_VARIABLE}" OFF PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_everest_include_modules_loop EVEREST_INTERNAL_DEPENDENT_MODULES_LIST OUTPUT_VARIABLE)
|
||||
# iterate over the provided list of dependent modules and check if one of these modules is included in EVEREST_INCLUDE_MODULES
|
||||
foreach(EVEREST_INTERNAL_DEPENDENT_MODULE IN LISTS EVEREST_INTERNAL_DEPENDENT_MODULES_LIST)
|
||||
if("${EVEREST_INTERNAL_DEPENDENT_MODULE}" IN_LIST EVEREST_INCLUDE_MODULES)
|
||||
# a dependent module is being build, include the dependency
|
||||
set("${OUTPUT_VARIABLE}" ON PARENT_SCOPE)
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(ev_define_dependency)
|
||||
#
|
||||
# handle passed arguments
|
||||
#
|
||||
set(options "")
|
||||
set(one_value_args
|
||||
DEPENDENCY_NAME
|
||||
OUTPUT_VARIABLE_SUFFIX
|
||||
)
|
||||
set(multi_value_args
|
||||
DEPENDENT_MODULES_LIST
|
||||
)
|
||||
cmake_parse_arguments(OPTNS "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
if (OPTNS_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} got unknown argument(s): ${OPTNS_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (NOT OPTNS_DEPENDENCY_NAME)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} requires DEPENDENCY_NAME parameter for the dependency name")
|
||||
endif()
|
||||
set(DEPENDENCY_NAME "${OPTNS_DEPENDENCY_NAME}")
|
||||
string(TOUPPER "${OPTNS_DEPENDENCY_NAME}" EVEREST_INTERNAL_DEPENDENCY_NAME_UPPER)
|
||||
|
||||
if (NOT OPTNS_DEPENDENT_MODULES_LIST)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} requires DEPENDENT_MODULES_LIST parameter for the dependent modules list")
|
||||
endif()
|
||||
set(EVEREST_INTERNAL_DEPENDENT_MODULES_LIST "${OPTNS_DEPENDENT_MODULES_LIST}")
|
||||
list(LENGTH EVEREST_INTERNAL_DEPENDENT_MODULES_LIST EVEREST_INTERNAL_DEPENDENT_MODULES_LIST_LEN)
|
||||
|
||||
if (NOT OPTNS_OUTPUT_VARIABLE_SUFFIX)
|
||||
# use the uppercase dependency name
|
||||
set(EVEREST_INTERNAL_DEPENDENCY_CONDITION "EVEREST_DEPENDENCY_ENABLED_${EVEREST_INTERNAL_DEPENDENCY_NAME_UPPER}")
|
||||
else()
|
||||
# set output variable suffix
|
||||
set(EVEREST_INTERNAL_DEPENDENCY_CONDITION "EVEREST_DEPENDENCY_ENABLED_${OPTNS_OUTPUT_VARIABLE_SUFFIX}")
|
||||
endif()
|
||||
|
||||
#
|
||||
# handle the various dependency conditions
|
||||
#
|
||||
if(DEFINED "${EVEREST_INTERNAL_DEPENDENCY_CONDITION}")
|
||||
# always enable a externally set dependency
|
||||
message(STATUS "${EVEREST_INTERNAL_DEPENDENCY_CONDITION} externally set to: ${${EVEREST_INTERNAL_DEPENDENCY_CONDITION}}")
|
||||
else()
|
||||
# disable dependency by default
|
||||
set("${EVEREST_INTERNAL_DEPENDENCY_CONDITION}" OFF)
|
||||
|
||||
# find out if dependency is excluded or uncluded
|
||||
if(NOT "${DEPENDENCY_NAME}" IN_LIST EVEREST_EXCLUDE_DEPENDENCIES)
|
||||
if(NOT EVEREST_INCLUDE_MODULES)
|
||||
# all modules are being build, at the moment we cannot know which dependencies are needed
|
||||
set("${EVEREST_INTERNAL_DEPENDENCY_CONDITION}" ON)
|
||||
# find out if all modules that need this dependency are excluded
|
||||
_everest_exclude_modules_loop("${EVEREST_INTERNAL_DEPENDENT_MODULES_LIST}" "${EVEREST_INTERNAL_DEPENDENCY_CONDITION}")
|
||||
else()
|
||||
# EVEREST_INCLUDE_MODULES takes precendece over EVEREST_EXCLUDE_MODULES in everest-generate as well, reflect this here
|
||||
_everest_include_modules_loop("${EVEREST_INTERNAL_DEPENDENT_MODULES_LIST}" "${EVEREST_INTERNAL_DEPENDENCY_CONDITION}")
|
||||
endif()
|
||||
else()
|
||||
# dependency disabled because it is listed in EVEREST_EXCLUDE_DEPENDENCIES
|
||||
set("${EVEREST_INTERNAL_DEPENDENCY_CONDITION}" OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# log the result
|
||||
if(NOT ${EVEREST_INTERNAL_DEPENDENCY_CONDITION})
|
||||
message(STATUS "Dependency ${DEPENDENCY_NAME} NOT enabled:")
|
||||
else()
|
||||
message(STATUS "Dependency ${DEPENDENCY_NAME} enabled:")
|
||||
endif()
|
||||
|
||||
message(STATUS " ${EVEREST_INTERNAL_DEPENDENCY_CONDITION}=${${EVEREST_INTERNAL_DEPENDENCY_CONDITION}}")
|
||||
|
||||
# propagate the result to the parent scope:
|
||||
set("${EVEREST_INTERNAL_DEPENDENCY_CONDITION}" "${${EVEREST_INTERNAL_DEPENDENCY_CONDITION}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
140
tools/EVerest-main/cmake/ev-lib-dependencies.cmake
Normal file
140
tools/EVerest-main/cmake/ev-lib-dependencies.cmake
Normal file
@@ -0,0 +1,140 @@
|
||||
#
|
||||
# Selective library inclusion for everest-core.
|
||||
#
|
||||
# When EVEREST_INCLUDE_LIBS is set (allowlist mode), only listed libraries
|
||||
# and their transitive internal dependencies are built.
|
||||
# When EVEREST_EXCLUDE_LIBS is set (blocklist mode), listed libraries are skipped.
|
||||
# When neither is set, all libraries are built (default / backwards-compatible).
|
||||
#
|
||||
# Usage from an external project via EDM/CPM:
|
||||
# options:
|
||||
# - "EVEREST_LIBS_ONLY ON"
|
||||
# - "EVEREST_INCLUDE_LIBS log;util;io"
|
||||
#
|
||||
# Adding a new library:
|
||||
# 1. Create lib/everest/<name>/ with its CMakeLists.txt
|
||||
# 2. Add <name> to EVEREST_LIB_SUBDIRS below
|
||||
# 3. If it depends on other everest-core libraries, add:
|
||||
# set(EVEREST_LIB_DEPS_<name> "dep1;dep2")
|
||||
#
|
||||
|
||||
# --- Master list of library subdirectories ---
|
||||
# This is the single source of truth for which libraries exist under lib/everest/.
|
||||
# Used by both the build-variable computation here and lib/everest/CMakeLists.txt.
|
||||
set(EVEREST_LIB_SUBDIRS
|
||||
can_dpm1000
|
||||
cbv2g
|
||||
conversions
|
||||
crc
|
||||
everest_api_module_helpers
|
||||
everest_api_types
|
||||
evse_security
|
||||
external_energy_limits
|
||||
framework
|
||||
fsm
|
||||
helpers
|
||||
ieee2030_1_1
|
||||
io
|
||||
iso15118
|
||||
log
|
||||
ocpp
|
||||
run_application
|
||||
slac
|
||||
sqlite
|
||||
timer
|
||||
tls
|
||||
util
|
||||
yaml
|
||||
)
|
||||
|
||||
# --- Internal dependency map ---
|
||||
# Each variable lists the everest-core libraries that the key library depends on.
|
||||
# Only internal (lib/everest/) dependencies are tracked here; external deps
|
||||
# (Boost, OpenSSL, etc.) are handled by each library's own CMakeLists.txt.
|
||||
# Libraries with no internal deps do not need an entry.
|
||||
|
||||
# Tier 1
|
||||
set(EVEREST_LIB_DEPS_yaml "log")
|
||||
set(EVEREST_LIB_DEPS_io "util")
|
||||
set(EVEREST_LIB_DEPS_run_application "log")
|
||||
set(EVEREST_LIB_DEPS_evse_security "cbv2g")
|
||||
# Tier 2
|
||||
set(EVEREST_LIB_DEPS_ocpp "log;timer;evse_security;sqlite")
|
||||
set(EVEREST_LIB_DEPS_iso15118 "cbv2g")
|
||||
set(EVEREST_LIB_DEPS_ieee2030_1_1 "framework")
|
||||
# Tier 3 (framework-coupled)
|
||||
set(EVEREST_LIB_DEPS_tls "util;evse_security;framework")
|
||||
set(EVEREST_LIB_DEPS_helpers "tls;framework")
|
||||
set(EVEREST_LIB_DEPS_external_energy_limits "framework")
|
||||
set(EVEREST_LIB_DEPS_everest_api_types "")
|
||||
set(EVEREST_LIB_DEPS_conversions "framework;evse_security")
|
||||
set(EVEREST_LIB_DEPS_slac "tls")
|
||||
|
||||
# --- Transitive dependency resolver ---
|
||||
# Given a list of library names, computes the full transitive closure
|
||||
# of internal dependencies and stores the result in OUTPUT_VAR.
|
||||
function(_ev_resolve_lib_transitive_deps INPUT_LIBS OUTPUT_VAR)
|
||||
set(_resolved "${INPUT_LIBS}")
|
||||
set(_frontier "${INPUT_LIBS}")
|
||||
|
||||
while(_frontier)
|
||||
set(_next_frontier "")
|
||||
foreach(_lib IN LISTS _frontier)
|
||||
if(DEFINED EVEREST_LIB_DEPS_${_lib})
|
||||
foreach(_dep IN LISTS EVEREST_LIB_DEPS_${_lib})
|
||||
if(NOT _dep IN_LIST _resolved)
|
||||
list(APPEND _resolved "${_dep}")
|
||||
list(APPEND _next_frontier "${_dep}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
set(_frontier "${_next_frontier}")
|
||||
endwhile()
|
||||
|
||||
set(${OUTPUT_VAR} "${_resolved}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# --- Resolve the library set once at configure time ---
|
||||
if(EVEREST_INCLUDE_LIBS)
|
||||
_ev_resolve_lib_transitive_deps("${EVEREST_INCLUDE_LIBS}" EVEREST_RESOLVED_LIBS)
|
||||
message(STATUS "EVEREST_INCLUDE_LIBS set. Requested: ${EVEREST_INCLUDE_LIBS}")
|
||||
message(STATUS " Resolved (with transitive deps): ${EVEREST_RESOLVED_LIBS}")
|
||||
elseif(EVEREST_EXCLUDE_LIBS)
|
||||
message(STATUS "EVEREST_EXCLUDE_LIBS set: ${EVEREST_EXCLUDE_LIBS}")
|
||||
endif()
|
||||
|
||||
# Set per-library build variables (used by cmake_condition in dependencies.yaml)
|
||||
# When EVEREST_INCLUDE_LIBS is empty these are all ON (build everything).
|
||||
# Includes the conditional libraries (gpio, system) that have additional guards.
|
||||
set(_EVEREST_ALL_LIBS ${EVEREST_LIB_SUBDIRS} gpio system)
|
||||
|
||||
foreach(_lib IN LISTS _EVEREST_ALL_LIBS)
|
||||
if(EVEREST_INCLUDE_LIBS)
|
||||
if(_lib IN_LIST EVEREST_RESOLVED_LIBS)
|
||||
set(EVEREST_BUILD_LIB_${_lib} ON)
|
||||
else()
|
||||
set(EVEREST_BUILD_LIB_${_lib} OFF)
|
||||
endif()
|
||||
elseif(EVEREST_EXCLUDE_LIBS)
|
||||
if(_lib IN_LIST EVEREST_EXCLUDE_LIBS)
|
||||
set(EVEREST_BUILD_LIB_${_lib} OFF)
|
||||
else()
|
||||
set(EVEREST_BUILD_LIB_${_lib} ON)
|
||||
endif()
|
||||
else()
|
||||
set(EVEREST_BUILD_LIB_${_lib} ON)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# --- Query function ---
|
||||
# ev_should_build_lib(<lib_name> <output_var>)
|
||||
# Sets <output_var> to ON or OFF in the caller's scope.
|
||||
function(ev_should_build_lib LIB_NAME OUTPUT_VAR)
|
||||
if(DEFINED EVEREST_BUILD_LIB_${LIB_NAME})
|
||||
set(${OUTPUT_VAR} "${EVEREST_BUILD_LIB_${LIB_NAME}}" PARENT_SCOPE)
|
||||
else()
|
||||
# Unknown library name — default to ON for forwards compatibility
|
||||
set(${OUTPUT_VAR} ON PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
14
tools/EVerest-main/cmake/ev-project-bootstrap.cmake
Normal file
14
tools/EVerest-main/cmake/ev-project-bootstrap.cmake
Normal file
@@ -0,0 +1,14 @@
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_REQUIRED_EV_CLI_VERSION "0.6.2"
|
||||
)
|
||||
|
||||
# FIXME (aw): clean up this inclusion chain
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/ev-cli.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/config-run-script.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/config-run-nodered-script.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/config-tmux-run-script.cmake)
|
||||
|
||||
# source generate scripts / setup
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/ev-targets.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/everest-generate.cmake)
|
||||
47
tools/EVerest-main/cmake/ev-targets.cmake
Normal file
47
tools/EVerest-main/cmake/ev-targets.cmake
Normal file
@@ -0,0 +1,47 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
add_custom_target(everest_targets)
|
||||
|
||||
set_target_properties(everest_targets
|
||||
PROPERTIES
|
||||
LIBRARIES ""
|
||||
MODULES ""
|
||||
TESTS ""
|
||||
)
|
||||
|
||||
function(_ev_register_target TYPE NAME)
|
||||
if (NOT TARGET ${NAME})
|
||||
if(EVEREST_LIBS_ONLY OR EVEREST_INCLUDE_LIBS OR EVEREST_EXCLUDE_LIBS)
|
||||
message(STATUS "Skipping registration of target ${NAME} (not built in selective mode)")
|
||||
return()
|
||||
endif()
|
||||
message(FATAL_ERROR "The supplied name ${NAME} of type ${TYPE} is not a valid target")
|
||||
endif()
|
||||
|
||||
set_property(
|
||||
TARGET everest_targets
|
||||
APPEND
|
||||
PROPERTY ${TYPE} ${NAME}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(ev_register_library_target NAME)
|
||||
_ev_register_target(LIBRARIES ${NAME})
|
||||
endfunction()
|
||||
|
||||
function(ev_register_module_target NAME)
|
||||
_ev_register_target(MODULES ${NAME})
|
||||
endfunction()
|
||||
|
||||
function(ev_register_test_target NAME)
|
||||
_ev_register_target(TESTS ${NAME})
|
||||
endfunction()
|
||||
|
||||
function(ev_get_targets NAME TYPE)
|
||||
get_target_property(tmp everest_targets ${TYPE})
|
||||
if (NOT tmp STREQUAL "" AND NOT tmp)
|
||||
message(FATAL_ERROR "There is no target of type ${TYPE} defined")
|
||||
endif()
|
||||
|
||||
set(${NAME} ${tmp} PARENT_SCOPE)
|
||||
endfunction()
|
||||
897
tools/EVerest-main/cmake/everest-generate.cmake
Normal file
897
tools/EVerest-main/cmake/everest-generate.cmake
Normal file
@@ -0,0 +1,897 @@
|
||||
if (NOT EVEREST_SCHEMA_DIR)
|
||||
get_filename_component(CUR_FILE_NAME ${CMAKE_CURRENT_LIST_FILE} NAME)
|
||||
message(FATAL_ERROR "\
|
||||
The variable EVEREST_SCHEMA_DIR is not set, this needs to be done, \
|
||||
before including \"${CUR_FILE_NAME}\"\
|
||||
")
|
||||
endif()
|
||||
|
||||
set (EV_CORE_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_DIR} CACHE FILEPATH "")
|
||||
|
||||
# FIXME (aw): where should this go, should it be global?
|
||||
string(ASCII 27 ESCAPE)
|
||||
set(FMT_RESET "${ESCAPE}[m")
|
||||
set(FMT_BOLD "${ESCAPE}[1m")
|
||||
|
||||
# NOTE (aw): maybe this could be also implemented as an IMPORTED target?
|
||||
add_custom_target(generate_cpp_files)
|
||||
set_target_properties(generate_cpp_files
|
||||
PROPERTIES
|
||||
EVEREST_SCHEMA_DIR "${EVEREST_SCHEMA_DIR}"
|
||||
EVEREST_GENERATED_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated"
|
||||
EVEREST_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/generated/include"
|
||||
EVEREST_PROJECT_DIRS ""
|
||||
)
|
||||
|
||||
#
|
||||
# out-of-tree interfaces/types/modules support
|
||||
#
|
||||
function(_ev_add_project)
|
||||
set(options SKIP_DOC_GENERATION)
|
||||
set(oneValueArgs EV_PROJECT_DIRECTORY EV_PROJECT_NAME)
|
||||
set(multiValueArgs "")
|
||||
cmake_parse_arguments(args "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if (args_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "_ev_add_project function got unknown argument(s): ${args_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if(args_KEYWORDS_MISSING_VALUES)
|
||||
message(FATAL_ERROR "ev_add_project() keyword(s) missing values: ${args_KEYWORDS_MISSING_VALUES}")
|
||||
endif()
|
||||
|
||||
if(args_EV_PROJECT_DIRECTORY AND args_EV_PROJECT_NAME)
|
||||
set (EVEREST_PROJECT_DIR ${args_EV_PROJECT_DIRECTORY})
|
||||
set (EVEREST_PROJECT_NAME ${args_EV_PROJECT_NAME})
|
||||
elseif(NOT args_PROJECT_NAME AND NOT args_PROJECT_DIRECTORY)
|
||||
# if we don't get a directory, we're assuming project directory
|
||||
set (EVEREST_PROJECT_DIR ${PROJECT_SOURCE_DIR})
|
||||
set (CALLED_FROM_WITHIN_PROJECT TRUE)
|
||||
set (EVEREST_PROJECT_NAME ${PROJECT_NAME})
|
||||
else()
|
||||
message(FATAL_ERROR "ev_add_project() can only be called with ALL or NONE of: 'EV_PROJECT_DIRECTORY', 'EV_PROJECT_NAME'")
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS ${EVEREST_PROJECT_DIR})
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} got non-existing project path: ${EVEREST_PROJECT_DIR}")
|
||||
endif ()
|
||||
|
||||
message(STATUS "APPENDING ${EVEREST_PROJECT_DIR} to EVEREST_PROJECT_DIRS")
|
||||
set_property(TARGET generate_cpp_files
|
||||
APPEND PROPERTY EVEREST_PROJECT_DIRS ${EVEREST_PROJECT_DIR}
|
||||
)
|
||||
get_target_property(EVEREST_PROJECT_DIRS generate_cpp_files EVEREST_PROJECT_DIRS)
|
||||
|
||||
# check for types
|
||||
set(TYPES_DIR "${EVEREST_PROJECT_DIR}/types")
|
||||
if (EXISTS ${TYPES_DIR})
|
||||
message(STATUS "Adding type definitions from ${TYPES_DIR}")
|
||||
file(GLOB TYPES_FILES
|
||||
${TYPES_DIR}/*.yaml
|
||||
)
|
||||
|
||||
if(EVEREST_BUILD_DOCS AND NOT args_SKIP_DOC_GENERATION)
|
||||
find_package(
|
||||
trailbook-ext-everest
|
||||
0.1.0
|
||||
REQUIRED
|
||||
PATHS "${CMAKE_SOURCE_DIR}/cmake"
|
||||
)
|
||||
foreach(TYPES_FILE ${TYPES_FILES})
|
||||
trailbook_ev_generate_rst_from_types(
|
||||
TRAILBOOK_NAME "everest"
|
||||
TYPES_FILE "${TYPES_FILE}"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
_ev_add_types(${TYPES_FILES})
|
||||
|
||||
if (CALLED_FROM_WITHIN_PROJECT)
|
||||
install(
|
||||
DIRECTORY ${TYPES_DIR}
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/everest"
|
||||
FILES_MATCHING PATTERN "*.yaml"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# check for API
|
||||
set(API_DIR "${EVEREST_PROJECT_DIR}/docs/source/reference/EVerest_API")
|
||||
if (EXISTS ${API_DIR})
|
||||
if (${EVEREST_SKIP_BUILD_API_DOC})
|
||||
message(WARNING "Skipping the generation of the EVerest API AsyncAPI html documentation")
|
||||
else()
|
||||
message(STATUS "Adding API definitions from ${API_DIR}")
|
||||
file(GLOB API_FILES
|
||||
${API_DIR}/*.yaml
|
||||
)
|
||||
|
||||
if(EVEREST_BUILD_DOCS AND NOT args_SKIP_DOC_GENERATION)
|
||||
find_package(
|
||||
trailbook-ext-everest
|
||||
0.1.0
|
||||
REQUIRED
|
||||
PATHS "${CMAKE_SOURCE_DIR}/cmake"
|
||||
)
|
||||
trailbook_ev_generate_api_doc(
|
||||
TRAILBOOK_NAME "everest"
|
||||
API_FILES ${API_FILES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CALLED_FROM_WITHIN_PROJECT)
|
||||
install(
|
||||
DIRECTORY ${API_DIR}
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/everest"
|
||||
FILES_MATCHING PATTERN "*.yaml"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# check for errors
|
||||
set(ERRORS_DIR "${EVEREST_PROJECT_DIR}/errors")
|
||||
if (EXISTS ${ERRORS_DIR})
|
||||
message(STATUS "Adding error definitions from ${ERRORS_DIR}")
|
||||
if (CALLED_FROM_WITHIN_PROJECT)
|
||||
install(
|
||||
DIRECTORY ${ERRORS_DIR}
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/everest"
|
||||
FILES_MATCHING PATTERN "*.yaml"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# check for interfaces
|
||||
set (INTERFACES_DIR "${EVEREST_PROJECT_DIR}/interfaces")
|
||||
if (EXISTS ${INTERFACES_DIR})
|
||||
message(STATUS "Adding interface definitions from ${INTERFACES_DIR}")
|
||||
file(GLOB INTERFACE_FILES
|
||||
${INTERFACES_DIR}/*.yaml
|
||||
)
|
||||
|
||||
if(EVEREST_BUILD_DOCS AND NOT args_SKIP_DOC_GENERATION)
|
||||
find_package(
|
||||
trailbook-ext-everest
|
||||
0.1.0
|
||||
REQUIRED
|
||||
PATHS "${CMAKE_SOURCE_DIR}/cmake"
|
||||
)
|
||||
foreach(INTERFACE_FILE ${INTERFACE_FILES})
|
||||
trailbook_ev_generate_rst_from_interface(
|
||||
TRAILBOOK_NAME "everest"
|
||||
INTERFACE_FILE "${INTERFACE_FILE}"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
_ev_add_interfaces(${INTERFACE_FILES})
|
||||
|
||||
if (CALLED_FROM_WITHIN_PROJECT)
|
||||
install(
|
||||
DIRECTORY ${INTERFACES_DIR}
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/everest"
|
||||
FILES_MATCHING PATTERN "*.yaml"
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# check for modules
|
||||
set (MODULES_DIR "${EVEREST_PROJECT_DIR}/modules")
|
||||
if (EXISTS "${MODULES_DIR}/CMakeLists.txt")
|
||||
# FIXME (aw): default handling of building all modules?
|
||||
if (EVC_MAIN_PROJECT OR NOT EVEREST_DONT_BUILD_ALL_MODULES)
|
||||
add_subdirectory(${MODULES_DIR})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
get_property(EVEREST_MODULES
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES
|
||||
)
|
||||
message(STATUS "${EVEREST_PROJECT_NAME} modules that will be built: ${EVEREST_MODULES}")
|
||||
|
||||
# generate and install version information
|
||||
evc_generate_version_information()
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/generated/version_information.txt
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/everest"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
macro(ev_add_project)
|
||||
set(options SKIP_DOC_GENERATION)
|
||||
set(oneValueArgs EV_PROJECT_DIRECTORY EV_PROJECT_NAME)
|
||||
set(multiValueArgs "")
|
||||
cmake_parse_arguments(macro_args "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if (macro_args_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "ev_add_project macro got unknown argument(s): ${macro_args_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if(macro_args_KEYWORDS_MISSING_VALUES)
|
||||
message(FATAL_ERROR "ev_add_project() keyword(s) missing values: ${macro_args_KEYWORDS_MISSING_VALUES}")
|
||||
endif()
|
||||
|
||||
if(macro_args_EV_PROJECT_DIRECTORY AND NOT macro_args_EV_PROJECT_NAME)
|
||||
message(FATAL_ERROR "ev_add_project() was called with EV_PROJECT_DIRECTORY but is missing EV_PROJECT_NAME.")
|
||||
elseif(NOT macro_args_EV_PROJECT_DIRECTORY AND macro_args_EV_PROJECT_NAME)
|
||||
message(FATAL_ERROR "ev_add_project() was called with EV_PROJECT_NAME but is missing EV_PROJECT_DIRECTORY.")
|
||||
endif()
|
||||
|
||||
ev_setup_cmake_variables_python_wheel()
|
||||
set(${PROJECT_NAME}_PYTHON_VENV_PATH "${CMAKE_BINARY_DIR}/venv" CACHE PATH "Path to python venv")
|
||||
|
||||
ev_setup_python_executable(
|
||||
USE_PYTHON_VENV ${${PROJECT_NAME}_USE_PYTHON_VENV}
|
||||
PYTHON_VENV_PATH ${${PROJECT_NAME}_PYTHON_VENV_PATH}
|
||||
)
|
||||
|
||||
setup_ev_cli()
|
||||
|
||||
if (${macro_args_SKIP_DOC_GENERATION})
|
||||
set (macro_fwd_OPTION "SKIP_DOC_GENERATION")
|
||||
else()
|
||||
set (macro_fwd_OPTION "")
|
||||
endif()
|
||||
|
||||
if (macro_args_EV_PROJECT_DIRECTORY AND macro_args_EV_PROJECT_NAME)
|
||||
_ev_add_project(
|
||||
EV_PROJECT_DIRECTORY ${macro_args_EV_PROJECT_DIRECTORY}
|
||||
EV_PROJECT_NAME ${macro_args_EV_PROJECT_NAME}
|
||||
${macro_fwd_OPTION}
|
||||
)
|
||||
else()
|
||||
_ev_add_project(${macro_fwd_OPTION})
|
||||
endif ()
|
||||
endmacro()
|
||||
|
||||
#
|
||||
# rust support
|
||||
#
|
||||
# FIXME (aw): move this stuff to some other cmake file for more modularity
|
||||
if (EVEREST_ENABLE_RS_SUPPORT)
|
||||
find_program(CARGO_EXECUTABLE cargo REQUIRED)
|
||||
|
||||
# FIXME (aw): the RUST_WORKSPACE_DIR could be user setable!
|
||||
set(RUST_WORKSPACE_DIR ${PROJECT_BINARY_DIR}/rust_workspace)
|
||||
set(RUST_WORKSPACE_CARGO_FILE ${RUST_WORKSPACE_DIR}/Cargo.toml)
|
||||
|
||||
if (NOT EXISTS ${RUST_WORKSPACE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${RUST_WORKSPACE_DIR}")
|
||||
message(STATUS "Creating rust workspace at ${RUST_WORKSPACE_DIR}")
|
||||
endif ()
|
||||
|
||||
# NOTE (aw): we could also write a small python script, which would do that for us
|
||||
add_custom_command(OUTPUT ${RUST_WORKSPACE_CARGO_FILE}
|
||||
COMMAND
|
||||
echo "[workspace]" > Cargo.toml
|
||||
COMMAND
|
||||
echo "resolver = \"2\"" >> Cargo.toml
|
||||
COMMAND
|
||||
echo "members = [" >> Cargo.toml
|
||||
COMMAND
|
||||
echo " \"$<JOIN:$<TARGET_PROPERTY:generate_rust,RUST_MODULE_LIST>,\", \">\"," >> Cargo.toml # :)
|
||||
COMMAND
|
||||
echo "]" >> Cargo.toml && echo "" >> Cargo.toml
|
||||
COMMAND
|
||||
echo "[workspace.dependencies]" >> Cargo.toml
|
||||
COMMAND
|
||||
echo "everestrs = { path = \"$<TARGET_PROPERTY:everest::everestrs_sys,EVERESTRS_DIR>\" }" >> Cargo.toml
|
||||
COMMAND
|
||||
echo "everestrs-build = { path = \"$<TARGET_PROPERTY:everest::everestrs_sys,EVERESTRS_BUILD_DIR>\" }" >> Cargo.toml
|
||||
WORKING_DIRECTORY
|
||||
${RUST_WORKSPACE_DIR}
|
||||
VERBATIM
|
||||
DEPENDS
|
||||
${RUST_WORKSPACE_DIR}
|
||||
)
|
||||
|
||||
# Put the resulting file in the top-level build directory so that it can be easily accessed without CMake
|
||||
set(RUST_LINK_DEPENDENCIES_FILE ${CMAKE_BINARY_DIR}/everestrs-link-dependencies.txt)
|
||||
set(RUST_LINK_DEPENDENCIES "$<TARGET_GENEX_EVAL:everest::everestrs_sys,$<TARGET_PROPERTY:everest::everestrs_sys,EVERESTRS_LINK_DEPENDENCIES>>")
|
||||
|
||||
add_custom_command(OUTPUT ${RUST_LINK_DEPENDENCIES_FILE}
|
||||
COMMAND_EXPAND_LISTS
|
||||
VERBATIM
|
||||
COMMAND
|
||||
echo -e $<LIST:JOIN,${RUST_LINK_DEPENDENCIES},\\n> > "${RUST_LINK_DEPENDENCIES_FILE}"
|
||||
)
|
||||
|
||||
add_custom_target(generate_rust
|
||||
DEPENDS
|
||||
${RUST_WORKSPACE_CARGO_FILE}
|
||||
${RUST_LINK_DEPENDENCIES_FILE}
|
||||
)
|
||||
|
||||
# Store the workspace directory as a target property so that it is accessible in different scopes
|
||||
set_property(TARGET generate_rust
|
||||
PROPERTY
|
||||
RUST_WORKSPACE_DIR "${RUST_WORKSPACE_DIR}"
|
||||
)
|
||||
|
||||
# FIXME (aw): use generator expressions here, but this first needs to be fixed in the build.rs file ...
|
||||
add_custom_target(build_rust_modules ALL
|
||||
USES_TERMINAL
|
||||
COMMENT
|
||||
"Build rust modules"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env
|
||||
EVEREST_CORE_ROOT="${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
EVEREST_RS_LINK_DEPENDENCIES="${RUST_LINK_DEPENDENCIES_FILE}"
|
||||
${CARGO_EXECUTABLE} build
|
||||
$<IF:$<STREQUAL:$<CONFIG>,Release>,--release,>
|
||||
# explicitly set the linker to match what we're using for C++ to avoid the following issue when cross compiling:
|
||||
# https://github.com/rust-lang/rust/issues/28924
|
||||
--config 'target.$<TARGET_PROPERTY:build_rust_modules,RUST_TARGET_TRIPLE>.linker = \"${CMAKE_CXX_COMPILER}\"'
|
||||
--target $<TARGET_PROPERTY:build_rust_modules,RUST_TARGET_TRIPLE>
|
||||
WORKING_DIRECTORY
|
||||
${RUST_WORKSPACE_DIR}
|
||||
DEPENDS
|
||||
everest::everestrs_sys
|
||||
generate_rust
|
||||
)
|
||||
|
||||
# FIXME: cleaning up doesn't work on the first run
|
||||
set_property(TARGET build_rust_modules
|
||||
APPEND
|
||||
PROPERTY
|
||||
ADDITIONAL_CLEAN_FILES ${RUST_WORKSPACE_DIR}/target ${RUST_WORKSPACE_DIR}/Cargo.lock
|
||||
)
|
||||
|
||||
set_property(TARGET build_rust_modules
|
||||
PROPERTY
|
||||
# FIXME: Don't assume the glibc ABI here. This won't respect musl builds.
|
||||
RUST_TARGET_TRIPLE "${CMAKE_SYSTEM_PROCESSOR}-unknown-linux-gnu"
|
||||
)
|
||||
|
||||
function (ev_add_rs_module MODULE_NAME)
|
||||
if(NOT ${EVEREST_ENABLE_RS_SUPPORT})
|
||||
message(STATUS "Excluding Rust module ${MODULE_NAME} because EVEREST_ENABLE_RS_SUPPORT=${EVEREST_ENABLE_RS_SUPPORT}")
|
||||
return()
|
||||
elseif ("${MODULE_NAME}" IN_LIST EVEREST_EXCLUDE_MODULES)
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
elseif (EVEREST_INCLUDE_MODULES AND NOT ("${MODULE_NAME}" IN_LIST EVEREST_INCLUDE_MODULES))
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}")
|
||||
if (NOT IS_DIRECTORY ${MODULE_PATH})
|
||||
message(FATAL "Rust module ${MODULE_NAME} does not exist at ${MODULE_PATH}")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
message(STATUS "Setting up Rust module ${MODULE_NAME}")
|
||||
|
||||
# FIXME (aw): we might also look for a CMakeFiles.txt in the module folder for custom logic
|
||||
set_property(
|
||||
TARGET generate_rust
|
||||
APPEND
|
||||
PROPERTY RUST_MODULE_LIST "${MODULE_NAME}"
|
||||
)
|
||||
get_target_property(RUST_WORKSPACE_DIR generate_rust RUST_WORKSPACE_DIR)
|
||||
|
||||
add_custom_command(OUTPUT ${RUST_WORKSPACE_DIR}/${MODULE_NAME}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E create_symlink ${MODULE_PATH} ${MODULE_NAME}
|
||||
COMMENT
|
||||
"Create symlink for rust module ${MODULE_NAME}"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY
|
||||
${RUST_WORKSPACE_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(rust_symlink_module_${MODULE_NAME}
|
||||
DEPENDS ${RUST_WORKSPACE_DIR}/${MODULE_NAME}
|
||||
COMMENT "Create symlink for rust module ${MODULE_NAME}"
|
||||
)
|
||||
|
||||
add_dependencies(generate_rust rust_symlink_module_${MODULE_NAME})
|
||||
|
||||
set(EVEREST_MODULE_INSTALL_PREFIX "${CMAKE_INSTALL_LIBEXECDIR}/everest/modules")
|
||||
set(BIN_PREFIX "target/$<TARGET_PROPERTY:build_rust_modules,RUST_TARGET_TRIPLE>/$<IF:$<STREQUAL:$<CONFIG>,Release>,release,debug>")
|
||||
|
||||
install(PROGRAMS ${RUST_WORKSPACE_DIR}/${BIN_PREFIX}/${MODULE_NAME}
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
)
|
||||
|
||||
# FIXME (aw): this should go into a general function for all add_module_* flavours
|
||||
install(FILES ${MODULE_PATH}/manifest.yaml
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
endif () # EVEREST_ENABLE_RS_SUPPORT
|
||||
|
||||
|
||||
#
|
||||
# interfaces
|
||||
#
|
||||
function (_ev_add_interfaces)
|
||||
# FIXME (aw): check for duplicates here!
|
||||
get_target_property(GENERATED_OUTPUT_DIR generate_cpp_files EVEREST_GENERATED_OUTPUT_DIR)
|
||||
set(CHECK_DONE_FILE "${GENERATED_OUTPUT_DIR}/.interfaces_generated_${EVEREST_PROJECT_NAME}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${CHECK_DONE_FILE}"
|
||||
DEPENDS
|
||||
${ARGV}
|
||||
"$<TARGET_PROPERTY:ev-cli,INTERFACE_TEMPLATES>"
|
||||
COMMENT
|
||||
"Generating/updating interface files ..."
|
||||
VERBATIM
|
||||
COMMAND
|
||||
${EV_CLI} interface generate-headers
|
||||
--disable-clang-format
|
||||
--schemas-dir "$<TARGET_PROPERTY:generate_cpp_files,EVEREST_SCHEMA_DIR>"
|
||||
--output-dir "$<TARGET_PROPERTY:generate_cpp_files,EVEREST_GENERATED_INCLUDE_DIR>/generated/interfaces"
|
||||
--everest-dir ${EVEREST_PROJECT_DIRS}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch "${CHECK_DONE_FILE}"
|
||||
WORKING_DIRECTORY
|
||||
${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(generate_interfaces_cpp_${EVEREST_PROJECT_NAME}
|
||||
DEPENDS "${CHECK_DONE_FILE}"
|
||||
)
|
||||
|
||||
add_dependencies(generate_cpp_files
|
||||
generate_interfaces_cpp_${EVEREST_PROJECT_NAME}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# types
|
||||
#
|
||||
|
||||
function (_ev_add_types)
|
||||
# FIXME (aw): check for duplicates here!
|
||||
get_target_property(GENERATED_OUTPUT_DIR generate_cpp_files EVEREST_GENERATED_OUTPUT_DIR)
|
||||
set(CHECK_DONE_FILE "${GENERATED_OUTPUT_DIR}/.types_generated_${EVEREST_PROJECT_NAME}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
"${CHECK_DONE_FILE}"
|
||||
DEPENDS
|
||||
${ARGV}
|
||||
"$<TARGET_PROPERTY:ev-cli,TYPES_TEMPLATES>"
|
||||
COMMENT
|
||||
"Generating/updating type files ..."
|
||||
VERBATIM
|
||||
COMMAND
|
||||
${EV_CLI} types generate-headers
|
||||
--disable-clang-format
|
||||
--schemas-dir "$<TARGET_PROPERTY:generate_cpp_files,EVEREST_SCHEMA_DIR>"
|
||||
--output-dir "$<TARGET_PROPERTY:generate_cpp_files,EVEREST_GENERATED_INCLUDE_DIR>/generated/types"
|
||||
--everest-dir ${EVEREST_PROJECT_DIRS}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch "${CHECK_DONE_FILE}"
|
||||
WORKING_DIRECTORY
|
||||
${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(generate_types_cpp_${EVEREST_PROJECT_NAME}
|
||||
DEPENDS
|
||||
${CHECK_DONE_FILE}
|
||||
)
|
||||
|
||||
add_dependencies(generate_cpp_files
|
||||
generate_types_cpp_${EVEREST_PROJECT_NAME}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# modules
|
||||
#
|
||||
|
||||
function(ev_setup_cpp_module)
|
||||
# no-op to not break API
|
||||
endfunction()
|
||||
|
||||
function (ev_add_module)
|
||||
#
|
||||
# handle passed arguments
|
||||
#
|
||||
set(options SKIP_DOC_GENERATION)
|
||||
set(one_value_args "")
|
||||
set(multi_value_args
|
||||
DEPENDENCIES
|
||||
)
|
||||
|
||||
if (${ARGC} LESS 1)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() missing module name")
|
||||
endif ()
|
||||
|
||||
set (MODULE_NAME ${ARGV0})
|
||||
|
||||
cmake_parse_arguments(PARSE_ARGV 1 OPTNS "${options}" "${one_value_args}" "${multi_value_args}")
|
||||
|
||||
if (OPTNS_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() got unknown argument(s): ${OPTNS_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (OPTNS_DEPENDENCIES)
|
||||
foreach(DEPENDENCY_NAME ${OPTNS_DEPENDENCIES})
|
||||
set(DEPENDENCY_VALUE ${${DEPENDENCY_NAME}})
|
||||
if (NOT DEPENDENCY_VALUE)
|
||||
message(STATUS "${FMT_BOLD}Skipping${FMT_RESET} module ${MODULE_NAME} (${DEPENDENCY_NAME} is false)")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (EVEREST_BUILD_DOCS AND NOT OPTNS_SKIP_DOC_GENERATION)
|
||||
find_package(
|
||||
trailbook-ext-everest
|
||||
0.1.0
|
||||
REQUIRED
|
||||
PATHS "${CMAKE_SOURCE_DIR}/cmake"
|
||||
)
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}/docs/")
|
||||
trailbook_ev_add_module_handwritten_doc(
|
||||
TRAILBOOK_NAME "everest"
|
||||
MODULE_NAME "${MODULE_NAME}"
|
||||
HANDWRITTEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}/docs"
|
||||
)
|
||||
endif()
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}/doc.rst")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Module ${MODULE_NAME} contains a doc.rst file"
|
||||
" this is not supported anymore, please move to"
|
||||
" docs/index.rst.inc, then it will be picked up automatically."
|
||||
" For now this file will be ignored."
|
||||
)
|
||||
endif()
|
||||
trailbook_ev_generate_rst_from_manifest(
|
||||
TRAILBOOK_NAME "everest"
|
||||
MANIFEST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}/manifest.yaml"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# check if python module
|
||||
string(FIND ${MODULE_NAME} "Py" MODULE_PREFIX_POS)
|
||||
if (MODULE_PREFIX_POS EQUAL 0)
|
||||
ev_add_py_module(${MODULE_NAME})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# check if javascript module
|
||||
string(FIND ${MODULE_NAME} "Js" MODULE_PREFIX_POS)
|
||||
if (MODULE_PREFIX_POS EQUAL 0)
|
||||
ev_add_js_module(${MODULE_NAME})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# check if rust module
|
||||
string(FIND ${MODULE_NAME} "Rs" MODULE_PREFIX_POS)
|
||||
if (MODULE_PREFIX_POS EQUAL 0)
|
||||
if (NOT EVEREST_ENABLE_RS_SUPPORT)
|
||||
return() # NOTE (aw): could log here
|
||||
endif ()
|
||||
|
||||
ev_add_rs_module(${MODULE_NAME})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# otherwise, should be cpp module
|
||||
ev_add_cpp_module(${MODULE_NAME})
|
||||
endfunction()
|
||||
|
||||
function (ev_add_cpp_module MODULE_NAME)
|
||||
set(EVEREST_MODULE_INSTALL_PREFIX "${CMAKE_INSTALL_LIBEXECDIR}/everest/modules")
|
||||
set(EVEREST_MODULE_DIR ${PROJECT_SOURCE_DIR}/modules)
|
||||
|
||||
file(RELATIVE_PATH MODULE_PARENT_DIR ${EVEREST_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(RELATIVE_MODULE_DIR ${MODULE_NAME})
|
||||
if (MODULE_PARENT_DIR)
|
||||
set(RELATIVE_MODULE_DIR ${MODULE_PARENT_DIR}/${MODULE_NAME})
|
||||
endif()
|
||||
|
||||
set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}")
|
||||
|
||||
get_property(EVEREST_MODULES
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES
|
||||
)
|
||||
|
||||
# TODO(hikinggrass): This code is duplicated in ev_add_*_module and should be refactored.
|
||||
if(IS_DIRECTORY ${MODULE_PATH})
|
||||
if(${EVEREST_EXCLUDE_CPP_MODULES})
|
||||
message(STATUS "Excluding C++ module ${MODULE_NAME} because EVEREST_EXCLUDE_CPP_MODULES=${EVEREST_EXCLUDE_CPP_MODULES}")
|
||||
return()
|
||||
elseif("${MODULE_NAME}" IN_LIST EVEREST_EXCLUDE_MODULES)
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
elseif(EVEREST_INCLUDE_MODULES AND NOT ("${MODULE_NAME}" IN_LIST EVEREST_INCLUDE_MODULES))
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "Setting up C++ module ${MODULE_NAME}")
|
||||
|
||||
get_target_property(GENERATED_OUTPUT_DIR generate_cpp_files EVEREST_GENERATED_OUTPUT_DIR)
|
||||
|
||||
set(GENERATED_MODULE_DIR "${GENERATED_OUTPUT_DIR}/modules")
|
||||
set(MODULE_LOADER_DIR ${GENERATED_MODULE_DIR}/${MODULE_NAME})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${MODULE_LOADER_DIR}/ld-ev.hpp
|
||||
${MODULE_LOADER_DIR}/ld-ev.cpp
|
||||
COMMAND
|
||||
${EV_CLI} module generate-loader
|
||||
--disable-clang-format
|
||||
--schemas-dir "$<TARGET_PROPERTY:generate_cpp_files,EVEREST_SCHEMA_DIR>"
|
||||
--output-dir ${GENERATED_MODULE_DIR}
|
||||
${RELATIVE_MODULE_DIR}
|
||||
DEPENDS
|
||||
${MODULE_PATH}/manifest.yaml
|
||||
"$<TARGET_PROPERTY:ev-cli,MODULE_TEMPLATES>"
|
||||
WORKING_DIRECTORY
|
||||
${PROJECT_SOURCE_DIR}
|
||||
COMMENT
|
||||
"Generating ld-ev for module ${MODULE_NAME}"
|
||||
)
|
||||
|
||||
add_custom_target(ld-ev_${MODULE_NAME}
|
||||
DEPENDS ${MODULE_LOADER_DIR}/ld-ev.cpp
|
||||
)
|
||||
|
||||
add_dependencies(generate_cpp_files ld-ev_${MODULE_NAME})
|
||||
|
||||
add_executable(${MODULE_NAME})
|
||||
|
||||
set_target_properties(${MODULE_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_NAME}"
|
||||
)
|
||||
|
||||
target_include_directories(${MODULE_NAME}
|
||||
PRIVATE
|
||||
${MODULE_PATH}
|
||||
"$<TARGET_PROPERTY:generate_cpp_files,EVEREST_GENERATED_INCLUDE_DIR>"
|
||||
${MODULE_LOADER_DIR}
|
||||
)
|
||||
|
||||
target_sources(${MODULE_NAME}
|
||||
PRIVATE
|
||||
${MODULE_PATH}/${MODULE_NAME}.cpp
|
||||
"${MODULE_LOADER_DIR}/ld-ev.cpp"
|
||||
)
|
||||
|
||||
target_link_libraries(${MODULE_NAME}
|
||||
PRIVATE
|
||||
everest::framework
|
||||
${ATOMIC_LIBS}
|
||||
)
|
||||
|
||||
if(EVEREST_ENABLE_COMPILE_WARNINGS)
|
||||
message(STATUS "Building ${MODULE_NAME} with the following compile options: ${EVEREST_COMPILE_OPTIONS}")
|
||||
target_compile_options(${MODULE_NAME}
|
||||
PRIVATE ${EVEREST_COMPILE_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(${MODULE_NAME} generate_cpp_files)
|
||||
|
||||
ev_register_module_target(${MODULE_NAME})
|
||||
|
||||
install(TARGETS ${MODULE_NAME}
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
)
|
||||
|
||||
install(FILES ${MODULE_PATH}/manifest.yaml
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
)
|
||||
|
||||
list(APPEND EVEREST_MODULES ${MODULE_NAME})
|
||||
add_subdirectory(${MODULE_PATH})
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "C++ module ${MODULE_NAME} does not exist at ${MODULE_PATH}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# this will override EVEREST_MODULES, but that is ok because we appended the list earlier
|
||||
# rename EVEREST_MODULES to EVEREST_MODULES
|
||||
# use set_property APPEND
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES ${EVEREST_MODULES}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function (ev_add_js_module MODULE_NAME)
|
||||
set(EVEREST_MODULE_INSTALL_PREFIX "${CMAKE_INSTALL_LIBEXECDIR}/everest/modules")
|
||||
|
||||
set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}")
|
||||
|
||||
get_property(EVEREST_MODULES
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES
|
||||
)
|
||||
|
||||
if(IS_DIRECTORY ${MODULE_PATH})
|
||||
if(NOT ${EVEREST_ENABLE_JS_SUPPORT})
|
||||
message(STATUS "Excluding JavaScript module ${MODULE_NAME} because EVEREST_ENABLE_JS_SUPPORT=${EVEREST_ENABLE_JS_SUPPORT}")
|
||||
return()
|
||||
elseif("${MODULE_NAME}" IN_LIST EVEREST_EXCLUDE_MODULES)
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
elseif(EVEREST_INCLUDE_MODULES AND NOT ("${MODULE_NAME}" IN_LIST EVEREST_INCLUDE_MODULES))
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "Setting up JavaScript module ${MODULE_NAME}")
|
||||
|
||||
add_custom_target(${MODULE_NAME} ALL)
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/package.json")
|
||||
message(STATUS "JavaScript module ${MODULE_NAME} contains a package.json file with dependencies that will be installed")
|
||||
|
||||
add_dependencies(${MODULE_NAME} ${MODULE_NAME}_INSTALL_NODE_MODULES)
|
||||
|
||||
find_program(
|
||||
RSYNC
|
||||
rsync
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
find_program(
|
||||
NPM
|
||||
npm
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/package.json
|
||||
MAIN_DEPENDENCY package.json
|
||||
COMMENT "Copy package.json of module ${MODULE_NAME} to build dir"
|
||||
COMMAND ${RSYNC} -avq ${MODULE_PATH}/package.json ${CMAKE_CURRENT_BINARY_DIR}/package.json
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT .installed
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/package.json
|
||||
COMMENT "Installing dependencies of module ${MODULE_NAME} from package.json"
|
||||
COMMAND ${NPM} install > npm.log 2>&1 || ${CMAKE_COMMAND} -E cat ${CMAKE_CURRENT_BINARY_DIR}/npm.log
|
||||
COMMAND ${CMAKE_COMMAND} -E touch .installed
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${MODULE_NAME}_INSTALL_NODE_MODULES
|
||||
DEPENDS .installed
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/node_modules
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# install the whole js project
|
||||
if(CREATE_SYMLINKS)
|
||||
include("CreateModuleSymlink")
|
||||
else()
|
||||
install(
|
||||
DIRECTORY ${MODULE_PATH}/
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
PATTERN "CMakeLists.txt" EXCLUDE
|
||||
PATTERN "CMakeFiles" EXCLUDE)
|
||||
endif()
|
||||
|
||||
list(APPEND EVEREST_MODULES ${MODULE_NAME})
|
||||
add_subdirectory(${MODULE_PATH})
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "JavaScript module ${MODULE_NAME} does not exist at ${MODULE_PATH}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# this will override EVEREST_MODULES, but that is ok because we appended the list earlier
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES ${EVEREST_MODULES}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function (ev_add_py_module MODULE_NAME)
|
||||
set(EVEREST_MODULE_INSTALL_PREFIX "${CMAKE_INSTALL_LIBEXECDIR}/everest/modules")
|
||||
|
||||
set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}")
|
||||
|
||||
get_property(EVEREST_MODULES
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES
|
||||
)
|
||||
|
||||
if(IS_DIRECTORY ${MODULE_PATH})
|
||||
if(NOT ${EVEREST_ENABLE_PY_SUPPORT})
|
||||
message(STATUS "Excluding Python module ${MODULE_NAME} because EVEREST_ENABLE_PY_SUPPORT=${EVEREST_ENABLE_PY_SUPPORT}")
|
||||
return()
|
||||
elseif("${MODULE_NAME}" IN_LIST EVEREST_EXCLUDE_MODULES)
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
elseif(EVEREST_INCLUDE_MODULES AND NOT ("${MODULE_NAME}" IN_LIST EVEREST_INCLUDE_MODULES))
|
||||
message(STATUS "Excluding module ${MODULE_NAME}")
|
||||
return()
|
||||
else()
|
||||
message(STATUS "Setting up Python module ${MODULE_NAME}")
|
||||
|
||||
add_custom_target(${MODULE_NAME} ALL)
|
||||
|
||||
# TODO: figure out how to properly install python dependencies
|
||||
|
||||
# install the whole python project
|
||||
install(
|
||||
DIRECTORY ${MODULE_PATH}/
|
||||
DESTINATION "${EVEREST_MODULE_INSTALL_PREFIX}/${MODULE_NAME}"
|
||||
PATTERN "CMakeLists.txt" EXCLUDE
|
||||
PATTERN "CMakeFiles" EXCLUDE)
|
||||
|
||||
list(APPEND EVEREST_MODULES ${MODULE_NAME})
|
||||
add_subdirectory(${MODULE_PATH})
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Python module ${MODULE_NAME} does not exist at ${MODULE_PATH}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# this will override EVEREST_MODULES, but that is ok because we appended the list earlier
|
||||
set_property(
|
||||
GLOBAL
|
||||
PROPERTY EVEREST_MODULES ${EVEREST_MODULES}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(ev_install_project)
|
||||
set (LIBRARY_PACKAGE_NAME ${PROJECT_NAME})
|
||||
set (LIBRARY_PACKAGE_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${LIBRARY_PACKAGE_NAME})
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set (EVEREST_DATADIR "${CMAKE_INSTALL_DATADIR}/everest")
|
||||
|
||||
configure_package_config_file(
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/project-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_PACKAGE_NAME}-config.cmake
|
||||
INSTALL_DESTINATION
|
||||
${LIBRARY_PACKAGE_CMAKE_INSTALL_DIR}
|
||||
PATH_VARS
|
||||
EVEREST_DATADIR
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT everest-core-targets
|
||||
FILE "everest-core-targets.cmake"
|
||||
NAMESPACE everest::
|
||||
DESTINATION ${LIBRARY_PACKAGE_CMAKE_INSTALL_DIR}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_PACKAGE_NAME}-config.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/everest-generate.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/ev-cli.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/project-config.cmake.in
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/ev-project-bootstrap.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/ev-targets.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/config-run-script.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/config-run-nodered-script.cmake
|
||||
${EV_CORE_CMAKE_SCRIPT_DIR}/config-tmux-run-script.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${LIBRARY_PACKAGE_NAME}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(EVEREST_EXCLUDE_MODULES "" CACHE STRING "A list of modules that will not be built")
|
||||
set(EVEREST_INCLUDE_MODULES "" CACHE STRING "A list of modules that will be built. If the list is empty, all modules will be built.")
|
||||
option(EVEREST_EXCLUDE_CPP_MODULES "Exclude all C++ modules from the build" OFF)
|
||||
22
tools/EVerest-main/cmake/project-config.cmake.in
Normal file
22
tools/EVerest-main/cmake/project-config.cmake.in
Normal file
@@ -0,0 +1,22 @@
|
||||
set(@LIBRARY_PACKAGE_NAME@_VERSION @PROJECT_VERSION@)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(EVEREST_SCHEMA_DIR "@PACKAGE_EVEREST_DATADIR@/schemas")
|
||||
find_package(everest-log REQUIRED)
|
||||
find_package(everest-sqlite REQUIRED)
|
||||
find_package(everest-timer REQUIRED)
|
||||
find_package(everest-evse_security REQUIRED)
|
||||
find_package(everest-ocpp REQUIRED)
|
||||
find_dependency(ryml REQUIRED)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/ev-project-bootstrap.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/everest-core-targets.cmake)
|
||||
find_package(everest-framework REQUIRED)
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
ev_add_project(
|
||||
EV_PROJECT_DIRECTORY @PACKAGE_EVEREST_DATADIR@
|
||||
EV_PROJECT_NAME everest-core
|
||||
SKIP_DOC_GENERATION
|
||||
)
|
||||
18
tools/EVerest-main/cmake/trailbook-ext-everest/README.md
Normal file
18
tools/EVerest-main/cmake/trailbook-ext-everest/README.md
Normal 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.
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
112
tools/EVerest-main/cmake/trailbook-ext-everest/process_api_template.py
Executable file
112
tools/EVerest-main/cmake/trailbook-ext-everest/process_api_template.py
Executable 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)
|
||||
@@ -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))
|
||||
192
tools/EVerest-main/cmake/trailbook-ext-everest/process_template.py
Executable file
192
tools/EVerest-main/cmake/trailbook-ext-everest/process_template.py
Executable 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)
|
||||
@@ -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 %}
|
||||
@@ -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 %}
|
||||
@@ -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 %}
|
||||
@@ -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) -}}
|
||||
@@ -0,0 +1,9 @@
|
||||
=========================================================
|
||||
{{ HEADLINE }}
|
||||
=========================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
*/autogenerated
|
||||
@@ -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) }}
|
||||
@@ -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()
|
||||
@@ -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")
|
||||
181
tools/EVerest-main/cmake/trailbook/EXTENDING.md
Normal file
181
tools/EVerest-main/cmake/trailbook/EXTENDING.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Extending the trailbook package
|
||||
|
||||
The trailbook package provides a set of targets and target properties
|
||||
that can be used to hook into the build process of the trailbook documentation
|
||||
and extend it with custom functionality.
|
||||
|
||||
## Important Note
|
||||
|
||||
Since the trailbook packages work a lot with custom CMake targets and
|
||||
custom CMake commands, it is important to set dependencies correctly
|
||||
when extending the trailbook package.
|
||||
|
||||
This means that it is not sufficient to just depend on the targets
|
||||
and extend target dependencies with `add_dependencies()`. Instead,
|
||||
you should also make sure to extend the file-level dependencies. For this
|
||||
a set of custom target properties is provided that can be used
|
||||
to add additional dependencies to the custom commands used in the
|
||||
trailbook build process.
|
||||
|
||||
## Available Stages to Hook Into
|
||||
|
||||
To hook into the build process custom commands can be placed in between
|
||||
stages
|
||||
|
||||
### Hook in before stage: Prepare Sphinx Source
|
||||
|
||||
If you want to hook into the build process before the Sphinx source
|
||||
is prepared, you can define a custom command that doesn't need to
|
||||
depend on any files, but the created files and targets should be appended to
|
||||
the target list property `ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE`.
|
||||
|
||||
This can be done by using the following code snippet:
|
||||
|
||||
```cmake
|
||||
# Your custom cmake code here
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
COMMAND
|
||||
<your_command_here>
|
||||
DEPENDS
|
||||
<your_dependencies_here>
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
<wrapper_target_name>
|
||||
DEPENDS
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
)
|
||||
|
||||
# Hook into the trailbook build process
|
||||
set_property(
|
||||
TARGET trailbook_<trailbook_name>
|
||||
APPEND
|
||||
PROPERTY
|
||||
ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE
|
||||
<wrapper_target_name>
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
)
|
||||
```
|
||||
|
||||
* `<output_file1>`, `<output_file2>` can be any custom files created
|
||||
by your command.
|
||||
* `<wrapper_target_name>` is a custom target that
|
||||
wraps your command for example.
|
||||
* `<trailbook_name>` should be replaced with the name of your trailbook
|
||||
provided in the `add_trailbook()` function call.
|
||||
|
||||
With this target-level dependencies and file-level dependencies can be added.
|
||||
If there is a target that depends on the output files, the file-level
|
||||
dependencies should be added as well.
|
||||
|
||||
### Hook in before stage: Build Sphinx
|
||||
|
||||
If you want to hook in before the Sphinx build process starts,
|
||||
you can use the target list property `ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE`.
|
||||
and `DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER` to add file-level dependencies
|
||||
to the stage before.
|
||||
|
||||
This can be done by using the following code snippet:
|
||||
|
||||
```cmake
|
||||
# Hook into the trailbook build process after the prepare stage
|
||||
get_target_property(
|
||||
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
|
||||
trailbook_<trailbook_name>
|
||||
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
|
||||
)
|
||||
|
||||
# Your custom cmake code here
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
DEPENDS
|
||||
<your_dependencies_here>
|
||||
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
|
||||
COMMAND
|
||||
<your_command_here>
|
||||
)
|
||||
add_custom_target(
|
||||
<wrapper_target_name>
|
||||
DEPENDS
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
|
||||
)
|
||||
|
||||
# Hook into the trailbook build process before the build stage
|
||||
set_property(
|
||||
TARGET trailbook_<trailbook_name>
|
||||
APPEND
|
||||
PROPERTY
|
||||
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE
|
||||
<wrapper_target_name>
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
)
|
||||
```
|
||||
|
||||
* `<output_file1>`, `<output_file2>` can be any custom files created
|
||||
by your command.
|
||||
* `<wrapper_target_name>` is a custom target that
|
||||
wraps your command for example.
|
||||
* `<trailbook_name>` should be replaced with the name of your trailbook
|
||||
provided in the `add_trailbook()` function call.
|
||||
|
||||
With the `get_target_property()` call the file-level dependencies
|
||||
from the previous stage are retrieved and added to the custom command
|
||||
and the custom target. This ensures that the custom command is executed
|
||||
after the previous stage is completed.
|
||||
|
||||
With the `set_property()` call the custom target and the output files
|
||||
are added to the target-level dependencies of the build stage.
|
||||
This ensures that the build stage waits for the custom command
|
||||
to complete before starting the Sphinx build process.
|
||||
|
||||
### Hook in before stage: Post Process Sphinx
|
||||
|
||||
This can be done analogously to the previous stage, but using the target list property
|
||||
`ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE` and `DEPS_STAGE_BUILD_SPHINX_AFTER`.
|
||||
|
||||
```cmake
|
||||
# Hook into the trailbook build process after the build stage
|
||||
get_target_property(
|
||||
DEPS_STAGE_BUILD_SPHINX_AFTER
|
||||
trailbook_<trailbook_name>
|
||||
DEPS_STAGE_BUILD_SPHINX_AFTER
|
||||
)
|
||||
# Your custom cmake code here
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
DEPENDS
|
||||
<your_dependencies_here>
|
||||
${DEPS_STAGE_BUILD_SPHINX_AFTER}
|
||||
COMMAND
|
||||
<your_command_here>
|
||||
)
|
||||
add_custom_target(
|
||||
<wrapper_target_name>
|
||||
DEPENDS
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
${DEPS_STAGE_BUILD_SPHINX_AFTER}
|
||||
)
|
||||
# Hook into the trailbook build process before the post process stage
|
||||
set_property(
|
||||
TARGET trailbook_<trailbook_name>
|
||||
APPEND
|
||||
PROPERTY
|
||||
ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE
|
||||
<wrapper_target_name>
|
||||
<output_file1>
|
||||
<output_file2>
|
||||
)
|
||||
```
|
||||
137
tools/EVerest-main/cmake/trailbook/README.md
Normal file
137
tools/EVerest-main/cmake/trailbook/README.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# CMake Package trailbook
|
||||
|
||||
This package provides CMake functions and macros to include
|
||||
the build of a trailbook documentation in a CMake-based project.
|
||||
|
||||
## Usage in CMake
|
||||
|
||||
To use this package in your CMake project, include the following line in your `CMakeLists.txt` file:
|
||||
|
||||
```cmake
|
||||
find_package(
|
||||
trailbook
|
||||
0.1.0
|
||||
REQUIRED
|
||||
PATHS "${CMAKE_SOURCE_DIR}/<path-to-the-package>"
|
||||
)
|
||||
```
|
||||
|
||||
* Specify the version to make sure you are using
|
||||
a compatible version of the package.
|
||||
* If the package is not found, CMake will
|
||||
stop with an error due to the `REQUIRED` keyword.
|
||||
* If the package is not installed in a standard
|
||||
location, you can specify the path to the package using the `PATHS` option.
|
||||
|
||||
After finding the package, you can use the provided functions.
|
||||
At the moment, the package provides the following functions:
|
||||
|
||||
### `add_trailbook()`
|
||||
|
||||
This function is the initial call for your trailbook documentation.
|
||||
It can be called as follows:
|
||||
|
||||
```cmake
|
||||
add_trailbook(
|
||||
NAME <trailbook_name>
|
||||
[STEM_DIRECTORY <stem_directory>]
|
||||
[REQUIREMENTS_TXT <requirements_txt>]
|
||||
INSTANCE_NAME <instance_name>
|
||||
[DEPLOYED_DOCS_REPO_URL <deployed_docs_repo_url>]
|
||||
[DEPLOYED_DOCS_REPO_BRANCH <deployed_docs_repo_branch>]
|
||||
)
|
||||
```
|
||||
|
||||
* This function needs to be called once per trailbook.
|
||||
* The `NAME` argument specifies the name of the trailbook.
|
||||
This name will be used to create unique target names.
|
||||
* The optional `STEM_DIRECTORY` argument specifies the
|
||||
directory containing the Sphinx source files.
|
||||
If not provided, it defaults to `${CMAKE_CURRENT_SOURCE_DIR}`
|
||||
* The optional `REQUIREMENTS_TXT` argument specifies the path to a
|
||||
`requirements.txt` file for Python dependencies.
|
||||
If not provided, it defaults to `${STEM_DIRECTORY}/requirements.txt`,
|
||||
if this file exists.
|
||||
This requirements file will be used to check if the required Python packages are installed and if not to install them, if a
|
||||
python virtual environment is active
|
||||
* The `INSTANCE_NAME` argument specifies the name that is used for
|
||||
the version in the multiversion structure.
|
||||
* The optional `DEPLOYED_DOCS_REPO_URL` argument specifies the URL of the
|
||||
repository where the already deployed documentation is located.
|
||||
It is required if `TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS` is set to `ON`.
|
||||
* The optional `DEPLOYED_DOCS_REPO_BRANCH` argument
|
||||
specifies the branch of the deployed documentation repository.
|
||||
It defaults to `main` if not provided.
|
||||
|
||||
## Configuring
|
||||
|
||||
There are several options that can be configured
|
||||
for each trailbook by setting CMake variables.
|
||||
|
||||
### `TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS`
|
||||
|
||||
* `<NAME>` should be replaced with the trailbook name provided
|
||||
in the `add_trailbook()` function call.
|
||||
|
||||
If `TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS` is set to `ON`,
|
||||
the build process will attempt to download all previously deployed versions
|
||||
of the trailbook from the specified repository. And then embed the
|
||||
new version into the multiversion structure.
|
||||
|
||||
If `TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS` is set to `OFF` (default),
|
||||
only the current version of the trailbook will be built. For this
|
||||
an empty multiversion skeleton will be created.
|
||||
|
||||
This configuration shouldn'T be changed after the first build.
|
||||
|
||||
### `TRAILBOOK_<NAME>_IS_RELEASE`
|
||||
|
||||
* `<NAME>` should be replaced with the trailbook name provided
|
||||
in the `add_trailbook()` function call.
|
||||
|
||||
If `TRAILBOOK_<NAME>_IS_RELEASE` is set to `ON` (default),
|
||||
the trailbook will be built as a release version. This means
|
||||
that the `latest` version is updated, and the `index.html` and
|
||||
`404.html` files are updated.
|
||||
|
||||
If `TRAILBOOK_<NAME>_IS_RELEASE` is set to `OFF`,
|
||||
the mentioned files are not updated, and the `latest` version
|
||||
is not changed. This can be used for example to build
|
||||
nightly versions without affecting the released version.
|
||||
|
||||
## Building
|
||||
|
||||
To build the trailbook documentation, simply run the following command, after configuring the project with CMake:
|
||||
|
||||
```bash
|
||||
cmake --build <build_directory> --target trailbook_<trailbook_name>
|
||||
```
|
||||
|
||||
* Replace `<build_directory>` with the path to your CMake build directory.
|
||||
* Replace `<trailbook_name>` with the name of your trailbook
|
||||
provided in the `add_trailbook()` function call.
|
||||
|
||||
This target will trigger the full build of the trailbook documentation
|
||||
|
||||
Furthermore, you can use the following additional targets:
|
||||
|
||||
```bash
|
||||
cmake --build <build_directory> --target trailbook_<trailbook_name>_preview
|
||||
```
|
||||
|
||||
This target will start a local server to preview the built documentation.
|
||||
|
||||
```bash
|
||||
cmake --build <build_directory> --target trailbook_<trailbook_name>_live_preview
|
||||
```
|
||||
This target will start a local server that watches for changes
|
||||
in the source files and automatically rebuilds the documentation
|
||||
and refreshes the preview in the browser.
|
||||
|
||||
## How to build a extension for the trailbook package
|
||||
|
||||
The trailbook package provides a set of targets and target properties
|
||||
that can be used to hook into the build process of the trailbook documentation
|
||||
and extend it with custom functionality.
|
||||
|
||||
See the full explanation in the [EXTENDING.md](EXTENDING.md) file.
|
||||
721
tools/EVerest-main/cmake/trailbook/add-trailbook.cmake
Normal file
721
tools/EVerest-main/cmake/trailbook/add-trailbook.cmake
Normal file
@@ -0,0 +1,721 @@
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It checks the requirements defined by the requirements.txt file
|
||||
# and installs any missing packages into the current Python virtual environment.
|
||||
# It checks during the configuration phase.
|
||||
macro(_add_trailbook_check_requirements_txt)
|
||||
if(EXISTS ${args_REQUIREMENTS_TXT})
|
||||
execute_process(
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_requirements_txt.py
|
||||
${args_REQUIREMENTS_TXT}
|
||||
--fix-in-venv
|
||||
RESULT_VARIABLE _CHECK_REQUIREMENTS_TXT_RESULT
|
||||
)
|
||||
|
||||
if(NOT _CHECK_REQUIREMENTS_TXT_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Trailbook: ${args_NAME} - ${args_REQUIREMENTS_TXT} not satisfied.")
|
||||
else()
|
||||
message(STATUS "Trailbook: ${args_NAME} - ${args_REQUIREMENTS_TXT} satisfied.")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Trailbook: ${args_NAME} - No requirements.txt found.")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It sets up the trailbook build directory where the multiversion HTML docs will be located.
|
||||
# If TRAILBOOK_INSTANCE_DOWNLOAD_ALL_VERSIONS is ON, it clones the deployed docs repo.
|
||||
# Otherwise, it creates an empty skeleton directory.
|
||||
# This configuration is checked during the configuration phase and should not be switched
|
||||
macro(_add_trailbook_setup_build_directory)
|
||||
set(CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/setup_build_directory.check_done")
|
||||
set(SETUP_BUILD_DIRECTORY_FILE_LIST "${CMAKE_CURRENT_BINARY_DIR}/setup_build_directory_filelist.yaml")
|
||||
set(DEPLOYED_DOCS_REPO_DIR "${CMAKE_CURRENT_BINARY_DIR}/deployed_docs_repo/")
|
||||
|
||||
if(TRAILBOOK_INSTANCE_DOWNLOAD_ALL_VERSIONS)
|
||||
if(_SETUP_BUILD_DIRECTORY_LAST_CONFIGURATION STREQUAL "EMPTY_SKELETON")
|
||||
message(FATAL_ERROR "add_trailbook: Cannot switch between DOWNLOAD_ALL_VERSIONS and EMPTY_SKELETON configurations for trailbook ${args_NAME} without cleaning build directory")
|
||||
endif()
|
||||
else()
|
||||
if(_SETUP_BUILD_DIRECTORY_LAST_CONFIGURATION STREQUAL "DOWNLOAD_ALL_VERSIONS")
|
||||
message(FATAL_ERROR "add_trailbook: Cannot switch between DOWNLOAD_ALL_VERSIONS and EMPTY_SKELETON configurations for trailbook ${args_NAME} without cleaning build directory")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TRAILBOOK_INSTANCE_DOWNLOAD_ALL_VERSIONS)
|
||||
find_program(
|
||||
GIT_EXECUTABLE
|
||||
NAMES git
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
set(CONDITIONAL_DELETE_LATEST_DIR_COMMAND "")
|
||||
if(TRAILBOOK_INSTANCE_IS_RELEASE)
|
||||
set(CONDITIONAL_DELETE_LATEST_DIR_COMMAND
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -rf
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download/docs/latest
|
||||
)
|
||||
endif()
|
||||
|
||||
set(CONDITIONAL_DELETE_INSTANCE_DIR_OR_FAIL_COMMAND "")
|
||||
if(TRAILBOOK_${args_NAME}_OVERWRITE_EXISTING_INSTANCE)
|
||||
set(CONDITIONAL_DELETE_INSTANCE_DIR_OR_FAIL_COMMAND
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -rf
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download/docs/${TRAILBOOK_${args_NAME}_INSTANCE_NAME}
|
||||
)
|
||||
else()
|
||||
# check if instance directory already exists and fail if it does
|
||||
set(CONDITIONAL_DELETE_INSTANCE_DIR_OR_FAIL_COMMAND
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
--directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download/docs/${TRAILBOOK_${args_NAME}_INSTANCE_NAME}
|
||||
--return-zero-if-not-exists
|
||||
)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE>
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
${Python3_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Downloading all versions repo"
|
||||
COMMAND # Remove existing files in deployed docs repo directory from previous builds
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
remove
|
||||
--data-file ${SETUP_BUILD_DIRECTORY_FILE_LIST}
|
||||
--root-directory ${DEPLOYED_DOCS_REPO_DIR}
|
||||
COMMAND # Clone deployed docs repo
|
||||
${GIT_EXECUTABLE} clone
|
||||
-b ${args_DEPLOYED_DOCS_REPO_BRANCH}
|
||||
--depth 1
|
||||
${args_DEPLOYED_DOCS_REPO_URL}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download/
|
||||
# Remove latest directory if this is a release instance
|
||||
${CONDITIONAL_DELETE_LATEST_DIR_COMMAND}
|
||||
# Remove existing instance directory if overwrite is enabled or fail if it exists
|
||||
${CONDITIONAL_DELETE_INSTANCE_DIR_OR_FAIL_COMMAND}
|
||||
COMMAND # Create file list of existing files in deployed docs repo directory after clone
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
create
|
||||
--data-file ${SETUP_BUILD_DIRECTORY_FILE_LIST}
|
||||
--root-directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download
|
||||
COMMAND # Move cloned files to deployed docs repo directory
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
move
|
||||
--data-file ${SETUP_BUILD_DIRECTORY_FILE_LIST}
|
||||
--root-directory ${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download
|
||||
--target-root-directory ${DEPLOYED_DOCS_REPO_DIR}/
|
||||
COMMAND # Delete temporary clone directory
|
||||
${CMAKE_COMMAND} -E rm -rf
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tmp_repo_download/
|
||||
COMMAND # Create convenience symlink to docs/ in build directory
|
||||
${CMAKE_COMMAND} -E create_symlink
|
||||
${DEPLOYED_DOCS_REPO_DIR}/docs/
|
||||
${TRAILBOOK_BUILD_DIRECTORY}
|
||||
COMMAND # Create done file
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
)
|
||||
set(_SETUP_BUILD_DIRECTORY_LAST_CONFIGURATION "DOWNLOAD_ALL_VERSIONS")
|
||||
else()
|
||||
set(CONDITIONAL_CLEANUP_COMMAND "")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE>
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Creating empty skeleton multiversion root directory"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E make_directory
|
||||
${TRAILBOOK_BUILD_DIRECTORY}/
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
)
|
||||
set(_SETUP_BUILD_DIRECTORY_LAST_CONFIGURATION "EMPTY_SKELETON")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It adds a custom command to copy the trailbook stem files to the build directory.
|
||||
# To be used a base for the tailbook instance source directory.
|
||||
macro(_add_trailbook_copy_stem_command)
|
||||
file(
|
||||
GLOB_RECURSE
|
||||
STEM_FILES_SOURCE_DIR
|
||||
CONFIGURE_DEPENDS
|
||||
"${args_STEM_DIRECTORY}/*"
|
||||
)
|
||||
|
||||
set(STEM_FILES_BUILD_DIR "")
|
||||
foreach(file_path IN LISTS STEM_FILES_SOURCE_DIR)
|
||||
file(RELATIVE_PATH rel_path "${args_STEM_DIRECTORY}" "${file_path}")
|
||||
list(APPEND STEM_FILES_BUILD_DIR "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}/${rel_path}")
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${STEM_FILES_BUILD_DIR}
|
||||
DEPENDS
|
||||
${STEM_FILES_SOURCE_DIR}
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE>
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Copying stem files to build directory"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
remove
|
||||
--data-file ${CMAKE_CURRENT_BINARY_DIR}/copy_stem_filelist.yaml
|
||||
--root-directory ${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
create
|
||||
--data-file ${CMAKE_CURRENT_BINARY_DIR}/copy_stem_filelist.yaml
|
||||
--root-directory ${args_STEM_DIRECTORY}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_directory
|
||||
${args_STEM_DIRECTORY}
|
||||
${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It adds a custom command to create the metadata YAML file for the trailbook instance.
|
||||
# The metadata YAML file is used by Sphinx during the build process.
|
||||
# It contains a list of all versions available in the multiversion root directory.
|
||||
macro(_add_trailbook_create_metadata_yaml_command)
|
||||
set(METADATA_YAML_FILE "${CMAKE_CURRENT_BINARY_DIR}/metadata_${args_NAME}.yaml")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${METADATA_YAML_FILE}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/create_metadata_yaml.py
|
||||
${STEM_FILES_BUILD_DIR}
|
||||
${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE>
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Creating metadata YAML file"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -f ${METADATA_YAML_FILE}
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/create_metadata_yaml.py
|
||||
--multiversion-root-directory "${TRAILBOOK_BUILD_DIRECTORY}"
|
||||
"--output-path" "${METADATA_YAML_FILE}"
|
||||
--additional-version "${TRAILBOOK_${args_NAME}_INSTANCE_NAME}"
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It adds a custom command to build the Sphinx HTML documentation for the trailbook instance.
|
||||
# It builds from the trailbook instance source directory to the trailbook instance build directory.
|
||||
macro(_add_trailbook_sphinx_build_command)
|
||||
set(CHECK_DONE_FILE_SPHINX_BUILD_COMMAND "${CMAKE_CURRENT_BINARY_DIR}/build_html.check_done")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_build_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE>
|
||||
${STEM_FILES_BUILD_DIR}
|
||||
${METADATA_YAML_FILE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Building HTML documentation with Sphinx"
|
||||
USES_TERMINAL
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
remove
|
||||
--data-file ${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_filelist.yaml
|
||||
--root-directory ${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}/
|
||||
COMMAND
|
||||
EVEREST_METADATA_YAML_PATH=${METADATA_YAML_FILE}
|
||||
${_SPHINX_BUILD_EXECUTABLE}
|
||||
-b html
|
||||
${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_temp/
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
create
|
||||
--data-file ${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_filelist.yaml
|
||||
--root-directory ${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_temp/
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/filelist_manager.py
|
||||
move
|
||||
--data-file ${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_filelist.yaml
|
||||
--root-directory ${CMAKE_CURRENT_BINARY_DIR}/sphinx_build_temp/
|
||||
--target-root-directory ${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}/
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E echo
|
||||
"Trailbook: ${args_NAME} - HTML documentation built at ${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It adds a custom command to replace the 'latest' copy in the multiversion root directory
|
||||
# It should be only called if TRAILBOOK_INSTANCE_IS_RELEASE is ON.
|
||||
macro(_add_trailbook_replace_latest_command)
|
||||
set(CHECK_DONE_FILE_REPLACE_LATEST "${CMAKE_CURRENT_BINARY_DIR}/replace_latest.check_done")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_REPLACE_LATEST}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Replacing 'latest' copy with copy of current instance"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -rf ${TRAILBOOK_BUILD_DIRECTORY}/latest
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_directory
|
||||
${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}
|
||||
${TRAILBOOK_BUILD_DIRECTORY}/latest
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_REPLACE_LATEST}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It copies the 404.html file from the trailbook instance build directory
|
||||
# to the multiversion root directory.
|
||||
# It should only be called if TRAILBOOK_INSTANCE_IS_RELEASE is ON.
|
||||
macro(_add_trailbook_copy_404_command)
|
||||
set(CHECK_DONE_FILE_COPY_404 "${CMAKE_CURRENT_BINARY_DIR}/copy_404.check_done")
|
||||
set(TRAILBOOK_404_FILE "${TRAILBOOK_BUILD_DIRECTORY}/404.html")
|
||||
set(TRAILBOOK_INSTANCE_404_FILE "${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}/404.html")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${TRAILBOOK_INSTANCE_404_FILE}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Checking for 404.html in built documentation"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
--file "${TRAILBOOK_INSTANCE_404_FILE}"
|
||||
--return-zero-if-exists
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_COPY_404}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${TRAILBOOK_INSTANCE_404_FILE}
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Copying 404.html to multiversion root directory"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -f ${TRAILBOOK_404_FILE}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy
|
||||
${TRAILBOOK_INSTANCE_404_FILE}
|
||||
${TRAILBOOK_404_FILE}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_COPY_404}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_tailbook.
|
||||
# It adds a custom command to render the redirect template. The rendered file
|
||||
# will be used as the index.html in the multiversion root directory.
|
||||
# This macro should only be called if TRAILBOOK_INSTANCE_IS_RELEASE is ON.
|
||||
macro(_add_trailbook_render_redirect_template_command)
|
||||
set(CHECK_DONE_FILE_RENDER_REDIRECT_TEMPLATE "${CMAKE_CURRENT_BINARY_DIR}/render_redirect_template.check_done")
|
||||
set(REDIRECT_TEMPLATE_FILE "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/templates/redirect.html.jinja")
|
||||
set(TRAILBOOK_REDIRECT_FILE "${TRAILBOOK_BUILD_DIRECTORY}/index.html")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_RENDER_REDIRECT_TEMPLATE}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/render_redirect_template.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Rendering redirect.html from template"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -f ${TRAILBOOK_REDIRECT_FILE}
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/render_redirect_template.py
|
||||
--redirect-template "${REDIRECT_TEMPLATE_FILE}"
|
||||
"--target-path" "${TRAILBOOK_REDIRECT_FILE}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_RENDER_REDIRECT_TEMPLATE}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_trailbook.
|
||||
# It adds a custom command to copy the versions_index.html file to the multiversion root directory
|
||||
macro(_add_trailbook_copy_versions_index_command)
|
||||
set(CHECK_DONE_FILE_COPY_VERSIONS_INDEX "${CMAKE_CURRENT_BINARY_DIR}/copy_versions_index.check_done")
|
||||
set(TRAILBOOK_VERSIONS_INDEX_FILE "${TRAILBOOK_BUILD_DIRECTORY}/versions_index.html")
|
||||
set(TRAILBOOK_INSTANCE_VERSIONS_INDEX_FILE "${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}/versions_index.html")
|
||||
set(CHECK_DONE_FILE_CHECK_LATEST_INSTANCE "${CMAKE_CURRENT_BINARY_DIR}/check_latest_instance.check_done")
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${TRAILBOOK_INSTANCE_VERSIONS_INDEX_FILE}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Checking for versions_index.html in built documentation"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
--file "${TRAILBOOK_INSTANCE_VERSIONS_INDEX_FILE}"
|
||||
--return-zero-if-exists
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_CHECK_LATEST_INSTANCE}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${CHECK_DONE_FILE_REPLACE_LATEST}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Checking for latest/ in multiversion root directory"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_path_exists.py
|
||||
--directory ${TRAILBOOK_BUILD_DIRECTORY}/latest
|
||||
--return-zero-if-exists
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_CHECK_LATEST_INSTANCE}
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CHECK_DONE_FILE_COPY_VERSIONS_INDEX}
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
${TRAILBOOK_INSTANCE_VERSIONS_INDEX_FILE}
|
||||
${CHECK_DONE_FILE_CHECK_LATEST_INSTANCE}
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Copying versions_index.html to multiversion root directory"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rm -f ${TRAILBOOK_VERSIONS_INDEX_FILE}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy
|
||||
${TRAILBOOK_INSTANCE_VERSIONS_INDEX_FILE}
|
||||
${TRAILBOOK_VERSIONS_INDEX_FILE}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E touch ${CHECK_DONE_FILE_COPY_VERSIONS_INDEX}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_tailbook.
|
||||
# It adds a custom target to serve the built HTML documentation via a simple HTTP server.
|
||||
macro(_add_trailbook_preview_target)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_preview
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Serve HTML documentation"
|
||||
USES_TERMINAL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E echo
|
||||
"Trailbook: ${args_NAME} - Serving HTML output at http://localhost:8000/"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE} -m http.server --directory ${TRAILBOOK_BUILD_DIRECTORY} 8000
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This macro is for internal use only
|
||||
#
|
||||
# It is used in the function add_tailbook.
|
||||
# It adds a custom target to watch the trailbook instance target for changes
|
||||
# and automatically rebuild the HTML documentation with Sphinx and serve it.
|
||||
macro(_add_trailbook_live_preview_target)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_live_preview
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/target_observer.py
|
||||
COMMENT
|
||||
"Trailbook: ${args_NAME} - Auto-build HTML documentation with Sphinx and serve"
|
||||
USES_TERMINAL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E echo
|
||||
"Trailbook: ${args_NAME} - Auto-building HTML output and serving at http://localhost:8000/"
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/target_observer.py
|
||||
"trailbook_${args_NAME}"
|
||||
"trailbook_${args_NAME}_preview"
|
||||
--build-dir ${CMAKE_BINARY_DIR}
|
||||
--interval-ms 2000
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# This is the main function to add a trailbook to the build system.
|
||||
# It sets up the necessary build commands and targets
|
||||
# to build the trailbook documentation.
|
||||
# It takes the following parameters:
|
||||
# NAME (required): The name of the trailbook.
|
||||
# STEM_DIRECTORY (optional): The directory containing the trailbook stem files.
|
||||
# Defaults to CMAKE_CURRENT_SOURCE_DIR.
|
||||
# REQUIREMENTS_TXT (optional): The path to the requirements.txt file.
|
||||
# Defaults to CMAKE_CURRENT_SOURCE_DIR/requirements.txt if exists.
|
||||
# INSTANCE_NAME (required): The instance name for the trailbook.
|
||||
# Needs to be lowercase alphanumeric and underscores only.
|
||||
# DEPLOYED_DOCS_REPO_URL (optional): The URL of the deployed docs repository.
|
||||
# Required if TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS is ON.
|
||||
# DEPLOYED_DOCS_REPO_BRANCH (optional): The branch of the deployed docs repository.
|
||||
# Defaults to 'main'.
|
||||
# Usage:
|
||||
# add_trailbook(
|
||||
# NAME <trailbook_name>
|
||||
# [STEM_DIRECTORY <stem_directory>]
|
||||
# [REQUIREMENTS_TXT <requirements_txt_path>]
|
||||
# INSTANCE_NAME <instance_name>
|
||||
# [DEPLOYED_DOCS_REPO_URL <deployed_docs_repo_url>]
|
||||
# [DEPLOYED_DOCS_REPO_BRANCH <deployed_docs_repo_branch>]
|
||||
# )
|
||||
function(add_trailbook)
|
||||
set(options)
|
||||
set(one_value_args
|
||||
NAME
|
||||
STEM_DIRECTORY
|
||||
REQUIREMENTS_TXT
|
||||
DEPLOYED_DOCS_REPO_URL
|
||||
DEPLOYED_DOCS_REPO_BRANCH
|
||||
)
|
||||
set(multi_value_args)
|
||||
cmake_parse_arguments(
|
||||
"args"
|
||||
"${options}"
|
||||
"${one_value_args}"
|
||||
"${multi_value_args}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
option(TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS "Download all versions for trailbook ${args_NAME} and build complete trailbook" OFF)
|
||||
option(TRAILBOOK_${args_NAME}_IS_RELEASE "If enabled, the trailbook ${args_NAME} will be marked as release version in versions index" ON)
|
||||
set(TRAILBOOK_${args_NAME}_INSTANCE_NAME "local" CACHE STRING "Instance name for trailbook ${args_NAME}")
|
||||
option(TRAILBOOK_${args_NAME}_OVERWRITE_EXISTING_INSTANCE "Overwrite existing instance with name ${TRAILBOOK_${args_NAME}_INSTANCE_NAME} if it exists" OFF)
|
||||
# Check that at least one of DOWNLOAD_ALL_VERSIONS or IS_RELEASE is ON
|
||||
if(NOT TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS AND NOT TRAILBOOK_${args_NAME}_IS_RELEASE)
|
||||
message(FATAL_ERROR "add_trailbook: TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS and TRAILBOOK_${args_NAME}_IS_RELEASE cannot both be OFF")
|
||||
endif()
|
||||
# Check that instance name is lowercase alphanumeric and underscores only
|
||||
string(REGEX MATCH "^[a-z0-9_]+$" _valid_instance_name "${TRAILBOOK_${args_NAME}_INSTANCE_NAME}")
|
||||
if("${_valid_instance_name}" STREQUAL "")
|
||||
message(FATAL_ERROR "add_trailbook: TRAILBOOK_${args_NAME}_INSTANCE_NAME needs to be lowercase alphanumeric and underscores only")
|
||||
endif()
|
||||
|
||||
# Parameter NAME
|
||||
# is required
|
||||
if("${args_NAME}" STREQUAL "")
|
||||
message(FATAL_ERROR "add_trailbook: NAME argument is required")
|
||||
endif()
|
||||
|
||||
# Parameter STEM_DIRECTORY
|
||||
# - defaults to CMAKE_CURRENT_SOURCE_DIR
|
||||
# - needs to be absolute path
|
||||
if("${args_STEM_DIRECTORY}" STREQUAL "")
|
||||
set(args_STEM_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
if(NOT IS_ABSOLUTE "${args_STEM_DIRECTORY}")
|
||||
message(FATAL_ERROR "add_trailbook: STEM_DIRECTORY needs to be an absolute path")
|
||||
endif()
|
||||
cmake_path(SET args_STEM_DIRECTORY NORMALIZE ${args_STEM_DIRECTORY})
|
||||
|
||||
# Parameter REQUIREMENTS_TXT
|
||||
# - defaults to ${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt if exists
|
||||
# - needs to be absolute path if set
|
||||
if("${args_REQUIREMENTS_TXT}" STREQUAL "")
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
|
||||
set(args_REQUIREMENTS_TXT "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT "${args_REQUIREMENTS_TXT}" STREQUAL "")
|
||||
if(NOT IS_ABSOLUTE "${args_REQUIREMENTS_TXT}")
|
||||
message(FATAL_ERROR "add_trailbook: REQUIREMENTS_TXT needs to be an absolute path")
|
||||
endif()
|
||||
if(NOT EXISTS "${args_REQUIREMENTS_TXT}")
|
||||
message(FATAL_ERROR "add_trailbook: REQUIREMENTS_TXT file does not exist: ${args_REQUIREMENTS_TXT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Parameter DEPLOYED_DOCS_REPO_URL
|
||||
# - required if TRAILBOOK_<NAME>_DOWNLOAD_ALL_VERSIONS is ON
|
||||
if(TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS AND "${args_DEPLOYED_DOCS_REPO_URL}" STREQUAL "")
|
||||
message(FATAL_ERROR "add_trailbook: DEPLOYED_DOCS_REPO_URL argument is required if TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS is ON")
|
||||
endif()
|
||||
|
||||
# Parameter DEPLOYED_DOCS_REPO_BRANCH
|
||||
# - defaults to 'main'
|
||||
if("${args_DEPLOYED_DOCS_REPO_BRANCH}" STREQUAL "")
|
||||
set(args_DEPLOYED_DOCS_REPO_BRANCH "main")
|
||||
endif()
|
||||
|
||||
set(TRAILBOOK_INSTANCE_SOURCE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/trailbook_${args_NAME}_source")
|
||||
set(TRAILBOOK_BUILD_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/trailbook_${args_NAME}_build")
|
||||
set(TRAILBOOK_INSTANCE_BUILD_DIRECTORY "${TRAILBOOK_BUILD_DIRECTORY}/${TRAILBOOK_${args_NAME}_INSTANCE_NAME}")
|
||||
set(TRAILBOOK_INSTANCE_IS_RELEASE "${TRAILBOOK_${args_NAME}_IS_RELEASE}")
|
||||
set(TRAILBOOK_INSTANCE_DOWNLOAD_ALL_VERSIONS "${TRAILBOOK_${args_NAME}_DOWNLOAD_ALL_VERSIONS}")
|
||||
|
||||
message(STATUS "Adding trailbook: ${args_NAME}")
|
||||
message(STATUS " Stem directory: ${args_STEM_DIRECTORY}")
|
||||
message(STATUS " Build directory: ${TRAILBOOK_BUILD_DIRECTORY}")
|
||||
message(STATUS " Instance source directory: ${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}")
|
||||
message(STATUS " Instance build directory: ${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}")
|
||||
if(NOT "${args_REQUIREMENTS_TXT}" STREQUAL "")
|
||||
message(STATUS " Requirements.txt: ${args_REQUIREMENTS_TXT}")
|
||||
else()
|
||||
message(STATUS " Requirements.txt: <none>")
|
||||
endif()
|
||||
message(STATUS " Deployed docs repo url: ${args_DEPLOYED_DOCS_REPO_URL}")
|
||||
message(STATUS " Deployed docs repo branch: ${args_DEPLOYED_DOCS_REPO_BRANCH}")
|
||||
|
||||
_add_trailbook_check_requirements_txt()
|
||||
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
DEPENDS
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE>
|
||||
)
|
||||
|
||||
_add_trailbook_setup_build_directory()
|
||||
_add_trailbook_copy_stem_command()
|
||||
_add_trailbook_create_metadata_yaml_command()
|
||||
set(DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_before
|
||||
${CHECK_DONE_FILE_SETUP_BUILD_DIRECTORY}
|
||||
${STEM_FILES_BUILD_DIR}
|
||||
${METADATA_YAML_FILE}
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_after
|
||||
DEPENDS
|
||||
${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}
|
||||
COMMENT
|
||||
"Prepare Sphinx source for trailbook: ${args_NAME}"
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_build_sphinx_before
|
||||
DEPENDS
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE>
|
||||
trailbook_${args_NAME}_stage_prepare_sphinx_source_after
|
||||
)
|
||||
_add_trailbook_sphinx_build_command()
|
||||
set(DEPS_STAGE_BUILD_SPHINX_AFTER
|
||||
trailbook_${args_NAME}_stage_build_sphinx_before
|
||||
${CHECK_DONE_FILE_SPHINX_BUILD_COMMAND}
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_build_sphinx_after
|
||||
DEPENDS
|
||||
${DEPS_STAGE_BUILD_SPHINX_AFTER}
|
||||
COMMENT
|
||||
"Build Sphinx documentation for trailbook: ${args_NAME}"
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
DEPENDS
|
||||
$<TARGET_PROPERTY:trailbook_${args_NAME},ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE>
|
||||
trailbook_${args_NAME}_stage_build_sphinx_after
|
||||
)
|
||||
if(TRAILBOOK_INSTANCE_IS_RELEASE)
|
||||
_add_trailbook_replace_latest_command()
|
||||
_add_trailbook_copy_404_command()
|
||||
_add_trailbook_render_redirect_template_command()
|
||||
endif()
|
||||
_add_trailbook_copy_versions_index_command()
|
||||
|
||||
set(DEPS_STAGE_POSTPROCESS_SPHINX_AFTER
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_before
|
||||
${CHECK_DONE_FILE_REPLACE_LATEST}
|
||||
${CHECK_DONE_FILE_COPY_404}
|
||||
${CHECK_DONE_FILE_COPY_VERSIONS_INDEX}
|
||||
${CHECK_DONE_FILE_RENDER_REDIRECT_TEMPLATE}
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_after
|
||||
DEPENDS
|
||||
${DEPS_STAGE_POSTPROCESS_SPHINX_AFTER}
|
||||
COMMENT
|
||||
"Post-process Sphinx documentation for trailbook: ${args_NAME}"
|
||||
)
|
||||
add_custom_target(
|
||||
trailbook_${args_NAME} ALL
|
||||
DEPENDS
|
||||
trailbook_${args_NAME}_stage_postprocess_sphinx_after
|
||||
COMMENT
|
||||
"Build trailbook: ${args_NAME}"
|
||||
)
|
||||
|
||||
_add_trailbook_preview_target()
|
||||
_add_trailbook_live_preview_target()
|
||||
|
||||
set_target_properties(
|
||||
trailbook_${args_NAME}
|
||||
PROPERTIES
|
||||
TRAILBOOK_INSTANCE_BUILD_DIRECTORY "${TRAILBOOK_INSTANCE_BUILD_DIRECTORY}"
|
||||
TRAILBOOK_BUILD_DIRECTORY "${TRAILBOOK_BUILD_DIRECTORY}"
|
||||
TRAILBOOK_INSTANCE_NAME "${TRAILBOOK_${args_NAME}_INSTANCE_NAME}"
|
||||
TRAILBOOK_INSTANCE_SOURCE_DIRECTORY "${TRAILBOOK_INSTANCE_SOURCE_DIRECTORY}"
|
||||
TRAILBOOK_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
ADDITIONAL_DEPS_STAGE_PREPARE_SPHINX_SOURCE_BEFORE ""
|
||||
ADDITIONAL_DEPS_STAGE_BUILD_SPHINX_BEFORE ""
|
||||
ADDITIONAL_DEPS_STAGE_POSTPROCESS_SPHINX_BEFORE ""
|
||||
DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER "${DEPS_STAGE_PREPARE_SPHINX_SOURCE_AFTER}"
|
||||
DEPS_STAGE_BUILD_SPHINX_AFTER "${DEPS_STAGE_BUILD_SPHINX_AFTER}"
|
||||
DEPS_STAGE_POSTPROCESS_SPHINX_AFTER "${DEPS_STAGE_POSTPROCESS_SPHINX_AFTER}"
|
||||
)
|
||||
endfunction()
|
||||
107
tools/EVerest-main/cmake/trailbook/check_path_exists.py
Executable file
107
tools/EVerest-main/cmake/trailbook/check_path_exists.py
Executable file
@@ -0,0 +1,107 @@
|
||||
#!/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 checks whether a directory exists or not and returns zero based on the flags provided.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Checks whether a directory exists or not and returns zero based on the flags provided')
|
||||
parser.add_argument(
|
||||
'--directory',
|
||||
type=Path,
|
||||
dest='directory',
|
||||
action='store',
|
||||
required=False,
|
||||
help='Directory to check for existence'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--file',
|
||||
type=Path,
|
||||
dest='file',
|
||||
action='store',
|
||||
required=False,
|
||||
help='Path to a file to check for existence'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--return-zero-if-exists',
|
||||
action='store_true',
|
||||
help='Return zero if the file/directory exists',
|
||||
dest='return_zero_if_exists',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--return-zero-if-not-exists',
|
||||
action='store_true',
|
||||
help='Return zero if the file/directory does not exist',
|
||||
dest='return_zero_if_not_exists',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.directory and not args.file:
|
||||
raise ValueError("Either --directory or --file must be specified")
|
||||
if args.return_zero_if_exists and args.return_zero_if_not_exists:
|
||||
raise ValueError("Cannot use both --return-zero-if-exists and --return-zero-if-not-exists at the same time")
|
||||
|
||||
if args.file:
|
||||
if not args.file.is_absolute():
|
||||
raise ValueError("File path must be absolute")
|
||||
if args.return_zero_if_exists:
|
||||
if not args.file.exists():
|
||||
print(f"❌ File does not exist at {args.file}")
|
||||
exit(1)
|
||||
if not args.file.is_file():
|
||||
print(f"❌ Path exists but is not a file at {args.file}")
|
||||
exit(2)
|
||||
print(f"✅ File exists at {args.file}")
|
||||
exit(0)
|
||||
elif args.return_zero_if_not_exists:
|
||||
if args.file.is_file():
|
||||
print(f"❌ File exists at {args.file}")
|
||||
exit(1)
|
||||
if args.file.exists():
|
||||
print(f"❌ Path exists but is not a file at {args.file}")
|
||||
exit(2)
|
||||
print(f"✅ File does not exist at {args.file}")
|
||||
exit(0)
|
||||
else:
|
||||
raise ValueError("Either --return-zero-if-exists or --return-zero-if-not-exists must be specified")
|
||||
else:
|
||||
if not args.directory.is_absolute():
|
||||
raise ValueError("Directory path must be absolute")
|
||||
if args.return_zero_if_exists:
|
||||
if not args.directory.exists():
|
||||
print(f"❌ Directory does not exist at {args.directory}")
|
||||
exit(1)
|
||||
if not args.directory.is_dir():
|
||||
print(f"❌ Path exists but is not a directory at {args.directory}")
|
||||
exit(2)
|
||||
print(f"✅ Directory exists at {args.directory}")
|
||||
exit(0)
|
||||
elif args.return_zero_if_not_exists:
|
||||
if args.directory.is_dir():
|
||||
print(f"❌ Directory exists at {args.directory}")
|
||||
exit(1)
|
||||
if args.directory.exists():
|
||||
print(f"❌ Path exists but is not a directory at {args.directory}")
|
||||
exit(2)
|
||||
print(f"✅ Directory does not exist at {args.directory}")
|
||||
exit(0)
|
||||
else:
|
||||
raise ValueError("Either --return-zero-if-exists or --return-zero-if-not-exists must be specified")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
exit(1)
|
||||
76
tools/EVerest-main/cmake/trailbook/check_requirements_txt.py
Executable file
76
tools/EVerest-main/cmake/trailbook/check_requirements_txt.py
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/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 checks whether the packages in a requirements.txt are satisfied.
|
||||
If run inside a virtual environment, it can optionally fix unmet requirements by running pip install -r.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from importlib.metadata import version, PackageNotFoundError
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
def parse_requirement(req_line: str):
|
||||
req_line = req_line.strip()
|
||||
if not req_line or req_line.startswith("#"):
|
||||
return None
|
||||
match = re.match(r"([a-zA-Z0-9_\-]+)==([0-9\.]+)", req_line)
|
||||
if match:
|
||||
return match.groups()
|
||||
return (req_line, None)
|
||||
|
||||
|
||||
def check_requirements(file_path: str, fix_in_venv: bool = False):
|
||||
errors = []
|
||||
with open(file_path, "r") as f:
|
||||
for line in f:
|
||||
parsed = parse_requirement(line)
|
||||
if not parsed:
|
||||
continue
|
||||
pkg, req_version = parsed
|
||||
try:
|
||||
installed_version = version(pkg)
|
||||
if req_version and installed_version != req_version:
|
||||
errors.append(f"{pkg}=={req_version} (installed: {installed_version})")
|
||||
except PackageNotFoundError:
|
||||
errors.append(f"{pkg}=={req_version or 'any version'} (not installed)")
|
||||
|
||||
if fix_in_venv and errors:
|
||||
if sys.prefix != sys.base_prefix:
|
||||
print(f"Attempting to fix requirements in the current venv: {sys.prefix}")
|
||||
subprocess.run([sys.executable, "-m", "pip", "install", "-r", file_path], check=True)
|
||||
return check_requirements(file_path, fix_in_venv=False)
|
||||
else:
|
||||
print("Not in a virtual environment. Cannot fix requirements automatically.")
|
||||
|
||||
if not errors:
|
||||
print("✅ All requirements are met.")
|
||||
else:
|
||||
print("❌ There are unmet requirements:")
|
||||
for e in errors:
|
||||
print(" ", e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Checks if the packages in a requirements.txt are satisfied.")
|
||||
parser.add_argument("requirements_file", type=str, help="Path to the requirements.txt")
|
||||
parser.add_argument("--fix-in-venv", action="store_true", help="Run pip install -r in the current venv if there are unmet requirements")
|
||||
args = parser.parse_args()
|
||||
check_requirements(args.requirements_file, args.fix_in_venv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
exit(1)
|
||||
85
tools/EVerest-main/cmake/trailbook/create_metadata_yaml.py
Executable file
85
tools/EVerest-main/cmake/trailbook/create_metadata_yaml.py
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/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 creates a trailbook_metadata.yaml file
|
||||
based on the versions found in the multiversion root directory.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import yaml
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Creates a trailbook_metadata.yaml file')
|
||||
|
||||
parser.add_argument(
|
||||
'--multiversion-root-directory',
|
||||
type=Path,
|
||||
dest='multiversion_root_dir',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path to the root directory of the multiversion documentation'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--output-path',
|
||||
type=Path,
|
||||
dest='output_path',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path where the trailbook_metadata.yaml file will be created'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--additional-version',
|
||||
type=str,
|
||||
dest='additional_versions',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Additional version to include in the metadata (can be used multiple times)'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.multiversion_root_dir.is_absolute():
|
||||
raise ValueError("Multiversion root directory must be absolute")
|
||||
if not args.multiversion_root_dir.is_dir():
|
||||
print(f"\033[33mWarning: {args.multiversion_root_dir} does not exist or is not a directory, it is treated as an empty multiversion root dir\033[0m")
|
||||
if not args.output_path.is_absolute():
|
||||
raise ValueError("Output path must be absolute")
|
||||
if args.output_path.exists():
|
||||
raise FileExistsError("Output path already exists")
|
||||
|
||||
versions_list = []
|
||||
if args.multiversion_root_dir.is_dir():
|
||||
for instance_dir in args.multiversion_root_dir.iterdir():
|
||||
if not instance_dir.is_dir():
|
||||
continue
|
||||
if not (instance_dir / 'index.html').is_file():
|
||||
continue
|
||||
versions_list.append(instance_dir.name)
|
||||
versions_list.extend(args.additional_versions)
|
||||
versions_list = list(set(versions_list))
|
||||
if len(versions_list) == 0:
|
||||
raise ValueError("No versions found in the specified multiversion root directory")
|
||||
versions_list.sort()
|
||||
|
||||
# create yaml content
|
||||
data = {
|
||||
'versions': versions_list
|
||||
}
|
||||
# render yaml content
|
||||
with args.output_path.open('w') as f:
|
||||
yaml.dump(data, f, default_flow_style=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
exit(1)
|
||||
223
tools/EVerest-main/cmake/trailbook/filelist_manager.py
Executable file
223
tools/EVerest-main/cmake/trailbook/filelist_manager.py
Executable file
@@ -0,0 +1,223 @@
|
||||
#!/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 provides command to manage a list of file paths
|
||||
It can be used for custom cmake commands to track created files and directories
|
||||
and later remove or move them.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import yaml
|
||||
|
||||
|
||||
def create_filelist(args):
|
||||
if not args.root_dir.exists():
|
||||
raise ValueError("Root directory does not exist")
|
||||
if not args.root_dir.is_dir():
|
||||
raise ValueError("Root directory must be a directory")
|
||||
|
||||
if args.data_file.exists():
|
||||
raise FileExistsError("Data file already exists")
|
||||
|
||||
file_paths = []
|
||||
directory_paths = []
|
||||
for item in args.root_dir.rglob('*'):
|
||||
relative_path = item.relative_to(args.root_dir)
|
||||
if item.is_dir():
|
||||
directory_paths.append(str(relative_path))
|
||||
elif item.is_file():
|
||||
file_paths.append(str(relative_path))
|
||||
else:
|
||||
raise ValueError(f"Unknown file type: {item}")
|
||||
|
||||
data = {
|
||||
'files': file_paths,
|
||||
'directories': directory_paths
|
||||
}
|
||||
|
||||
args.data_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with args.data_file.open('w') as f:
|
||||
yaml.dump(data, f)
|
||||
exit(0)
|
||||
|
||||
|
||||
def remove_filelist(args):
|
||||
if not args.data_file.exists():
|
||||
exit(0)
|
||||
if not args.data_file.is_file():
|
||||
raise ValueError("Data file path is not a file")
|
||||
|
||||
with args.data_file.open('r') as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
for file_path in data.get('files', []):
|
||||
full_path = args.root_dir / file_path
|
||||
if not full_path.exists():
|
||||
raise FileNotFoundError(f"File does not exist: {full_path}")
|
||||
if not full_path.is_file():
|
||||
raise ValueError(f"Path is not a file: {full_path}")
|
||||
full_path.unlink()
|
||||
|
||||
for dir_path in data.get('directories', []):
|
||||
full_path = args.root_dir / dir_path
|
||||
if not full_path.exists():
|
||||
raise FileNotFoundError(f"Directory does not exist: {full_path}")
|
||||
if not full_path.is_dir():
|
||||
raise ValueError(f"Path is not a directory: {full_path}")
|
||||
|
||||
if len(list(full_path.iterdir())) > 0:
|
||||
continue
|
||||
|
||||
full_path.rmdir()
|
||||
|
||||
args.data_file.unlink()
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
def move_filelist(args):
|
||||
if not args.root_dir.exists():
|
||||
raise ValueError("Root directory does not exist")
|
||||
if not args.root_dir.is_dir():
|
||||
raise ValueError("Root directory must be a directory")
|
||||
|
||||
if not args.data_file.exists():
|
||||
raise FileNotFoundError("Data file does not exist")
|
||||
if not args.data_file.is_file():
|
||||
raise ValueError("Data file path is not a file")
|
||||
|
||||
if not args.target_root_dir.is_absolute():
|
||||
raise ValueError("Target root directory must be absolute")
|
||||
if args.target_root_dir.exists():
|
||||
if not args.target_root_dir.is_dir():
|
||||
raise ValueError("Target root directory must be a directory")
|
||||
|
||||
with args.data_file.open('r') as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
for file_path in data.get('files', []):
|
||||
source_file = args.root_dir / file_path
|
||||
target_file = args.target_root_dir / file_path
|
||||
target_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
source_file.rename(target_file)
|
||||
|
||||
for dir_path in data.get('directories', []):
|
||||
source_dir = args.root_dir / dir_path
|
||||
target_dir = args.target_root_dir / dir_path
|
||||
if not target_dir.exists():
|
||||
source_dir.rename(target_dir)
|
||||
exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='This script provides command to manage a list of file paths')
|
||||
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
create_parser = subparsers.add_parser(
|
||||
"create",
|
||||
description="Creates the file with a list of all paths in it",
|
||||
add_help=True,
|
||||
)
|
||||
create_parser.add_argument(
|
||||
'--data-file',
|
||||
type=Path,
|
||||
dest='data_file',
|
||||
action='store',
|
||||
required=True,
|
||||
help='File to read/write from/to filelist'
|
||||
)
|
||||
create_parser.add_argument(
|
||||
'--root-directory',
|
||||
type=Path,
|
||||
dest='root_dir',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path to the directory to list'
|
||||
)
|
||||
create_parser.set_defaults(
|
||||
action_handler=create_filelist
|
||||
)
|
||||
|
||||
remove_parser = subparsers.add_parser(
|
||||
"remove",
|
||||
description="Removes all files and directories listed in the filelist",
|
||||
add_help=True,
|
||||
)
|
||||
remove_parser.add_argument(
|
||||
'--data-file',
|
||||
type=Path,
|
||||
dest='data_file',
|
||||
action='store',
|
||||
required=True,
|
||||
help='File to read/write from/to filelist'
|
||||
)
|
||||
remove_parser.add_argument(
|
||||
'--root-directory',
|
||||
type=Path,
|
||||
dest='root_dir',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path to the directory to list'
|
||||
)
|
||||
remove_parser.set_defaults(
|
||||
action_handler=remove_filelist
|
||||
)
|
||||
|
||||
move_parser = subparsers.add_parser(
|
||||
"move",
|
||||
description="Moves all files and directories listed in the filelist to a new root directory",
|
||||
add_help=True,
|
||||
)
|
||||
move_parser.add_argument(
|
||||
'--data-file',
|
||||
type=Path,
|
||||
dest='data_file',
|
||||
action='store',
|
||||
required=True,
|
||||
help='File to read/write from/to filelist'
|
||||
)
|
||||
move_parser.add_argument(
|
||||
'--root-directory',
|
||||
type=Path,
|
||||
dest='root_dir',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path to the directory to list'
|
||||
)
|
||||
move_parser.add_argument(
|
||||
'--target-root-directory',
|
||||
type=Path,
|
||||
dest='target_root_dir',
|
||||
action='store',
|
||||
required=True,
|
||||
help='Path to the target root directory to move files to'
|
||||
)
|
||||
move_parser.set_defaults(
|
||||
action_handler=move_filelist
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.root_dir.is_absolute():
|
||||
raise ValueError("Root directory must be absolute")
|
||||
|
||||
if not args.data_file.is_absolute():
|
||||
raise ValueError("Data file path must be absolute")
|
||||
|
||||
if 'action_handler' not in args:
|
||||
raise ValueError("No action specified")
|
||||
|
||||
args.action_handler(args)
|
||||
exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
80
tools/EVerest-main/cmake/trailbook/render_redirect_template.py
Executable file
80
tools/EVerest-main/cmake/trailbook/render_redirect_template.py
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/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 redirect template and generates a <target_file_name>.html file
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
import jinja2
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Process versions_index.html.jinja and place redirect.html in the output directory')
|
||||
parser.add_argument(
|
||||
'--redirect-template',
|
||||
type=Path,
|
||||
dest='redirect_template',
|
||||
action='store',
|
||||
required=True,
|
||||
help="Redirect jinja template file"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--target-path',
|
||||
type=Path,
|
||||
dest='target_path',
|
||||
action='store',
|
||||
required=True,
|
||||
help="Target path for the output"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--latest-release-name',
|
||||
type=str,
|
||||
dest='latest_release_name',
|
||||
action='store',
|
||||
default="latest",
|
||||
help="Name of the latest release"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.redirect_template.is_absolute():
|
||||
raise ValueError("Redirect template path must be absolute")
|
||||
if not args.redirect_template.exists():
|
||||
raise FileNotFoundError(
|
||||
"Redirect template path: '"
|
||||
+ str(args.redirect_template)
|
||||
+ "' doesn't exist"
|
||||
)
|
||||
if not args.redirect_template.is_file():
|
||||
raise FileNotFoundError(
|
||||
f"Redirect template path: '{args.redirect_template}' is not a file"
|
||||
)
|
||||
|
||||
template_dir = args.redirect_template.parent
|
||||
template_name = args.redirect_template.name
|
||||
|
||||
env = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(template_dir),
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True
|
||||
)
|
||||
|
||||
template = env.get_template(template_name)
|
||||
output = template.render(
|
||||
latest_release=args.latest_release_name
|
||||
)
|
||||
args.target_path.write_text(output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
exit(1)
|
||||
46
tools/EVerest-main/cmake/trailbook/setup-trailbook.cmake
Normal file
46
tools/EVerest-main/cmake/trailbook/setup-trailbook.cmake
Normal file
@@ -0,0 +1,46 @@
|
||||
# Internal macro to find the sphinx-build executable.
|
||||
macro(_find_sphinx_build)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${Python3_EXECUTABLE} -m sphinx.cmd.build --version
|
||||
RESULT_VARIABLE RESULT_SPHINX_VERSION
|
||||
)
|
||||
if("${RESULT_SPHINX_VERSION}" STREQUAL "0")
|
||||
set(_SPHINX_BUILD_EXECUTABLE "${Python3_EXECUTABLE}" "-m" "sphinx.cmd.build")
|
||||
else()
|
||||
set(_SPHINX_BUILD_EXECUTABLE "_SPHINX_BUILD_EXECUTABLE-NOTFOUND")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Internal macro to find sphinx-build, and if not found, try to install it in an active python venv.
|
||||
macro(_find_and_fix_sphinx_build)
|
||||
_find_sphinx_build()
|
||||
|
||||
if("${_SPHINX_BUILD_EXECUTABLE}" STREQUAL "_SPHINX_BUILD_EXECUTABLE-NOTFOUND")
|
||||
ev_is_python_venv_active(
|
||||
RESULT_VAR IS_PYTHON_VENV_ACTIVE
|
||||
)
|
||||
if(IS_PYTHON_VENV_ACTIVE)
|
||||
message(STATUS "sphinx-build executable not found in system, but python venv is active. Trying to use 'python3 -m pip install sphinx'.")
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip install sphinx
|
||||
)
|
||||
_find_sphinx_build()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if("${_SPHINX_BUILD_EXECUTABLE}" STREQUAL "_SPHINX_BUILD_EXECUTABLE-NOTFOUND")
|
||||
message(FATAL_ERROR "sphinx-build executable not found. Please install Sphinx. You can install it via pip: pip install sphinx")
|
||||
endif()
|
||||
|
||||
message(STATUS "Found sphinx-build: ${_SPHINX_BUILD_EXECUTABLE}")
|
||||
endmacro()
|
||||
|
||||
# Internal macro to set up the trailbook environment.
|
||||
macro(_setup_trailbook)
|
||||
if(NOT _TRAILBOOK_SETUP_DONE)
|
||||
_find_and_fix_sphinx_build()
|
||||
|
||||
set(_TRAILBOOK_SETUP_DONE TRUE)
|
||||
endif()
|
||||
endmacro()
|
||||
123
tools/EVerest-main/cmake/trailbook/target_observer.py
Executable file
123
tools/EVerest-main/cmake/trailbook/target_observer.py
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/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 starts a CMake target http server and triggers
|
||||
regular rebuilds of a specified CMake target upon changes.
|
||||
"""
|
||||
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import argparse
|
||||
import signal
|
||||
from pathlib import Path
|
||||
from rich.live import Live
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.layout import Layout
|
||||
from threading import Thread
|
||||
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def run_target(build_dir: Path, target: str, live_panel, panel_size: int) -> None:
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
"cmake",
|
||||
"--build", build_dir.as_posix(),
|
||||
"--target", target
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True
|
||||
)
|
||||
output_lines = []
|
||||
output_lines.append(f"Running target {target} at {time.strftime('%X')}\n")
|
||||
for line in iter(process.stdout.readline, ""):
|
||||
line = line.rstrip()
|
||||
output_lines.append(line)
|
||||
output_lines = output_lines[-panel_size:]
|
||||
live_panel.update(Panel("\n".join(output_lines), title=f"{target} output"))
|
||||
process.wait()
|
||||
|
||||
|
||||
def start_server(build_dir: Path, server_target: str, server_lines: list, live_panel, panel_size: int) -> subprocess.Popen:
|
||||
print(f"Starting server target {server_target}...")
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
"cmake",
|
||||
"--build", str(build_dir),
|
||||
"--target", server_target
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
)
|
||||
|
||||
def read_server_output():
|
||||
for line in iter(process.stdout.readline, ""):
|
||||
line = line.rstrip()
|
||||
server_lines.append(line)
|
||||
server_lines[:] = server_lines[-panel_size:]
|
||||
live_panel.update(Panel("\n".join(server_lines), title=f"{server_target} output"))
|
||||
|
||||
t = Thread(target=read_server_output, daemon=True)
|
||||
t.start()
|
||||
return process
|
||||
|
||||
|
||||
def stop_server(proc: subprocess.Popen) -> None:
|
||||
if proc and proc.poll() is None:
|
||||
print("Stopping server...")
|
||||
proc.send_signal(signal.SIGINT)
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.kill()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Watch CMake target and manage server target")
|
||||
parser.add_argument("watch_target", help="CMake target to monitor and rerun if changed")
|
||||
parser.add_argument("server_target", help="CMake target that runs the server")
|
||||
parser.add_argument("--build-dir", default="build", help="CMake build directory")
|
||||
parser.add_argument("--interval-ms", type=int, default=2000, help="Check interval in milliseconds")
|
||||
args = parser.parse_args()
|
||||
|
||||
build_dir = Path(args.build_dir)
|
||||
watch_target = args.watch_target
|
||||
server_target = args.server_target
|
||||
|
||||
panel_size = 10
|
||||
layout = Layout()
|
||||
layout.split_column(
|
||||
Layout(name="server", size=panel_size+2),
|
||||
Layout(name="watch", size=panel_size+2)
|
||||
)
|
||||
with Live(layout, console=console, refresh_per_second=1):
|
||||
server_lines = []
|
||||
server_lines.append("Starting server...")
|
||||
server_panel = Panel("\n".join(server_lines), title=f"{server_target} output")
|
||||
layout["server"].update(server_panel)
|
||||
watch_panel = Panel("\n\n\n", title=f"{watch_target} output")
|
||||
layout["watch"].update(watch_panel)
|
||||
|
||||
server_proc = start_server(build_dir, server_target, server_lines, layout["server"], panel_size)
|
||||
try:
|
||||
while True:
|
||||
time.sleep(args.interval_ms / 1000)
|
||||
run_target(build_dir, watch_target, layout["watch"], panel_size)
|
||||
except KeyboardInterrupt:
|
||||
stop_server(server_proc)
|
||||
print("\n Exiting.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Redirecting...
|
||||
</title>
|
||||
<meta http-equiv="refresh" content="0;url=./{{ latest_release }}">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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()
|
||||
@@ -0,0 +1,5 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/setup-trailbook.cmake")
|
||||
_setup_trailbook()
|
||||
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/add-trailbook.cmake")
|
||||
Reference in New Issue
Block a user