Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 1 | # |
| 2 | # Copyright 2018, Data61 |
| 3 | # Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| 4 | # ABN 41 687 119 230. |
| 5 | # |
| 6 | # This software may be distributed and modified according to the terms of |
| 7 | # the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| 8 | # See "LICENSE_BSD2.txt" for details. |
| 9 | # |
| 10 | # @TAG(DATA61_BSD) |
| 11 | # |
| 12 | |
| 13 | cmake_minimum_required(VERSION 3.7.2) |
| 14 | |
| 15 | include(ExternalProject) |
| 16 | |
| 17 | include(${KERNEL_HELPERS_PATH}) |
| 18 | |
| 19 | set(configure_string "") |
| 20 | |
| 21 | config_string(CAmkESDefaultStackSize CAMKES_DEFAULT_STACK_SIZE |
| 22 | "Stack size to allocate per-component, in bytes. Note that this value |
| 23 | should be page-aligned. If not, it will be rounded up." |
| 24 | DEFAULT 16384 |
| 25 | UNQUOTE |
| 26 | ) |
| 27 | |
| 28 | config_string(CAmkESDefaultHeapSize CAMKES_DEFAULT_HEAP_SIZE |
| 29 | "Heap size to allocate per-component, in bytes." |
| 30 | DEFAULT 1048576 |
| 31 | UNQUOTE |
| 32 | ) |
| 33 | |
| 34 | config_choice(CAmkESErrorHandlingMode CAMKES_ERROR_HANDLING_MODE |
| 35 | "Select the mode of error handling used in the glue code. It should only |
| 36 | be necessary to adjust this setting if you are doing verification. |
| 37 | Otherwise, the default error handling mechanism allows for |
| 38 | configuration at runtime. |
| 39 | |
| 40 | Standard -> Standard error handling mechanism, that is configurable by the user at |
| 41 | runtime. See the documentation for details of the API for this. |
| 42 | |
| 43 | Guards -> Use verification-visible guards at the site of each potential error. |
| 44 | Note that this assumes that none of the error conditions are possible. |
| 45 | If you are trying to verify code, you will be forced to prove that none |
| 46 | of the error conditions can ever actually occur. |
| 47 | |
| 48 | Abort -> Call 'abort' inline when an error occurs. For debugging purposes, this |
| 49 | is probably not the behaviour you want as it will give you no |
| 50 | information about the error. The standard error handling mechanism has |
| 51 | a nicer default for debugging. This mode is primarily useful when you |
| 52 | want to verify code whose error handlers are unreachable for |
| 53 | non-trivial reasons. |
| 54 | |
| 55 | Discard -> Perform the 'discard' action on any error that occurs. The advantage of |
| 56 | this over simply configuring this behaviour via the standard mechanism |
| 57 | is that you will not need to reason about any of the complicated error |
| 58 | handling structures or control flow. This has no implementation |
| 59 | advantages over the standard mechanism." |
| 60 | "Standard;CAmkESErrorHandlingConfigurable;CAMKES_ERROR_HANDLER_CONFIGURABLE" |
| 61 | "Guards;CAmkESErrorHandlingGuard;CAMKES_ERROR_HANDLER_GUARD" |
| 62 | "Abort;CAmkESErrorHandlingAbort;CAMKES_ERROR_HANDLER_ABORT" |
| 63 | "Discard;CAmkESErrorHandlingDiscard;CAMKES_ERROR_HANDLER_DISCARD" |
| 64 | ) |
| 65 | |
| 66 | config_option(CAmkESConnectorTiming CAMKES_CONNECTOR_TIMING |
| 67 | "Enable timing points within connector templates that take cycle counter |
| 68 | values as they are passed. This timing data can then be retrieved after |
| 69 | execution." |
| 70 | DEFAULT OFF |
| 71 | ) |
| 72 | |
| 73 | config_option(CAmkESProvideTCBCaps CAMKES_PROVIDE_TCB_CAPS |
| 74 | "Hand out TCB caps to components. These caps are used by the component |
| 75 | to exit cleanly by suspending. Disabling this option leaves components |
| 76 | with an empty slot in place of their TCB cap. This means they will cap |
| 77 | fault when attempting to exit. The advantage is that your resulting |
| 78 | CapDL specification contains no TCB caps and is thus easier to reason |
| 79 | about." |
| 80 | DEFAULT ON |
| 81 | ) |
| 82 | |
| 83 | config_choice(CAmkESTLSModel CAMKES_TLS_MODEL |
| 84 | "The CAmkES glue code uses thread-local variables for marshalling and |
| 85 | unmarshalling of RPC parameters. This setting controls how this thread- |
| 86 | local storage is implemented. |
| 87 | |
| 88 | standard -> Allocate thread-local variables on the stack or the heap as appropriate. |
| 89 | This is the default and will hold the fewest surprises for C |
| 90 | programmers. |
| 91 | |
| 92 | per-thread -> Allocate per-thread global variables for use as thread-local storage. |
| 93 | The main purpose of this implementation is to avoid taking the address |
| 94 | of local variables, an idiom that cannot be handled by the verification |
| 95 | C parser." |
| 96 | "standard;CAmkESTLSStandard;CAMKES_TLS_STANDARD" |
| 97 | "per-thread;CAmkESTLSPerThreadGlobal;CAMKES_TLS_PTG" |
| 98 | ) |
| 99 | |
Adrian Danis | 4a99eb3 | 2018-03-07 15:58:12 +1100 | [diff] [blame] | 100 | config_string(CAmkESDefaultPriority CAMKES_DEFAULT_PRIORITY |
| 101 | "Default priority for component threads if this is not overridden via an |
| 102 | attribute. Generally you want to set this as high as possible due to |
| 103 | the suboptimal seL4 scheduler." |
| 104 | # Default to one less than max prio to avoid interleaving with the CapDL intialiser |
| 105 | DEFAULT 254 |
| 106 | UNQUOTE |
| 107 | ) |
| 108 | if ((${CAmkESDefaultPriority} LESS 0) OR (${CAmkESDefaultPriority} GREATER 255)) |
| 109 | message(FATAL_ERROR "CAmkESDefaultPriority must be [0, 255]") |
| 110 | endif() |
| 111 | |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 112 | add_config_library(camkes_config "${configure_string}") |
| 113 | |
| 114 | # These options are not declared with the config_* system because they only need to exist |
| 115 | # in the build system, and not appear in a configuration library |
| 116 | set(CAmkESCPP OFF CACHE BOOL |
| 117 | "Run CPP on the input specification(s) before parsing them into an AST. |
| 118 | This can allow you to write parameterised specs in the case of more |
| 119 | complex system" |
| 120 | ) |
| 121 | |
| 122 | set(CAmkESImportPath "" CACHE STRING |
| 123 | "CAmkES can include components and interfaces stored outside the current application |
| 124 | directory. This option is a space delimited list of absolute paths to directories |
| 125 | to be searched for components or interfaces included with angle brackets." |
| 126 | ) |
| 127 | |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 128 | set(CAmkESDefaultAffinity 0 CACHE STRING |
| 129 | # Default to 0 as this is the index assigned to the BSP (Boot Strap Processor) by seL4 |
| 130 | "Default affinity for component threads if this is not overridden via an |
| 131 | attribute. Think carefully when organizing your applications for |
| 132 | multiprocessor operation" |
| 133 | ) |
| 134 | math(EXPR MaxNumNodesMin1 "${KernelMaxNumNodes} - 1") |
| 135 | if((${CAmkESDefaultAffinity} < 0) OR (${CAmkESDefaultAffinity} GREATER ${MaxNumNodesMin1})) |
| 136 | message(FATAL_ERROR "Invalid CAmkESDefaultAffinity") |
| 137 | endif() |
| 138 | |
| 139 | set(CAmkESAllowForwardReferences OFF CACHE BOOL |
| 140 | "By default, you can only refer to objects in your specification which |
| 141 | have been defined before the point at which you reference them. |
| 142 | Selecting this option allows you to also reference objects that are |
| 143 | defined below the point at which the reference occurs. This option is |
| 144 | off by default because it leads to a slight performance degradation in |
| 145 | parsing specification" |
| 146 | ) |
| 147 | |
| 148 | set(CAmkESObjdumpMethod "auto" CACHE STRING |
| 149 | "Instead of using the internal ELF parsing functionality, it is |
| 150 | possible to call out to your toolchain's objdump to perform |
| 151 | required operations. This is more fragile than using internal |
| 152 | functionality, but can provide a performance boost in compilation |
| 153 | times. If you set this to auto (default), CAmkES will use your |
| 154 | toolchain's objdump if it is in your PATH. |
| 155 | |
| 156 | off -> Disable the use of objdump for ELF symbol lookups. Lookups will be |
| 157 | done via standard built-in CAmkES mechanisms. This may be slightly |
| 158 | slower. |
| 159 | |
| 160 | auto -> Automatically detect whether objdump is available for use for ELF |
| 161 | symbol lookups, and use it if so. This will result in the fastest |
| 162 | available method for ELF symbol lookup being used automatically and |
| 163 | is the recommended default. |
| 164 | |
| 165 | on -> Use objdump for ELF symbol lookups. Lookups will be done by calling |
| 166 | out to your toolchain's objdump binary. This is fastest at the |
| 167 | expense of some robustness." |
| 168 | ) |
| 169 | set_property(CACHE CAmkESObjdumpMethod PROPERTY STRINGS "auto;on;off") |
| 170 | |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 171 | set(CAmkESRPCLockElision ON CACHE BOOL |
| 172 | "Detect when it is safe to exclude locking operations in the seL4RPC connector and |
| 173 | automatically do so. This is an optimisation that can improve the performance of |
| 174 | this connector." |
| 175 | ) |
| 176 | |
| 177 | set(CAmkESSpecialiseSyscallStubs ON CACHE BOOL |
| 178 | "Detect when glue code overhead could be reduced with a custom syscall |
| 179 | stub and generate and use this instead of the libsel4 stubs. This does |
| 180 | not affect whether a given IPC will hit the fastpath, but it does |
| 181 | reduce the userlevel overhead of these system calls. In ideal |
| 182 | conditions this will give you RPC as fast as native seL4 IPC. This only |
| 183 | has an effect on ARM." |
| 184 | ) |
| 185 | |
| 186 | set(CAmkESLargeFramePromotion ON CACHE BOOL |
| 187 | "Some hardware platforms support multiple page sizes. In components with |
| 188 | large virtual address spaces, it is possible to reduce memory usage |
| 189 | (and consequent load time) by backing the component's address space with |
| 190 | pages of these larger sizes. When this setting is enabled, small |
| 191 | consecutive page mappings will be promoted to fewer consecutive large |
| 192 | mappings. Note that larger frame sizes are directly mapped into page |
| 193 | directories and can also save the overhead of an accompanying page |
| 194 | table." |
| 195 | ) |
| 196 | |
| 197 | set(CAmkESDMALargeFramePromotion OFF CACHE BOOL |
| 198 | "For components with a configured DMA pool, the frames backing this |
| 199 | are not automatically promoted to large frames even if the pool is |
| 200 | sufficiently large. Select this option to enable such promotion |
| 201 | automatically. This is off by default because it requires support |
| 202 | for large alignments in your toolchain's assembler, which is often |
| 203 | absent in ARM toolchains." |
| 204 | ) |
| 205 | |
| 206 | set(CAmkESPythonOptimisation "none" CACHE STRING |
| 207 | "Select the optimisation flag to pass to the Python interpreter. The |
| 208 | default is for no optimisation because profiling has suggested this |
| 209 | has a detrimental effect for CAmkES. However, you may find |
| 210 | different results depending on your wor |
| 211 | |
| 212 | none -> Do not pass any optimisation flags to the Python interpreter. |
| 213 | |
| 214 | -O -> Enable basic optimisations. This disables assertions and is not |
| 215 | recommended if you are working on the internals of CAmkES itself. |
| 216 | |
| 217 | -OO -> Enable basic optimisations and also strip docstrings." |
| 218 | ) |
| 219 | set_property(CACHE CAmkESPythonOptimisation PROPERTY STRINGS "none;-O;-OO") |
| 220 | |
| 221 | set(CAmkESPythonInterpreter "cpython" CACHE STRING |
| 222 | "Select the Python interpreter used for executing CAmkES. The default |
| 223 | CPython interpreter should be acceptable for any normal use, but you |
| 224 | may find PyPy provides better build system performance under some |
| 225 | circumstances. To use PyPy, obviously you need it installed. The other |
| 226 | interpreters are for profiling or dynamic analysis. |
| 227 | |
| 228 | cpython -> Use CPython, the default Python interpreter. This is what will be |
| 229 | most familiar to Python users. |
| 230 | |
| 231 | cpython2 -> Force the use of Python 2, instead of the default Python |
| 232 | executable. |
| 233 | |
| 234 | cpython3 -> Force the use of Python 3, instead of the default Python |
| 235 | executable. Note that Python 3 support is currently experimental |
| 236 | and should not be expected to work without tweaks. |
| 237 | |
| 238 | pypy -> Use PyPy, an optimised Python interpreter. PyPy is intended to be |
| 239 | faster than CPython with maximum compatibility, but it is not |
| 240 | recommended for use with CAmkES because profiling has indicated it |
| 241 | is actually *slower* in general for CAmkES' workload. |
| 242 | |
| 243 | figleaf -> Use Figleaf, an interpreter that reports code coverage statistics. |
| 244 | This interpreter is primarily useful for profiling or debugging |
| 245 | CAmkES itself. |
| 246 | |
| 247 | coverage -> Use Python-coverage, an interpreter that reports code coverage |
| 248 | statistics. This interpreter is primarily useful for profiling or |
| 249 | debugging CAmkES itself." |
| 250 | ) |
| 251 | set_property(CACHE CAmkESPythonInterpreter PROPERTY STRINGS "cpython;cpython2;cpython3;pypy;figleaf;coverage") |
| 252 | |
| 253 | set(CAmkESFaultHandlers ON CACHE BOOL |
| 254 | "When a component references invalid virtual memory or an invalid |
| 255 | capability, the access generates a fault. With this option selected |
| 256 | a handler is provided that decodes this fault for debugging |
| 257 | purposes. You will want to disable this in a production system or in |
| 258 | a system where you want to handle your own faults." |
| 259 | ) |
| 260 | |
| 261 | set(CAmkESSupportInit ON CACHE BOOL |
| 262 | "Support the pre_init, post_init and interface init functions as part of |
| 263 | component startup. These functions allow extra functionality, but |
| 264 | introduce some endpoint caps for synchronisation. You probably want |
| 265 | this option enabled unless you are targetting verification." |
| 266 | ) |
| 267 | |
| 268 | # TODO: The following options are not yet supported in cmake build template, as a result |
| 269 | # these are currently commented out to as not to confuse users. They should be uncommented |
| 270 | # as support is added |
| 271 | #set(CAmkESPruneGenerated OFF CACHE BOOL |
| 272 | # "Prune generated C files |
| 273 | # When selected, this option minimises the number of C functions in a |
| 274 | # given generated file. This can be done because the CAmkES generation |
| 275 | # logic knows which functions are required by the user's components and |
| 276 | # which are not. This option implies a separate pre-process step on the |
| 277 | # generated files prior to pruning/compilation, otherwise the generated |
| 278 | # C files are already minimal. Note, you will need libclang-dev installed |
| 279 | # to enable this option." |
| 280 | #) |
| 281 | |
| 282 | #set(CAmkESThys OFF CACHE BOOL |
| 283 | # "Generate correctness proofs |
| 284 | # Generate AutoCorres-based theories of connector correctness during |
| 285 | # compilation." |
| 286 | #) |
| 287 | |
| 288 | #set(CAmkESUnifiedThy OFF CACHE BOOL |
| 289 | # "Generate unified correctness proof |
| 290 | # Generate an AutoCorred-based theory combining the two glue code halves |
| 291 | # of a connector, resulting in a final correctness statement." |
| 292 | # DEPENDS CAmkESPruneGenerated |
| 293 | #) |
| 294 | |
| 295 | #set(CAmkESArchThy OFF CACHE BOOL |
| 296 | # "Generate architectural specification |
| 297 | # Generate an Isabelle theory specifying the architecture of the |
| 298 | # system, using the l4.verified formal model of ADL." |
| 299 | #) |
| 300 | |
| 301 | #set(CAmkESCImpThy OFF CACHE BOOL |
| 302 | # "Generate dynamic behavioural specification |
| 303 | # Generate an Isabelle theory specifying the dynamic behaviour of the |
| 304 | # system. This theory builds on top of the CIMP formalisation." |
| 305 | #) |
| 306 | |
| 307 | #set(CAmkESCapDLThy OFF CACHE BOOL |
| 308 | # "Generate CapDL Isabelle specification |
| 309 | # During a CAmkES build, a textual CapDL specification of the system |
| 310 | # is generated for the purpose of initialisation. Selecting this |
| 311 | # option causes an Isabelle version of this specification to be |
| 312 | # generated as well for the purposes of reasoning about the |
| 313 | # capability distribution of a CAmkES system" |
| 314 | #) |
| 315 | |
| 316 | #set(CAmkESLabelMapping OFF CACHE BOOL |
| 317 | # "Generate policy label mapping |
| 318 | # Enable this option to generate a mapping from labels to kernel objects |
| 319 | # during compilation. A label per-CAmkES entity (component instance or |
| 320 | # connection) is generated and they are intended to form the input domain |
| 321 | # of a function mapping these to final policy labels. The final labels |
| 322 | # are then used to reason about the security properties of a system." |
| 323 | #) |
| 324 | |
| 325 | set(CAmkESVerbose OFF CACHE BOOL |
| 326 | "Enable verbose output from CAmkES. This is disabled by default as it |
| 327 | can result in a lot of output, but is useful for debugging CAmkES problems" |
| 328 | ) |
| 329 | |
Adrian Danis | ca89b10 | 2018-03-14 16:41:18 +1100 | [diff] [blame] | 330 | # Save the path to to python-capdl whilst we know it (unless it was already specified) |
| 331 | if (NOT PYTHON_CAPDL_PATH) |
| 332 | set(PYTHON_CAPDL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/projects/capdl/python-capdl-tool") |
| 333 | endif() |
| 334 | if (NOT CAPDL_TOOL_SOURCE_PATH) |
| 335 | set(CAPDL_TOOL_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/projects/capdl/capDL-tool") |
| 336 | endif() |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 337 | |
| 338 | # Save the location of the camkes tool wrapper script |
| 339 | RequireFile(CAMKES_TOOL camkes.sh PATHS "${CMAKE_CURRENT_LIST_DIR}") |
| 340 | |
| 341 | # Use the camkes script to determine the location of other things |
| 342 | get_filename_component(CAMKES_TOOL_DIR "${CAMKES_TOOL}" DIRECTORY) |
| 343 | set(CAMKES_TOOL_BUILTIN_DIR "${CAMKES_TOOL_DIR}/include/builtin") |
| 344 | |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 345 | # Require the parse-capDL tool |
| 346 | ExternalProject_Add(parse_capdl_tool |
| 347 | SOURCE_DIR "${CAPDL_TOOL_SOURCE_PATH}" |
| 348 | CONFIGURE_COMMAND bash -c "cp -ra ${CAPDL_TOOL_SOURCE_PATH}/* ." |
| 349 | BUILD_ALWAYS ON |
| 350 | BUILD_COMMAND ${CMAKE_COMMAND} -E env "CONFIG_CAPDL_LOADER_MAX_IRQS=${CapDLLoaderMaxIRQs}" make |
| 351 | INSTALL_COMMAND ${CMAKE_COMMAND} -E env "PATH=$ENV{PATH}:${CMAKE_CURRENT_BINARY_DIR}/parse_capdl_tool-prefix/src/parse_capdl_tool-build" make install |
| 352 | ) |
| 353 | ExternalProject_Get_property(parse_capdl_tool BINARY_DIR) |
| 354 | set(CAPDL_TOOL_PATH "${BINARY_DIR}") |
| 355 | |
| 356 | # Search for a FMT tool for reformatting generated CAmkES C files |
| 357 | find_program(CLANG_FORMAT_TOOL clang-format) |
| 358 | if ("${CLANG_FORMAT_TOOL}" STREQUAL "CLANG_FORMAT_TOOL-NOTFOUND") |
| 359 | set(CAMKES_C_FMT_INVOCATION "") |
| 360 | else() |
| 361 | set(CAMKES_C_FMT_INVOCATION "${CLANG_FORMAT_TOOL} --style=LLVM") |
| 362 | endif() |
| 363 | |
| 364 | # Find the sponge tool, or emulate it |
| 365 | find_program(SPONGE_TOOL sponge) |
| 366 | if ("${SPONGE_TOOL}" STREQUAL "SPONGE_TOOL-NOTFOUND") |
| 367 | set(CAMKES_SPONGE_INVOCATION "${CMAKE_COMMAND} -E ${CMAKE_CURRENT_BINARY_DIR}/sponge_emul.sh") |
| 368 | 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()' $@") |
| 369 | else() |
| 370 | set(CAMKES_SPONGE_INVOCATION "${SPONGE_TOOL}") |
| 371 | endif() |
| 372 | |
| 373 | # Find the Isabelle theory pre-process for formatting theory files |
| 374 | find_program(TPP_TOOL tpp PATHS tools/camkes/tools) |
| 375 | if ("${TPP_TOOL}" STREQUAL "TPP_TOOL-NOTFOUND") |
| 376 | message(FATAL_ERROR "Failed to find tpp tool") |
| 377 | endif() |
| 378 | |
| 379 | # CAmkES defines its own heaps and for this to work muslcsys must not be configured to |
| 380 | # use a static morecore. We make the morecore dynamic by setting the size to 0 |
| 381 | set(LibSel4MuslcSysMorecoreBytes 0 CACHE STRING "" FORCE) |
| 382 | |
| 383 | # Function to help build the CAMKES_TOOL_ENVIRONMENT below |
| 384 | function(camkes_append_env_if) |
| 385 | # Loop through each pair of arguments and build the environment |
| 386 | set(local_env "${CAMKES_TOOL_ENVIRONMENT}") |
| 387 | math(EXPR limit "${ARGC} - 1") |
| 388 | foreach(i RANGE 0 ${limit} 2) |
| 389 | math(EXPR ip1 "${i} + 1") |
| 390 | set(check "${ARGV${i}}") |
| 391 | string(REGEX REPLACE " +" ";" check "${check}") |
| 392 | if(${check}) |
| 393 | # Add the environment |
| 394 | list(APPEND local_env "${ARGV${ip1}}=1") |
| 395 | endif() |
| 396 | endforeach() |
| 397 | set(CAMKES_TOOL_ENVIRONMENT "${local_env}" PARENT_SCOPE) |
| 398 | endfunction(camkes_append_env_if) |
| 399 | |
| 400 | function(camkes_append_flags) |
| 401 | math(EXPR limit "${ARGC} - 1") |
| 402 | set(local_flags "${CAMKES_FLAGS}") |
| 403 | foreach(i RANGE 0 ${limit}) |
| 404 | set(list "${ARGV${i}}") |
| 405 | list(GET list 0 check) |
| 406 | string(REGEX REPLACE " +" ";" check "${check}") |
| 407 | if(${check}) |
| 408 | list(GET list 1 when_true) |
| 409 | list(APPEND local_flags "${when_true}") |
| 410 | else() |
| 411 | list(LENGTH list len) |
| 412 | if (${len} GREATER 2) |
| 413 | list(GET list 2 when_false) |
| 414 | list(APPEND local_flags "${when_false}") |
| 415 | endif() |
| 416 | endif() |
| 417 | endforeach() |
| 418 | set(CAMKES_FLAGS "${local_flags}" PARENT_SCOPE) |
| 419 | endfunction(camkes_append_flags) |
| 420 | |
| 421 | # This is called from the context of a CAmkES application that has decided what the 'root' |
| 422 | # application is. This function will effectively generate a rule for building the final |
| 423 | # rootserver image |
| 424 | function(DeclareCAmkESRootserver adl) |
| 425 | cmake_parse_arguments(PARSE_ARGV 1 CAMKES_ROOT |
| 426 | "" # Option arguments |
| 427 | "" # Single arguments |
| 428 | "CPP_FLAGS;CPP_INCLUDES" # Multiple aguments |
| 429 | ) |
| 430 | # Stash this request as a global property. The main CAmkES build file will call |
| 431 | # GenerateCAmkESRootserver later once all the build scripts are processed |
| 432 | get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED) |
| 433 | if (declared) |
| 434 | message(FATAL_ERROR "A CAmkES rootserver was already declared") |
| 435 | endif() |
| 436 | foreach(include IN LISTS CAMKES_ROOT_CPP_INCLUDES) |
| 437 | get_absolute_source_or_binary(include "${include}") |
| 438 | list(APPEND CAMKES_ROOT_CPP_FLAGS "-I${include}") |
| 439 | endforeach() |
| 440 | get_absolute_source_or_binary(adl "${adl}") |
| 441 | set_property(GLOBAL PROPERTY CAMKES_ROOT_ADL "${adl}") |
| 442 | set_property(GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS "${CAMKES_ROOT_CPP_FLAGS}") |
| 443 | set_property(GLOBAL PROPERTY CAMKES_ROOT_DECLARED TRUE) |
| 444 | endfunction(DeclareCAmkESRootserver) |
| 445 | |
| 446 | # Called to actually generate the definitions for the CAmkES rootserver. Due to its |
| 447 | # use of properties for some configuration it needs to be run after all other build |
| 448 | # scripts, typically by the main CAmkES build file |
| 449 | function(GenerateCAmkESRootserver) |
| 450 | # Retrieve properties from the declare call above |
| 451 | get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED) |
| 452 | if (NOT declared) |
| 453 | message(FATAL_ERROR "No CAmkES rootserver was declared") |
| 454 | endif() |
| 455 | get_property(adl GLOBAL PROPERTY CAMKES_ROOT_ADL) |
| 456 | get_property(CAMKES_ROOT_CPP_FLAGS GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS) |
| 457 | set(CAMKES_TOOL_ENVIRONMENT "") |
| 458 | set(CAMKES_TOOL_DEPENDENCIES "") |
| 459 | # Build the environment expected by camkes, as well as the camkes.sh wrapper script |
| 460 | list(APPEND CAMKES_TOOL_ENVIRONMENT "PYTHONPATH=$ENV{PYTHONPATH}:${PYTHON_CAPDL_PATH}") |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 461 | # List of 'if condition' 'definition to add' for building the environment exports |
| 462 | camkes_append_env_if( |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 463 | "${CAmkESObjdumpMethod} STREQUAL on" CONFIG_CAMKES_USE_OBJDUMP_ON |
| 464 | "${CAmkESObjdumpMethod} STREQUAL auto" CONFIG_CAMKES_USE_OBJDUMP_AUTO |
| 465 | "${CAmkESPythonOptimisation} STREQUAL -O" CONFIG_CAMKES_PYTHON_OPTIMISE_BASIC |
| 466 | "${CAmkESPythonOptimisation} STREQUAL -OO" CONFIG_CAMKES_PYTHON_OPTIMISE_MORE |
| 467 | "${CAmkESPythonInterpreter} STREQUAL cpython" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON |
| 468 | "${CAmkESPythonInterpreter} STREQUAL cpython2" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON2 |
| 469 | "${CAmkESPythonInterpreter} STREQUAL cpython3" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON3 |
| 470 | "${CAmkESPythonInterpreter} STREQUAL pypy" CONFIG_CAMKES_PYTHON_INTERPRETER_PYPY |
| 471 | "${CAmkESPythonInterpreter} STREQUAL figleaf" CONFIG_CAMKES_PYTHON_INTERPRETER_FIGLEAF |
| 472 | "${CAmkESPythonInterpreter} STREQUAL coverage" CONFIG_CAMKES_PYTHON_INTERPRETER_COVERAGE |
| 473 | ) |
| 474 | # Use the path as constructed at generation time |
| 475 | list(APPEND CAMKES_TOOL_ENVIRONMENT "PATH=$ENV{PATH}") |
| 476 | get_filename_component(CAMKES_CDL_TARGET "${adl}" NAME_WE) |
| 477 | set(CAMKES_CDL_TARGET "${CMAKE_CURRENT_BINARY_DIR}/${CAMKES_CDL_TARGET}.cdl") |
| 478 | # Get an absolute reference to the ADL source |
| 479 | get_absolute_source_or_binary(CAMKES_ADL_SOURCE "${adl}") |
| 480 | # Declare a common CAMKES_FLAGS that we will need to give to every invocation of camkes |
| 481 | set(CAMKES_FLAGS |
| 482 | "--import-path=${CAMKES_TOOL_BUILTIN_DIR}" |
| 483 | --platform seL4 |
| 484 | --architecture ${KernelSel4Arch} |
| 485 | --default-priority ${CAmkESDefaultPriority} |
| 486 | --default-affinity ${CAmkESDefaultAffinity} |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 487 | ) |
| 488 | # Build extra flags from the configuration |
| 489 | # Each of these arguments is a CONDITION FLAG_IF_CONDITION_TRUE [FLAG_IF_CONDITION_FALSE] |
| 490 | camkes_append_flags( |
| 491 | "CAmkESVerbose;--debug" |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 492 | "KernelIsMCS;--realtime" |
| 493 | "CAmkESRPCLockElision;--frpc-lock-elision;--fno-rpc-lock-elision" |
| 494 | "CAmkESSpecialiseSyscallStubs;--fspecialise-syscall-stubs;--fno-specialise-syscall-stubs" |
| 495 | "CAmkESProvideTCBCaps;--fprovide-tcb-caps;--fno-provide-tcb-caps" |
| 496 | "CAmkESSupportInit;--fsupport-init;--fno-support-init" |
| 497 | "CAmkESLargeFramePromotion;--largeframe" |
| 498 | "CAmkESDMALargeFramePromotion;--largeframe-dma" |
| 499 | "CAmkESAllowForwardReferences;--allow-forward-references" |
| 500 | "CAmkESFaultHandlers;--debug-fault-handlers" |
| 501 | "CAmkESCPP;--cpp" |
| 502 | ) |
| 503 | foreach(flag IN LISTS CAMKES_ROOT_CPP_FLAGS) |
| 504 | if(NOT CAmkESCPP) |
| 505 | message(FATAL_ERROR "Given CPP_FLAGS ${CAMKES_ROOT_CPP_FLAGS} but CAmkESCPP is disabled") |
| 506 | endif() |
| 507 | list(APPEND CAMKES_FLAGS "--cpp-flag=${flag}") |
| 508 | endforeach() |
| 509 | # Retrieve any extra import paths |
| 510 | get_property(imports GLOBAL PROPERTY CAmkESExtraImportPaths) |
| 511 | foreach(import IN LISTS imports) |
| 512 | list(APPEND CAMKES_FLAGS "--import-path=${import}") |
| 513 | endforeach() |
| 514 | # Retrieve any templte paths |
| 515 | get_property(templates GLOBAL PROPERTY CAmkESTemplatePaths) |
| 516 | foreach(template IN LISTS templates) |
| 517 | list(APPEND CAMKES_FLAGS --templates "${template}") |
| 518 | endforeach() |
Adrian Danis | 0f24c72 | 2018-03-23 11:30:23 +1100 | [diff] [blame^] | 519 | # Need to ensure our camkes_gen folder exists as camkes will not create the directory |
| 520 | file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/camkes_gen") |
| 521 | set(deps_file "${CMAKE_CURRENT_BINARY_DIR}/camkes_gen/deps") |
Adrian Danis | cf76ead | 2018-03-23 10:57:41 +1100 | [diff] [blame] | 522 | set(gen_outfile "${CMAKE_CURRENT_BINARY_DIR}/camkes-gen.cmake") |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 523 | execute_process( |
| 524 | # First delete the data structure cache directory as this is a new build |
| 525 | COMMAND |
| 526 | ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIRECTOR}/camkes_pickle" |
| 527 | COMMAND |
| 528 | ${CMAKE_COMMAND} -E env ${CAMKES_TOOL_ENVIRONMENT} "${CAMKES_TOOL}" |
| 529 | --file "${CAMKES_ADL_SOURCE}" |
| 530 | --item camkes-gen.cmake |
Adrian Danis | cf76ead | 2018-03-23 10:57:41 +1100 | [diff] [blame] | 531 | --outfile "${gen_outfile}" |
Adrian Danis | 0f24c72 | 2018-03-23 11:30:23 +1100 | [diff] [blame^] | 532 | --makefile-dependencies "${deps_file}" |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 533 | ${CAMKES_FLAGS} |
| 534 | RESULT_VARIABLE camkes_gen_error |
| 535 | OUTPUT_VARIABLE camkes_output |
| 536 | ERROR_VARIABLE camkes_output |
| 537 | ) |
| 538 | if (camkes_gen_error) |
| 539 | message(FATAL_ERROR "Failed to generate camkes-gen.cmake: ${camkes_output}") |
| 540 | endif() |
| 541 | # We set a property to indicate that we have done execute_process (which happens during the |
| 542 | # generation phase. This just allows us to do some debugging and detect cases where options |
| 543 | # are changed *after* this point that would have affected the execute_process |
| 544 | set_property(GLOBAL PROPERTY CAMKES_GEN_DONE TRUE) |
Adrian Danis | cf76ead | 2018-03-23 10:57:41 +1100 | [diff] [blame] | 545 | include("${gen_outfile}") |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 546 | endfunction(GenerateCAmkESRootserver) |
| 547 | |
Adrian Danis | 3291bed | 2018-03-08 13:47:17 +1100 | [diff] [blame] | 548 | # Internal helper function for setting camkes component properties |
| 549 | function(AppendCAmkESComponentTarget target_name) |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 550 | cmake_parse_arguments(PARSE_ARGV 1 CAMKES_COMPONENT |
| 551 | "" # Option arguments |
| 552 | "" # Single arguments |
| 553 | "SOURCES;INCLUDES;C_FLAGS;LD_FLAGS;LIBS" # Multiple aguments |
| 554 | ) |
| 555 | # Declare a target that we will set properties on |
Adrian Danis | 3291bed | 2018-03-08 13:47:17 +1100 | [diff] [blame] | 556 | if (NOT (TARGET "${target_name}")) |
| 557 | add_custom_target("${target_name}") |
Adrian Danis | 810df60 | 2018-03-08 13:44:21 +1100 | [diff] [blame] | 558 | endif() |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 559 | # Get absolute paths for the includes and sources |
| 560 | set(includes "") |
| 561 | set(sources "") |
| 562 | foreach(inc IN LISTS CAMKES_COMPONENT_INCLUDES) |
| 563 | get_absolute_source_or_binary(inc "${inc}") |
| 564 | list(APPEND includes "${inc}") |
| 565 | endforeach() |
| 566 | foreach(file IN LISTS CAMKES_COMPONENT_SOURCES) |
| 567 | get_absolute_source_or_binary(file "${file}") |
| 568 | list(APPEND sources "${file}") |
| 569 | endforeach() |
Adrian Danis | 3291bed | 2018-03-08 13:47:17 +1100 | [diff] [blame] | 570 | set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_INCLUDES "${includes}") |
| 571 | set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_SOURCES "${sources}") |
| 572 | set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_C_FLAGS "${CAMKES_COMPONENT_C_FLAGS}") |
| 573 | set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LD_FLAGS "${CAMKES_COMPONENT_LD_FLAGS}") |
| 574 | set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LIBS "${CAMKES_COMPONENT_LIBS}") |
| 575 | endfunction(AppendCAmkESComponentTarget) |
| 576 | |
| 577 | # This is called by CAmkES components to declare information needed for the camkes-gen.cmake to |
| 578 | # actually build them. Can be called multiple times to append additional information. |
| 579 | function(DeclareCAmkESComponent name) |
| 580 | AppendCAmkESComponentTarget(CAmkESComponent_${name} ${ARGN}) |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 581 | endfunction(DeclareCAmkESComponent) |
| 582 | |
Adrian Danis | 39b2860 | 2018-03-08 14:19:08 +1100 | [diff] [blame] | 583 | # Extend a particular instantiation of a CAmkES component with additional information. This takes |
| 584 | # similar arguments to DeclareCAmkESComponent and all of the declared includes, flags etc also |
| 585 | # apply to the sources from DeclareCAmkESComponent. The includes provided here will be passed |
| 586 | # prior to the original includes allowing for overriding. This can be called multiple times for the |
| 587 | # same instance to repeatedly extend it. Similar flags will be placed after. |
| 588 | function(ExtendCAmkESComponentInstance component_name instance_name) |
| 589 | AppendCAmkESComponentTarget(CAmkESComponent_${component_name}_instance_${instance_name} ${ARGN}) |
| 590 | endfunction(ExtendCAmkESComponentInstance) |
| 591 | |
Adrian Danis | ec8f709 | 2017-10-16 16:47:58 +1100 | [diff] [blame] | 592 | # Helper function for adding additional import paths. Largely it exists to allow list |
| 593 | # files to give relative paths and have them automatically expanded to absolute paths |
| 594 | # We add the import paths to a property, instead of a target, since we need to use |
| 595 | # it in an `execute_process` above, which cannot take generator expressions |
| 596 | function(CAmkESAddImportPath) |
| 597 | # Ensure we haven't generated the camkes-gen.cmake yet |
| 598 | get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE) |
| 599 | if (is_done) |
| 600 | message(FATAL_ERROR "Adding import path after camkes-gen.cmake has been generated") |
| 601 | endif() |
| 602 | foreach(arg IN LISTS ARGV) |
| 603 | get_absolute_source_or_binary(arg "${arg}") |
| 604 | set_property(GLOBAL APPEND PROPERTY CAmkESExtraImportPaths "${arg}") |
| 605 | endforeach() |
| 606 | endfunction(CAmkESAddImportPath) |
| 607 | function(CAmkESAddTemplatesPath) |
| 608 | # Ensure we haven't generated the camkes-gen.cmake yet |
| 609 | get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE) |
| 610 | if (is_done) |
| 611 | message(FATAL_ERROR "Adding templates path after camkes-gen.cmake has been generated") |
| 612 | endif() |
| 613 | foreach(arg IN LISTS ARGV) |
| 614 | get_absolute_source_or_binary(arg "${arg}") |
| 615 | set_property(GLOBAL APPEND PROPERTY CAmkESTemplatePaths "${arg}") |
| 616 | endforeach() |
| 617 | endfunction(CAmkESAddTemplatesPath) |