Files
cariflex/tools/EVerest-main/cmake/everest-generate.cmake
Eric F d398a6ced2 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
2026-06-08 00:38:27 -04:00

898 lines
32 KiB
CMake

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)