826 lines
29 KiB
CMake
826 lines
29 KiB
CMake
#
|
|
# Copyright 2018, Data61, CSIRO (ABN 41 687 119 230)
|
|
#
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
#
|
|
|
|
cmake_minimum_required(VERSION 3.7.2)
|
|
|
|
include(${KERNEL_HELPERS_PATH})
|
|
include(${PLATSUPPORT_HELPERS})
|
|
include(dts)
|
|
|
|
function(append_flags parent_list)
|
|
math(EXPR limit "${ARGC} - 1")
|
|
set(local_flags "${${parent_list}}")
|
|
foreach(i RANGE 1 ${limit})
|
|
set(list "${ARGV${i}}")
|
|
list(GET list 0 check)
|
|
string(
|
|
REGEX
|
|
REPLACE
|
|
" +"
|
|
";"
|
|
check
|
|
"${check}"
|
|
)
|
|
if(${check})
|
|
list(GET list 1 when_true)
|
|
list(APPEND local_flags "${when_true}")
|
|
else()
|
|
list(LENGTH list len)
|
|
if(${len} GREATER 2)
|
|
list(GET list 2 when_false)
|
|
list(APPEND local_flags "${when_false}")
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
set(${parent_list} "${local_flags}" PARENT_SCOPE)
|
|
endfunction(append_flags)
|
|
|
|
macro(set_config_guard)
|
|
set(${ARGV})
|
|
if(CAMKES_CONFIG_DEFAULT_ADVANCED)
|
|
mark_as_advanced(${ARGV0})
|
|
endif()
|
|
endmacro()
|
|
|
|
function(set_camkes_flags_from_config list)
|
|
|
|
set_config_guard(
|
|
CAmkESVerbose
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"Enable verbose output from CAmkES. This is disabled by default as it
|
|
can result in a lot of output, but is useful for debugging CAmkES problems"
|
|
)
|
|
|
|
set(local_flags "${${list}}")
|
|
append_flags(local_flags "CAmkESVerbose;--debug")
|
|
set(${list} "${local_flags}" PARENT_SCOPE)
|
|
endfunction(set_camkes_flags_from_config)
|
|
|
|
function(set_camkes_parser_flags_from_config list)
|
|
|
|
# These options are not declared with the config_* system because they only
|
|
# need to exist in the build system, and not appear in a configuration
|
|
# library
|
|
set_config_guard(
|
|
CAmkESCPP
|
|
ON
|
|
CACHE
|
|
BOOL
|
|
"Run CPP on the input specification(s) before parsing them into an AST.
|
|
This can allow you to write parameterised specs in the case of more
|
|
complex system"
|
|
)
|
|
set_config_guard(
|
|
CAmkESAllowForwardReferences
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"By default, you can only refer to objects in your specification which
|
|
have been defined before the point at which you reference them.
|
|
Selecting this option allows you to also reference objects that are
|
|
defined below the point at which the reference occurs. This option is
|
|
off by default because it leads to a slight performance degradation in
|
|
parsing specification"
|
|
)
|
|
set(local_flags "${${list}}")
|
|
append_flags(
|
|
local_flags "CAmkESAllowForwardReferences;--allow-forward-references"
|
|
"CAmkESCPP;--cpp;--nocpp"
|
|
)
|
|
if(CAmkESCPP)
|
|
find_program(C_PREPROCESSOR cpp)
|
|
if("${C_PREPROCESSOR}" STREQUAL "C_PREPROCESSOR-NOTFOUND")
|
|
message(FATAL_ERROR "Could not find cpp. Override with -DC_PREPROCESSOR=path/to/cpp")
|
|
endif()
|
|
mark_as_advanced(C_PREPROCESSOR)
|
|
list(APPEND local_flags --cpp-bin "${C_PREPROCESSOR}")
|
|
endif()
|
|
set(${list} "${local_flags}" PARENT_SCOPE)
|
|
|
|
endfunction(set_camkes_parser_flags_from_config)
|
|
|
|
function(set_camkes_render_flags_from_config list)
|
|
|
|
set_config_guard(
|
|
CAmkESDefaultStackSize
|
|
16384
|
|
CACHE
|
|
STRING
|
|
"Stack size to allocate per-component, in bytes. Note that this value
|
|
should be page-aligned. If not, it will be rounded up."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESProvideTCBCaps
|
|
ON
|
|
CACHE
|
|
BOOL
|
|
"Hand out TCB caps to components. These caps are used by the component
|
|
to exit cleanly by suspending. Disabling this option leaves components
|
|
with an empty slot in place of their TCB cap. This means they will cap
|
|
fault when attempting to exit. The advantage is that your resulting
|
|
CapDL specification contains no TCB caps and is thus easier to reason
|
|
about."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESDefaultPriority
|
|
254
|
|
CACHE
|
|
STRING
|
|
"Default priority for component threads if this is not overridden via an
|
|
attribute. Generally you want to set this as high as possible.
|
|
Defaults to one less than the max priority to avoid interleaving with
|
|
the CapDL intialiser."
|
|
)
|
|
if((${CAmkESDefaultPriority} LESS 0) OR (${CAmkESDefaultPriority} GREATER 255))
|
|
message(FATAL_ERROR "CAmkESDefaultPriority must be [0, 255]")
|
|
endif()
|
|
|
|
set_config_guard(
|
|
CAmkESDefaultAffinity
|
|
0
|
|
CACHE
|
|
STRING
|
|
# Default to 0 as this is the index assigned to the BSP (Boot Strap
|
|
# Processor) by seL4
|
|
"Default affinity for component threads if this is not overridden via an
|
|
attribute. Think carefully when organizing your applications for
|
|
multiprocessor operation"
|
|
)
|
|
math(EXPR MaxNumNodesMin1 "${KernelMaxNumNodes} - 1")
|
|
if((${CAmkESDefaultAffinity} < 0) OR (${CAmkESDefaultAffinity} GREATER ${MaxNumNodesMin1}))
|
|
message(FATAL_ERROR "Invalid CAmkESDefaultAffinity")
|
|
endif()
|
|
|
|
set_config_guard(
|
|
CAmkESRPCLockElision
|
|
ON
|
|
CACHE
|
|
BOOL
|
|
"Detect when it is safe to exclude locking operations in the seL4RPC
|
|
connector and automatically do so. This is an optimisation that can
|
|
improve the performance of this connector."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESLargeFramePromotion
|
|
ON
|
|
CACHE
|
|
BOOL
|
|
"Some hardware platforms support multiple page sizes. In components with
|
|
large virtual address spaces, it is possible to reduce memory usage
|
|
(and consequent load time) by backing the component's address space with
|
|
pages of these larger sizes. When this setting is enabled, small
|
|
consecutive page mappings will be promoted to fewer consecutive large
|
|
mappings. Note that larger frame sizes are directly mapped into page
|
|
directories and can also save the overhead of an accompanying page
|
|
table."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESDMALargeFramePromotion
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"For components with a configured DMA pool, the frames backing this
|
|
are not automatically promoted to large frames even if the pool is
|
|
sufficiently large. Select this option to enable such promotion
|
|
automatically. This is off by default because it requires support
|
|
for large alignments in your toolchain's assembler, which is often
|
|
absent in ARM toolchains."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESFaultHandlers
|
|
ON
|
|
CACHE
|
|
BOOL
|
|
"When a component references invalid virtual memory or an invalid
|
|
capability, the access generates a fault. With this option selected
|
|
a handler is provided that decodes this fault for debugging
|
|
purposes. You will want to disable this in a production system or in
|
|
a system where you want to handle your own faults."
|
|
)
|
|
|
|
set(local_flags "${${list}}")
|
|
|
|
list(
|
|
APPEND
|
|
local_flags
|
|
--architecture
|
|
${KernelSel4Arch}
|
|
--default-priority
|
|
${CAmkESDefaultPriority}
|
|
--default-affinity
|
|
${CAmkESDefaultAffinity}
|
|
--default-stack-size
|
|
${CAmkESDefaultStackSize}
|
|
)
|
|
append_flags(
|
|
local_flags
|
|
"KernelIsMCS;--realtime"
|
|
"CAmkESRPCLockElision;--frpc-lock-elision;--fno-rpc-lock-elision"
|
|
"CAmkESProvideTCBCaps;--fprovide-tcb-caps;--fno-provide-tcb-caps"
|
|
"CAmkESLargeFramePromotion;--largeframe"
|
|
"CAmkESDMALargeFramePromotion;--largeframe-dma"
|
|
"CAmkESFaultHandlers;--debug-fault-handlers"
|
|
)
|
|
|
|
set(${list} "${local_flags}" PARENT_SCOPE)
|
|
|
|
endfunction(set_camkes_render_flags_from_config)
|
|
|
|
set_config_guard(
|
|
CAmkESDTS
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"Support using a device tree (.dts) file, which camkes can query
|
|
for device properties. A file path can be provided by as an argument
|
|
to DeclareCAmkESRootserver as DTS_FILE_PATH, otherwise the a dts file
|
|
matching the platform will be found in seL4/tools."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESCapDLVerification
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"Generate Isabelle definitions and proofs for CapDL refinement. This
|
|
verifies that the system's capability distribution conforms to the expected
|
|
integrity policy of the component assembly."
|
|
)
|
|
|
|
set_config_guard(
|
|
CAmkESCapDLStaticAlloc
|
|
OFF
|
|
CACHE
|
|
BOOL
|
|
"Statically allocate all capDL objects. This requires the target
|
|
platform to have a DTS file, and also requires a certain amount of
|
|
cooperation from kernel boot (currently available on ARM)."
|
|
)
|
|
|
|
if((NOT CAmkESCapDLStaticAlloc) AND CAmkESCapDLVerification)
|
|
message(FATAL_ERROR "CAmkESCapDLVerification requires CAmkESCapDLStaticAlloc to be enabled")
|
|
endif()
|
|
|
|
# Check static allocation options. These should have been propagated correctly
|
|
# by settings.cmake
|
|
if(CAmkESCapDLStaticAlloc)
|
|
if(NOT CapDLLoaderStaticAlloc)
|
|
message(FATAL_ERROR "CAmkESCapDLStaticAlloc requires CapDLLoaderStaticAlloc to be enabled")
|
|
endif()
|
|
if(NOT ElfloaderRootserversLast)
|
|
message(
|
|
FATAL_ERROR "CAmkESCapDLStaticAlloc requires ElfloaderRootserversLast to be enabled"
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
# This also provides PYTHON_CAPDL_PATH
|
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/projects/capdl)
|
|
find_package(capdl REQUIRED)
|
|
CapDLToolInstall(install_capdl_tool CAPDL_TOOL_BINARY)
|
|
|
|
RequireFile(TLS_LINKER_LDS tls.lds PATHS "${CMAKE_CURRENT_LIST_DIR}/libsel4camkes/src")
|
|
|
|
# Use the camkes script to determine the location of other things
|
|
set(CAMKES_TOOL_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
|
set(CAMKES_TOOL_BUILTIN_DIR "${CAMKES_TOOL_DIR}/include/builtin")
|
|
|
|
# Build the environment expected by camkes
|
|
set(CAMKES_TOOL_ENVIRONMENT "PYTHONPATH=${CAMKES_TOOL_DIR}:${PYTHON_CAPDL_PATH}")
|
|
|
|
# Save camkes tool commands
|
|
set(CAMKES_PYTHON_COMMAND ${CMAKE_COMMAND} -E env "${CAMKES_TOOL_ENVIRONMENT}" ${PYTHON3})
|
|
set(CAMKES_TOOL ${CAMKES_PYTHON_COMMAND} -m camkes.runner)
|
|
set(CAMKES_PARSER_TOOL ${CAMKES_PYTHON_COMMAND} -m camkes.parser)
|
|
set(
|
|
CAPDL_LINKER
|
|
${CMAKE_COMMAND}
|
|
-E
|
|
env
|
|
"PYTHONPATH=${PYTHON_CAPDL_PATH}"
|
|
${PYTHON3}
|
|
${PYTHON_CAPDL_PATH}/../cdl_utils/capdl_linker.py
|
|
)
|
|
set(CAPDL_LINKER_DEPENDENCIES "${PYTHON_CAPDL_PATH}/../cdl_utils/capdl_linker.py")
|
|
set(
|
|
CAPDL_UNTYPED_GEN
|
|
${CMAKE_COMMAND}
|
|
-E
|
|
env
|
|
"PYTHONPATH=${PYTHON_CAPDL_PATH}"
|
|
${PYTHON3}
|
|
${PYTHON_CAPDL_PATH}/../cdl_utils/untyped_gen.py
|
|
)
|
|
set(CAPDL_UNTYPED_GEN_DEPENDENCIES "${PYTHON_CAPDL_PATH}/../cdl_utils/untyped_gen.py")
|
|
|
|
# Search for a FMT tool for reformatting generated CAmkES C files
|
|
find_program(CLANG_FORMAT_TOOL clang-format)
|
|
if("${CLANG_FORMAT_TOOL}" STREQUAL "CLANG_FORMAT_TOOL-NOTFOUND")
|
|
set(CAMKES_C_FMT_INVOCATION "")
|
|
else()
|
|
set(CAMKES_C_FMT_INVOCATION "${CLANG_FORMAT_TOOL} --style=LLVM")
|
|
mark_as_advanced(CLANG_FORMAT_TOOL)
|
|
endif()
|
|
|
|
# Find the sponge tool, or emulate it
|
|
find_program(SPONGE_TOOL sponge)
|
|
if("${SPONGE_TOOL}" STREQUAL "SPONGE_TOOL-NOTFOUND")
|
|
set(CAMKES_SPONGE_INVOCATION "sh ${CMAKE_CURRENT_BINARY_DIR}/sponge_emul.sh")
|
|
file(
|
|
WRITE
|
|
"${CMAKE_CURRENT_BINARY_DIR}/sponge_emul.sh"
|
|
"python -c 'import sys; data = sys.stdin.read(); f = open(sys.argv[1], \"w\"); f.write(data); f.close()' $@"
|
|
)
|
|
else()
|
|
set(CAMKES_SPONGE_INVOCATION "${SPONGE_TOOL}")
|
|
mark_as_advanced(SPONGE_TOOL)
|
|
endif()
|
|
|
|
# Find the Isabelle theory pre-process for formatting theory files
|
|
find_program(TPP_TOOL tpp PATHS ${CMAKE_CURRENT_LIST_DIR}/tools)
|
|
if("${TPP_TOOL}" STREQUAL "TPP_TOOL-NOTFOUND")
|
|
message(FATAL_ERROR "Failed to find tpp tool")
|
|
endif()
|
|
mark_as_advanced(TPP_TOOL)
|
|
|
|
file(
|
|
GLOB
|
|
CAMKES_TOOL_FILES
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/ast/*.py
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/internal/*.py
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/parser/*.py
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/runner/*.py
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/templates/Template.py
|
|
${CMAKE_CURRENT_LIST_DIR}/camkes/templates/macros.py
|
|
)
|
|
|
|
file(GLOB PYTHON_CAPDL_FILES ${PYTHON_CAPDL_PATH}/capdl/*.py)
|
|
|
|
# CAmkES defines its own heaps and for this to work muslcsys must not be
|
|
# configured to use a static morecore. We make the morecore dynamic by setting
|
|
# the size to 0
|
|
set(LibSel4MuslcSysMorecoreBytes 0 CACHE STRING "" FORCE)
|
|
|
|
# This is called from the context of a CAmkES application that has decided what
|
|
# the 'root' application is. This function will effectively generate a rule for
|
|
# building the final rootserver image
|
|
function(DeclareCAmkESRootserver adl)
|
|
cmake_parse_arguments(
|
|
PARSE_ARGV
|
|
1
|
|
CAMKES_ROOT
|
|
"" # Option arguments
|
|
"DTS_FILE_PATH;DTB_FILE_PATH" # Single arguments
|
|
"CPP_FLAGS;CPP_INCLUDES" # Multiple arguments
|
|
)
|
|
|
|
# Stash this request as a global property. The main CAmkES build file will
|
|
# call GenerateCAmkESRootserver later once all the build scripts are
|
|
# processed
|
|
get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED)
|
|
if(declared)
|
|
message(FATAL_ERROR "A CAmkES rootserver was already declared")
|
|
endif()
|
|
foreach(include IN LISTS CAMKES_ROOT_CPP_INCLUDES)
|
|
get_absolute_list_source_or_binary(include "${include}")
|
|
list(APPEND CAMKES_ROOT_CPP_FLAGS "-I${include}")
|
|
endforeach()
|
|
# this define can be used to detect if the CAmkES Tool is processing a file
|
|
# or the C compiler. This allows excluding C specific things from CAmkES in
|
|
# shared header files.
|
|
list(APPEND CAMKES_ROOT_CPP_FLAGS "-DCAMKES_TOOL_PROCESSING")
|
|
get_absolute_list_source_or_binary(adl "${adl}")
|
|
set_property(GLOBAL PROPERTY CAMKES_ROOT_ADL "${adl}")
|
|
set_property(GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS "${CAMKES_ROOT_CPP_FLAGS}" APPEND)
|
|
set_property(GLOBAL PROPERTY CAMKES_ROOT_DECLARED TRUE)
|
|
|
|
if(CAMKES_ROOT_DTB_FILE_PATH)
|
|
get_absolute_list_source_or_binary(CAMKES_ROOT_DTB_FILE_PATH "${CAMKES_ROOT_DTB_FILE_PATH}")
|
|
set_property(GLOBAL PROPERTY CAMKES_ROOT_DTB_FILE_PATH "${CAMKES_ROOT_DTB_FILE_PATH}")
|
|
endif()
|
|
if(CAMKES_ROOT_DTS_FILE_PATH)
|
|
if(CAMKES_ROOT_DTB_FILE_PATH)
|
|
message(FATAL_ERROR "Either give a DTB or a DTS file")
|
|
endif()
|
|
get_absolute_list_source_or_binary(CAMKES_ROOT_DTS_FILE_PATH "${CAMKES_ROOT_DTS_FILE_PATH}")
|
|
set_property(GLOBAL PROPERTY CAMKES_ROOT_DTS_FILE_PATH "${CAMKES_ROOT_DTS_FILE_PATH}")
|
|
endif()
|
|
|
|
endfunction(DeclareCAmkESRootserver)
|
|
|
|
# Called to actually generate the definitions for the CAmkES rootserver. Due to
|
|
# its use of properties for some configuration it needs to be run after all
|
|
# other build scripts, typically by the main CAmkES build file
|
|
function(GenerateCAmkESRootserver)
|
|
# Retrieve properties from the declare call above
|
|
get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED)
|
|
if(NOT declared)
|
|
message(FATAL_ERROR "No CAmkES rootserver was declared")
|
|
endif()
|
|
get_property(adl GLOBAL PROPERTY CAMKES_ROOT_ADL)
|
|
get_property(CAMKES_ROOT_CPP_FLAGS GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS)
|
|
get_property(dts_file GLOBAL PROPERTY CAMKES_ROOT_DTS_FILE_PATH)
|
|
get_property(dtb_file GLOBAL PROPERTY CAMKES_ROOT_DTB_FILE_PATH)
|
|
set(CAMKES_TOOL_DEPENDENCIES "")
|
|
get_filename_component(CAMKES_CDL_TARGET "${adl}" NAME_WE)
|
|
set(CAMKES_CDL_TARGET "${CMAKE_CURRENT_BINARY_DIR}/${CAMKES_CDL_TARGET}.cdl")
|
|
# Get an absolute reference to the ADL source
|
|
get_absolute_list_source_or_binary(CAMKES_ADL_SOURCE "${adl}")
|
|
# Declare a common CAMKES_FLAGS that we will need to give to every
|
|
# invocation of camkes
|
|
set(CAMKES_PARSER_FLAGS "--import-path=${CAMKES_TOOL_BUILTIN_DIR}")
|
|
|
|
if(${CAmkESDTS})
|
|
if(NOT dtb_file)
|
|
if(NOT dts_file)
|
|
# Use the kernel's generated DTB file. There might be none on
|
|
# architectures that don't use device trees.
|
|
set(dtb_file "${KernelDTBPath}")
|
|
else()
|
|
if(NOT EXISTS "${dts_file}")
|
|
message(FATAL_ERROR "Could not find dts file ${dts_file}")
|
|
endif()
|
|
set(dtb_file "${dts_file}.dtb")
|
|
GenDTB("${dts_file}" dtb_file)
|
|
endif()
|
|
endif()
|
|
if(dtb_file)
|
|
if(NOT EXISTS "${dtb_file}")
|
|
message(FATAL_ERROR "missing dtb file ${dtb_file}")
|
|
endif()
|
|
list(APPEND CAMKES_PARSER_FLAGS "--dtb=${dtb_file}")
|
|
endif()
|
|
endif()
|
|
|
|
# Grab the list of GPIO pins for the parser
|
|
if(NOT ${KernelPlatform} STREQUAL "pc99")
|
|
if(NOT ${KernelARMPlatform} STREQUAL "")
|
|
get_device_list(gpio_list gpio ${KernelARMPlatform})
|
|
else()
|
|
get_device_list(gpio_list gpio ${KernelPlatform})
|
|
endif()
|
|
if(EXISTS ${gpio_list})
|
|
list(APPEND CAMKES_PARSER_FLAGS "--gpio-list=${gpio_list}")
|
|
endif()
|
|
endif()
|
|
|
|
set_camkes_flags_from_config(CAMKES_FLAGS)
|
|
set_camkes_parser_flags_from_config(CAMKES_PARSER_FLAGS)
|
|
set_camkes_render_flags_from_config(CAMKES_RENDER_FLAGS)
|
|
|
|
foreach(flag IN LISTS CAMKES_ROOT_CPP_FLAGS)
|
|
if(NOT "--cpp" IN_LIST CAMKES_PARSER_FLAGS)
|
|
message(
|
|
FATAL_ERROR "Given CPP_FLAGS ${CAMKES_ROOT_CPP_FLAGS} but CAmkESCPP is disabled"
|
|
)
|
|
endif()
|
|
list(APPEND CAMKES_PARSER_FLAGS "--cpp-flag=${flag}")
|
|
endforeach()
|
|
# Retrieve any extra import paths
|
|
get_property(imports GLOBAL PROPERTY CAmkESExtraImportPaths)
|
|
foreach(import IN LISTS imports)
|
|
list(APPEND CAMKES_PARSER_FLAGS "--import-path=${import}")
|
|
endforeach()
|
|
# Retrieve any template paths
|
|
get_property(templates GLOBAL PROPERTY CAmkESTemplatePaths)
|
|
foreach(template IN LISTS templates)
|
|
list(APPEND CAMKES_RENDER_FLAGS --templates "${template}")
|
|
endforeach()
|
|
|
|
set(CAMKES_AST_PICKLE "${CMAKE_CURRENT_BINARY_DIR}/ast.pickle")
|
|
set(CAMKES_AST_DEP_FILE "${CAMKES_AST_PICKLE}.d")
|
|
set(extra_dependencies ${CAMKES_TOOL_FILES} ${PYTHON_CAPDL_FILES})
|
|
execute_process_with_stale_check(
|
|
"${CAMKES_AST_PICKLE}.cmd"
|
|
"${CAMKES_AST_DEP_FILE}"
|
|
"${CAMKES_AST_PICKLE}"
|
|
"${extra_dependencies}"
|
|
COMMAND
|
|
${CAMKES_PARSER_TOOL}
|
|
${CAMKES_FLAGS}
|
|
${CAMKES_PARSER_FLAGS}
|
|
--makefile-dependencies
|
|
"${CAMKES_AST_DEP_FILE}"
|
|
--file
|
|
"${CAMKES_ADL_SOURCE}"
|
|
--save-ast
|
|
"${CAMKES_AST_PICKLE}"
|
|
WORKING_DIRECTORY
|
|
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
INPUT_FILE
|
|
/dev/stdin
|
|
OUTPUT_FILE
|
|
/dev/stdout
|
|
ERROR_FILE
|
|
/dev/stderr
|
|
RESULT_VARIABLE
|
|
camkes_gen_error
|
|
)
|
|
if(camkes_gen_error)
|
|
file(REMOVE ${CAMKES_AST_PICKLE})
|
|
message(FATAL_ERROR "Failed to generate ${CAMKES_AST_PICKLE}")
|
|
endif()
|
|
|
|
set(CAMKES_CMAKE_FILE "${CMAKE_CURRENT_BINARY_DIR}/camkes-gen.cmake")
|
|
set(CAMKES_CMAKE_DEP_FILE "${CAMKES_CMAKE_FILE}.d")
|
|
set(extra_dependencies ${CAMKES_AST_PICKLE} ${CAMKES_TOOL_FILES} ${PYTHON_CAPDL_FILES})
|
|
execute_process_with_stale_check(
|
|
"${CAMKES_CMAKE_FILE}.cmd"
|
|
"${CAMKES_CMAKE_DEP_FILE}"
|
|
"${CAMKES_CMAKE_FILE}"
|
|
"${extra_dependencies}"
|
|
COMMAND
|
|
${CAMKES_TOOL}
|
|
${CAMKES_FLAGS}
|
|
${CAMKES_RENDER_FLAGS}
|
|
--makefile-dependencies
|
|
"${CAMKES_CMAKE_DEP_FILE}"
|
|
--load-ast
|
|
"${CAMKES_AST_PICKLE}"
|
|
--item
|
|
assembly/
|
|
--template
|
|
camkes-gen.cmake
|
|
--outfile
|
|
"${CAMKES_CMAKE_FILE}"
|
|
WORKING_DIRECTORY
|
|
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
INPUT_FILE
|
|
/dev/stdin
|
|
OUTPUT_FILE
|
|
/dev/stdout
|
|
ERROR_FILE
|
|
/dev/stderr
|
|
RESULT_VARIABLE
|
|
camkes_gen_error
|
|
)
|
|
if(camkes_gen_error)
|
|
file(REMOVE ${CAMKES_CMAKE_FILE})
|
|
message(FATAL_ERROR "Failed to generate ${CAMKES_CMAKE_FILE}")
|
|
endif()
|
|
|
|
# We set a property to indicate that we have done execute_process (which
|
|
# happens during the generation phase. This just allows us to do some
|
|
# debugging and detect cases where options are changed *after* this point
|
|
# that would have affected the execute_process
|
|
set_property(GLOBAL PROPERTY CAMKES_GEN_DONE TRUE)
|
|
include("${CAMKES_CMAKE_FILE}")
|
|
|
|
endfunction(GenerateCAmkESRootserver)
|
|
|
|
# Internal helper function for setting camkes component properties
|
|
# The following common parameters are supported
|
|
#
|
|
# SOURCES <src1> <src2> ...
|
|
# INCLUDES <inc1> <inc2> ...
|
|
# C_FLAGS <flag1> <flag2> ...
|
|
# CXX_FLAGS <flag1> <flag2> ...
|
|
# LD_FLAGS <flag1> <flag2> ...
|
|
# LIBS <lib1> <lib1> ...
|
|
#
|
|
# For CakeML components, these parameters are supported
|
|
#
|
|
# CAKEML_HEAP_SIZE <val>
|
|
# sets target propery COMPONENT_CAKEML_HEAP_SIZE
|
|
#
|
|
# CAKEML_STACK_SIZE <val>
|
|
# sets target propery COMPONENT_CAKEML_STACK_SIZE
|
|
#
|
|
# CAKEML_SOURCES <src1> <src2> ...
|
|
# CAKEML_DEPENDS <dep1> <dep2> ...
|
|
# CAKEML_INCLUDES<inc1> <inc2> ...
|
|
#
|
|
# LINKER_LANGUAGE <lng>
|
|
# sets target propery COMPONENT_LINKER_LANGUAGE
|
|
#
|
|
# TEMPLATE_SOURCES
|
|
# TEMPLATE_HEADERS
|
|
#
|
|
function(AppendCAmkESComponentTarget target_name)
|
|
cmake_parse_arguments(
|
|
PARSE_ARGV
|
|
1
|
|
CAMKES_COMPONENT
|
|
"" # Option arguments
|
|
"CAKEML_HEAP_SIZE;CAKEML_STACK_SIZE;LINKER_LANGUAGE" # Single arguments
|
|
"SOURCES;CAKEML_SOURCES;CAKEML_DEPENDS;CAKEML_INCLUDES;INCLUDES;C_FLAGS;CXX_FLAGS;LD_FLAGS;LIBS;TEMPLATE_SOURCES;TEMPLATE_HEADERS" # Multiple aguments
|
|
)
|
|
# Declare a target that we will set properties on
|
|
if(NOT (TARGET "${target_name}"))
|
|
add_custom_target("${target_name}")
|
|
endif()
|
|
# Get absolute paths for the includes and sources
|
|
set(includes "")
|
|
set(sources "")
|
|
set(cakeml_sources "")
|
|
set(cakeml_includes "")
|
|
foreach(inc IN LISTS CAMKES_COMPONENT_INCLUDES)
|
|
get_absolute_list_source_or_binary(inc "${inc}")
|
|
list(APPEND includes "${inc}")
|
|
endforeach()
|
|
foreach(file IN LISTS CAMKES_COMPONENT_SOURCES)
|
|
get_absolute_list_source_or_binary(file "${file}")
|
|
list(APPEND sources "${file}")
|
|
endforeach()
|
|
foreach(file IN LISTS CAMKES_COMPONENT_CAKEML_SOURCES)
|
|
get_absolute_list_source_or_binary(file "${file}")
|
|
list(APPEND cakeml_sources "${file}")
|
|
endforeach()
|
|
foreach(file IN LISTS CAMKES_COMPONENT_CAKEML_INCLUDES)
|
|
get_absolute_list_source_or_binary(file "${file}")
|
|
list(APPEND cakeml_includes "${file}")
|
|
endforeach()
|
|
set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_INCLUDES "${includes}")
|
|
set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_SOURCES "${sources}")
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_TEMPLATE_SOURCES "${CAMKES_COMPONENT_TEMPLATE_SOURCES}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_TEMPLATE_HEADERS "${CAMKES_COMPONENT_TEMPLATE_HEADERS}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_CAKEML_SOURCES "${cakeml_sources}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_CAKEML_INCLUDES "${cakeml_includes}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_CAKEML_DEPENDS "${CAMKES_COMPONENT_CAKEML_DEPENDS}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_C_FLAGS "${CAMKES_COMPONENT_C_FLAGS}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_CXX_FLAGS "${CAMKES_COMPONENT_CXX_FLAGS}"
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_LD_FLAGS "${CAMKES_COMPONENT_LD_FLAGS}"
|
|
)
|
|
set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LIBS "${CAMKES_COMPONENT_LIBS}")
|
|
# Overwrite any previous CakeML heap or stack size
|
|
if(CAMKES_COMPONENT_CAKEML_HEAP_SIZE)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
PROPERTY COMPONENT_CAKEML_HEAP_SIZE "${CAMKES_COMPONENT_CAKEML_HEAP_SIZE}"
|
|
)
|
|
endif()
|
|
if(CAMKES_COMPONENT_CAKEML_STACK_SIZE)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
PROPERTY COMPONENT_CAKEML_STACK_SIZE "${CAMKES_COMPONENT_CAKEML_STACK_SIZE}"
|
|
)
|
|
endif()
|
|
if(CAMKES_COMPONENT_LINKER_LANGUAGE)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY COMPONENT_LINKER_LANGUAGE "${CAMKES_COMPONENT_LINKER_LANGUAGE}"
|
|
)
|
|
endif()
|
|
endfunction(AppendCAmkESComponentTarget)
|
|
|
|
# Internal helper function for setting camkes component properties
|
|
function(DeclareCAmkESConnector name)
|
|
set(target_name CAmkESConnector_${name})
|
|
cmake_parse_arguments(
|
|
PARSE_ARGV
|
|
1
|
|
CAMKES_CONNECTOR
|
|
"" # Option arguments
|
|
"FROM;TO;CAKEML_TO;FROM_HEADER;TO_HEADER" # Single arguments
|
|
"FROM_LIBS;TO_LIBS" # Multiple aguments
|
|
)
|
|
# Declare a target that we will set properties on
|
|
if(NOT (TARGET "${target_name}"))
|
|
add_custom_target("${target_name}")
|
|
endif()
|
|
set_property(TARGET "${target_name}" APPEND PROPERTY CONNECTOR_FROM ${CAMKES_CONNECTOR_FROM})
|
|
set_property(TARGET "${target_name}" APPEND PROPERTY CONNECTOR_TO ${CAMKES_CONNECTOR_TO})
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY CONNECTOR_FROM_HEADER ${CAMKES_CONNECTOR_FROM_HEADER}
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY CONNECTOR_FROM_LIBS ${CAMKES_CONNECTOR_FROM_LIBS}
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY CONNECTOR_TO_HEADER ${CAMKES_CONNECTOR_TO_HEADER}
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY CONNECTOR_TO_LIBS ${CAMKES_CONNECTOR_TO_LIBS}
|
|
)
|
|
set_property(
|
|
TARGET "${target_name}"
|
|
APPEND
|
|
PROPERTY CONNECTOR_CAKEML_TO ${CAMKES_CONNECTOR_CAKEML_TO}
|
|
)
|
|
endfunction(DeclareCAmkESConnector)
|
|
|
|
# This is called by CAmkES components to declare information needed for the
|
|
# camkes-gen.cmake to actually build them. Can be called multiple times to
|
|
# append additional information.
|
|
function(DeclareCAmkESComponent name)
|
|
AppendCAmkESComponentTarget(CAmkESComponent_${name} ${ARGN})
|
|
endfunction(DeclareCAmkESComponent)
|
|
|
|
# Declare built-in components that are constructed from templates and have no
|
|
# source files
|
|
DeclareCAmkESComponent(debug_server)
|
|
DeclareCAmkESComponent(debug_serial)
|
|
|
|
# Extend a particular instantiation of a CAmkES component with additional
|
|
# information. This takes similar arguments to DeclareCAmkESComponent and all
|
|
# of the declared includes, flags etc also apply to the sources from
|
|
# DeclareCAmkESComponent. The includes provided here will be passed prior to
|
|
# the original includes allowing for overriding. This can be called multiple
|
|
# times for the same instance to repeatedly extend it. Similar flags will be
|
|
# placed after.
|
|
function(ExtendCAmkESComponentInstance component_name instance_name)
|
|
AppendCAmkESComponentTarget(CAmkESComponent_${component_name}_instance_${instance_name} ${ARGN})
|
|
endfunction(ExtendCAmkESComponentInstance)
|
|
|
|
# Helper function for adding additional import paths. Largely it exists to
|
|
# allow list files to give relative paths and have them automatically expanded
|
|
# to absolute paths. We add the import paths to a property, instead of a target,
|
|
# since we need to use it in an `execute_process` above, which cannot take
|
|
# generator expressions
|
|
function(CAmkESAddImportPath)
|
|
# Ensure we haven't generated the camkes-gen.cmake yet
|
|
get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE)
|
|
if(is_done)
|
|
message(FATAL_ERROR "Adding import path after camkes-gen.cmake has been generated")
|
|
endif()
|
|
foreach(arg IN LISTS ARGV)
|
|
get_absolute_list_source_or_binary(arg "${arg}")
|
|
set_property(GLOBAL APPEND PROPERTY CAmkESExtraImportPaths "${arg}")
|
|
endforeach()
|
|
endfunction(CAmkESAddImportPath)
|
|
|
|
# Add an import path but only if it exists
|
|
function(CAmkESMaybeAddImportPath)
|
|
foreach(arg IN LISTS ARGV)
|
|
if(EXISTS ${arg})
|
|
CAmkESAddImportPath(${arg})
|
|
endif()
|
|
endforeach()
|
|
endfunction()
|
|
|
|
function(CAmkESAddTemplatesPath)
|
|
# Ensure we haven't generated the camkes-gen.cmake yet
|
|
get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE)
|
|
if(is_done)
|
|
message(FATAL_ERROR "Adding templates path after camkes-gen.cmake has been generated")
|
|
endif()
|
|
foreach(arg IN LISTS ARGV)
|
|
get_absolute_list_source_or_binary(arg "${arg}")
|
|
set_property(GLOBAL APPEND PROPERTY CAmkESTemplatePaths "${arg}")
|
|
endforeach()
|
|
endfunction(CAmkESAddTemplatesPath)
|
|
|
|
include(${CMAKE_CURRENT_LIST_DIR}/components/components.cmake)
|
|
|
|
# Function to add an include path to the c preprocessor when running over
|
|
# camkes ADL files (example.camkes).
|
|
function(CAmkESAddCPPInclude)
|
|
foreach(arg IN LISTS ARGV)
|
|
get_absolute_list_source_or_binary(arg "${arg}")
|
|
set_property(GLOBAL APPEND PROPERTY CAMKES_ROOT_CPP_FLAGS "-I${arg}")
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# Declare all built-in templates
|
|
include(${CMAKE_CURRENT_LIST_DIR}/camkes/templates/templates.cmake)
|