blob: c9b1e3f87e63903f9e50e4b5d964262eb5fa20b6 [file] [log] [blame]
Adrian Danisec8f7092017-10-16 16:47:58 +11001#
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
13cmake_minimum_required(VERSION 3.7.2)
14
15include(ExternalProject)
16
17include(${KERNEL_HELPERS_PATH})
18
19set(configure_string "")
20
21config_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
28config_string(CAmkESDefaultHeapSize CAMKES_DEFAULT_HEAP_SIZE
29 "Heap size to allocate per-component, in bytes."
30 DEFAULT 1048576
31 UNQUOTE
32)
33
34config_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
66config_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
73config_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
83config_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 Danis4a99eb32018-03-07 15:58:12 +1100100config_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)
108if ((${CAmkESDefaultPriority} LESS 0) OR (${CAmkESDefaultPriority} GREATER 255))
109 message(FATAL_ERROR "CAmkESDefaultPriority must be [0, 255]")
110endif()
111
Adrian Danisec8f7092017-10-16 16:47:58 +1100112add_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
116set(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
122set(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 Danisec8f7092017-10-16 16:47:58 +1100128set(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)
134math(EXPR MaxNumNodesMin1 "${KernelMaxNumNodes} - 1")
135if((${CAmkESDefaultAffinity} < 0) OR (${CAmkESDefaultAffinity} GREATER ${MaxNumNodesMin1}))
136 message(FATAL_ERROR "Invalid CAmkESDefaultAffinity")
137endif()
138
139set(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
148set(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)
169set_property(CACHE CAmkESObjdumpMethod PROPERTY STRINGS "auto;on;off")
170
Adrian Danisec8f7092017-10-16 16:47:58 +1100171set(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
177set(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
186set(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
197set(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
206set(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)
219set_property(CACHE CAmkESPythonOptimisation PROPERTY STRINGS "none;-O;-OO")
220
221set(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)
251set_property(CACHE CAmkESPythonInterpreter PROPERTY STRINGS "cpython;cpython2;cpython3;pypy;figleaf;coverage")
252
253set(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
261set(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
Anna Lyons44adb6d2018-08-02 14:39:50 +1000268set(CAmkESDTS OFF CACHE BOOL
269 "Support using a device tree (.dts) file, which camkes can query
270 for device properties. A file path can be provided by as an argument
271 to DeclareCAmkESRootserver as DTS_FILE_PATH, otherwise the a dts file
272 matching the platform will be found in seL4/tools."
273)
274
Adrian Danisec8f7092017-10-16 16:47:58 +1100275# TODO: The following options are not yet supported in cmake build template, as a result
276# these are currently commented out to as not to confuse users. They should be uncommented
277# as support is added
278#set(CAmkESPruneGenerated OFF CACHE BOOL
279# "Prune generated C files
280# When selected, this option minimises the number of C functions in a
281# given generated file. This can be done because the CAmkES generation
282# logic knows which functions are required by the user's components and
283# which are not. This option implies a separate pre-process step on the
284# generated files prior to pruning/compilation, otherwise the generated
285# C files are already minimal. Note, you will need libclang-dev installed
286# to enable this option."
287#)
288
289#set(CAmkESThys OFF CACHE BOOL
290# "Generate correctness proofs
291# Generate AutoCorres-based theories of connector correctness during
292# compilation."
293#)
294
295#set(CAmkESUnifiedThy OFF CACHE BOOL
296# "Generate unified correctness proof
297# Generate an AutoCorred-based theory combining the two glue code halves
298# of a connector, resulting in a final correctness statement."
299# DEPENDS CAmkESPruneGenerated
300#)
301
302#set(CAmkESArchThy OFF CACHE BOOL
303# "Generate architectural specification
304# Generate an Isabelle theory specifying the architecture of the
305# system, using the l4.verified formal model of ADL."
306#)
307
308#set(CAmkESCImpThy OFF CACHE BOOL
309# "Generate dynamic behavioural specification
310# Generate an Isabelle theory specifying the dynamic behaviour of the
311# system. This theory builds on top of the CIMP formalisation."
312#)
313
314#set(CAmkESCapDLThy OFF CACHE BOOL
315# "Generate CapDL Isabelle specification
316# During a CAmkES build, a textual CapDL specification of the system
317# is generated for the purpose of initialisation. Selecting this
318# option causes an Isabelle version of this specification to be
319# generated as well for the purposes of reasoning about the
320# capability distribution of a CAmkES system"
321#)
322
323#set(CAmkESLabelMapping OFF CACHE BOOL
324# "Generate policy label mapping
325# Enable this option to generate a mapping from labels to kernel objects
326# during compilation. A label per-CAmkES entity (component instance or
327# connection) is generated and they are intended to form the input domain
328# of a function mapping these to final policy labels. The final labels
329# are then used to reason about the security properties of a system."
330#)
331
332set(CAmkESVerbose OFF CACHE BOOL
333 "Enable verbose output from CAmkES. This is disabled by default as it
334 can result in a lot of output, but is useful for debugging CAmkES problems"
335)
336
Adrian Danisca89b102018-03-14 16:41:18 +1100337# Save the path to to python-capdl whilst we know it (unless it was already specified)
338if (NOT PYTHON_CAPDL_PATH)
Kent McLeodf5d7fd62018-07-24 13:43:44 +1000339 set(PYTHON_CAPDL_PATH "${CMAKE_SOURCE_DIR}/projects/capdl/python-capdl-tool")
Adrian Danisca89b102018-03-14 16:41:18 +1100340endif()
341if (NOT CAPDL_TOOL_SOURCE_PATH)
Kent McLeodf5d7fd62018-07-24 13:43:44 +1000342 set(CAPDL_TOOL_SOURCE_PATH "${CMAKE_SOURCE_DIR}/projects/capdl/capDL-tool")
Adrian Danisca89b102018-03-14 16:41:18 +1100343endif()
Adrian Danisec8f7092017-10-16 16:47:58 +1100344
345# Save the location of the camkes tool wrapper script
346RequireFile(CAMKES_TOOL camkes.sh PATHS "${CMAKE_CURRENT_LIST_DIR}")
347
348# Use the camkes script to determine the location of other things
349get_filename_component(CAMKES_TOOL_DIR "${CAMKES_TOOL}" DIRECTORY)
350set(CAMKES_TOOL_BUILTIN_DIR "${CAMKES_TOOL_DIR}/include/builtin")
351
Adrian Danisec8f7092017-10-16 16:47:58 +1100352# Require the parse-capDL tool
353ExternalProject_Add(parse_capdl_tool
354 SOURCE_DIR "${CAPDL_TOOL_SOURCE_PATH}"
355 CONFIGURE_COMMAND bash -c "cp -ra ${CAPDL_TOOL_SOURCE_PATH}/* ."
356 BUILD_ALWAYS ON
Kent McLeode13a05e2018-08-28 11:37:19 +1000357 BUILD_COMMAND ${CMAKE_COMMAND} -E env make
Adrian Danisec8f7092017-10-16 16:47:58 +1100358 INSTALL_COMMAND ${CMAKE_COMMAND} -E env "PATH=$ENV{PATH}:${CMAKE_CURRENT_BINARY_DIR}/parse_capdl_tool-prefix/src/parse_capdl_tool-build" make install
359)
360ExternalProject_Get_property(parse_capdl_tool BINARY_DIR)
361set(CAPDL_TOOL_PATH "${BINARY_DIR}")
362
363# Search for a FMT tool for reformatting generated CAmkES C files
364find_program(CLANG_FORMAT_TOOL clang-format)
365if ("${CLANG_FORMAT_TOOL}" STREQUAL "CLANG_FORMAT_TOOL-NOTFOUND")
366 set(CAMKES_C_FMT_INVOCATION "")
367else()
368 set(CAMKES_C_FMT_INVOCATION "${CLANG_FORMAT_TOOL} --style=LLVM")
369endif()
370
371# Find the sponge tool, or emulate it
372find_program(SPONGE_TOOL sponge)
373if ("${SPONGE_TOOL}" STREQUAL "SPONGE_TOOL-NOTFOUND")
Adrian Danis0fdc9d62018-06-22 15:01:49 +1000374 set(CAMKES_SPONGE_INVOCATION "sh ${CMAKE_CURRENT_BINARY_DIR}/sponge_emul.sh")
Adrian Danisec8f7092017-10-16 16:47:58 +1100375 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()' $@")
376else()
377 set(CAMKES_SPONGE_INVOCATION "${SPONGE_TOOL}")
378endif()
379
380# Find the Isabelle theory pre-process for formatting theory files
Kent McLeodf5d7fd62018-07-24 13:43:44 +1000381find_program(TPP_TOOL tpp PATHS ${CMAKE_CURRENT_LIST_DIR}/tools)
Adrian Danisec8f7092017-10-16 16:47:58 +1100382if ("${TPP_TOOL}" STREQUAL "TPP_TOOL-NOTFOUND")
383 message(FATAL_ERROR "Failed to find tpp tool")
384endif()
385
386# CAmkES defines its own heaps and for this to work muslcsys must not be configured to
387# use a static morecore. We make the morecore dynamic by setting the size to 0
388set(LibSel4MuslcSysMorecoreBytes 0 CACHE STRING "" FORCE)
389
390# Function to help build the CAMKES_TOOL_ENVIRONMENT below
391function(camkes_append_env_if)
392 # Loop through each pair of arguments and build the environment
393 set(local_env "${CAMKES_TOOL_ENVIRONMENT}")
394 math(EXPR limit "${ARGC} - 1")
395 foreach(i RANGE 0 ${limit} 2)
396 math(EXPR ip1 "${i} + 1")
397 set(check "${ARGV${i}}")
398 string(REGEX REPLACE " +" ";" check "${check}")
399 if(${check})
400 # Add the environment
401 list(APPEND local_env "${ARGV${ip1}}=1")
402 endif()
403 endforeach()
404 set(CAMKES_TOOL_ENVIRONMENT "${local_env}" PARENT_SCOPE)
405endfunction(camkes_append_env_if)
406
407function(camkes_append_flags)
408 math(EXPR limit "${ARGC} - 1")
409 set(local_flags "${CAMKES_FLAGS}")
410 foreach(i RANGE 0 ${limit})
411 set(list "${ARGV${i}}")
412 list(GET list 0 check)
413 string(REGEX REPLACE " +" ";" check "${check}")
414 if(${check})
415 list(GET list 1 when_true)
416 list(APPEND local_flags "${when_true}")
417 else()
418 list(LENGTH list len)
419 if (${len} GREATER 2)
420 list(GET list 2 when_false)
421 list(APPEND local_flags "${when_false}")
422 endif()
423 endif()
424 endforeach()
425 set(CAMKES_FLAGS "${local_flags}" PARENT_SCOPE)
426endfunction(camkes_append_flags)
427
428# This is called from the context of a CAmkES application that has decided what the 'root'
429# application is. This function will effectively generate a rule for building the final
430# rootserver image
431function(DeclareCAmkESRootserver adl)
432 cmake_parse_arguments(PARSE_ARGV 1 CAMKES_ROOT
433 "" # Option arguments
Anna Lyons44adb6d2018-08-02 14:39:50 +1000434 "DTS_FILE_PATH" # Single arguments
Adrian Danisec8f7092017-10-16 16:47:58 +1100435 "CPP_FLAGS;CPP_INCLUDES" # Multiple aguments
436 )
437 # Stash this request as a global property. The main CAmkES build file will call
438 # GenerateCAmkESRootserver later once all the build scripts are processed
439 get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED)
440 if (declared)
441 message(FATAL_ERROR "A CAmkES rootserver was already declared")
442 endif()
443 foreach(include IN LISTS CAMKES_ROOT_CPP_INCLUDES)
Kent McLeod94369c42018-07-24 13:46:25 +1000444 get_absolute_list_source_or_binary(include "${include}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100445 list(APPEND CAMKES_ROOT_CPP_FLAGS "-I${include}")
446 endforeach()
Kent McLeod94369c42018-07-24 13:46:25 +1000447 get_absolute_list_source_or_binary(adl "${adl}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100448 set_property(GLOBAL PROPERTY CAMKES_ROOT_ADL "${adl}")
449 set_property(GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS "${CAMKES_ROOT_CPP_FLAGS}")
450 set_property(GLOBAL PROPERTY CAMKES_ROOT_DECLARED TRUE)
Anna Lyons44adb6d2018-08-02 14:39:50 +1000451 if(${CAmkESDTS} AND NOT "${CAMKES_ROOT_DTS_FILE}" STREQUAL "")
452 get_absolute_list_source_or_binary(CAMKES_ROOT_DTS_FILE_PATH "${CAMKES_ROOT_DTS_FILE_PATH}")
453 endif()
454 set_property(GLOBAL PROPERTY CAMKES_ROOT_DTS_FILE_PATH "${CAMKES_ROOT_DTS_FILE_PATH}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100455endfunction(DeclareCAmkESRootserver)
456
Adrian Danis84a80212018-03-23 11:35:17 +1100457# This takes a camkes produced dependency file (this means we can assume one dependency
458# per line) and produces a cmake list of dependencies
459function(MakefileDepsToList mdfile output_variable)
460 file(READ "${mdfile}" raw_file)
461 # First remove the target of the dependency list
462 string(REGEX REPLACE "^[^:]*: \\\\\r?\n" "" string_deps "${raw_file}")
463 # Now turn the list of dependencies into a cmake list. We have assumed
464 # that this makefile dep file was generated by camkes and so it has one
465 # item per line
466 string(REGEX REPLACE "\\\\\r?\n" ";" deps "${string_deps}")
467 # Strip the space from each dep
468 foreach(dep IN LISTS deps)
469 # Strip extra spacing
470 string(STRIP "${dep}" dep)
471 list(APPEND final_deps "${dep}")
472 endforeach()
473 # Write the output to the parent
474 set("${output_variable}" "${final_deps}" PARENT_SCOPE)
475endfunction(MakefileDepsToList)
476
Adrian Danisec8f7092017-10-16 16:47:58 +1100477# Called to actually generate the definitions for the CAmkES rootserver. Due to its
478# use of properties for some configuration it needs to be run after all other build
479# scripts, typically by the main CAmkES build file
480function(GenerateCAmkESRootserver)
481 # Retrieve properties from the declare call above
482 get_property(declared GLOBAL PROPERTY CAMKES_ROOT_DECLARED)
483 if (NOT declared)
484 message(FATAL_ERROR "No CAmkES rootserver was declared")
485 endif()
486 get_property(adl GLOBAL PROPERTY CAMKES_ROOT_ADL)
487 get_property(CAMKES_ROOT_CPP_FLAGS GLOBAL PROPERTY CAMKES_ROOT_CPP_FLAGS)
Anna Lyons44adb6d2018-08-02 14:39:50 +1000488 get_property(dts_file GLOBAL PROPERTY CAMKES_ROOT_DTS_FILE_PATH)
Adrian Danisec8f7092017-10-16 16:47:58 +1100489 set(CAMKES_TOOL_ENVIRONMENT "")
490 set(CAMKES_TOOL_DEPENDENCIES "")
491 # Build the environment expected by camkes, as well as the camkes.sh wrapper script
492 list(APPEND CAMKES_TOOL_ENVIRONMENT "PYTHONPATH=$ENV{PYTHONPATH}:${PYTHON_CAPDL_PATH}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100493 # List of 'if condition' 'definition to add' for building the environment exports
494 camkes_append_env_if(
Adrian Danisec8f7092017-10-16 16:47:58 +1100495 "${CAmkESObjdumpMethod} STREQUAL on" CONFIG_CAMKES_USE_OBJDUMP_ON
496 "${CAmkESObjdumpMethod} STREQUAL auto" CONFIG_CAMKES_USE_OBJDUMP_AUTO
497 "${CAmkESPythonOptimisation} STREQUAL -O" CONFIG_CAMKES_PYTHON_OPTIMISE_BASIC
498 "${CAmkESPythonOptimisation} STREQUAL -OO" CONFIG_CAMKES_PYTHON_OPTIMISE_MORE
499 "${CAmkESPythonInterpreter} STREQUAL cpython" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON
500 "${CAmkESPythonInterpreter} STREQUAL cpython2" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON2
501 "${CAmkESPythonInterpreter} STREQUAL cpython3" CONFIG_CAMKES_PYTHON_INTERPRETER_CPYTHON3
502 "${CAmkESPythonInterpreter} STREQUAL pypy" CONFIG_CAMKES_PYTHON_INTERPRETER_PYPY
503 "${CAmkESPythonInterpreter} STREQUAL figleaf" CONFIG_CAMKES_PYTHON_INTERPRETER_FIGLEAF
504 "${CAmkESPythonInterpreter} STREQUAL coverage" CONFIG_CAMKES_PYTHON_INTERPRETER_COVERAGE
505 )
506 # Use the path as constructed at generation time
507 list(APPEND CAMKES_TOOL_ENVIRONMENT "PATH=$ENV{PATH}")
508 get_filename_component(CAMKES_CDL_TARGET "${adl}" NAME_WE)
509 set(CAMKES_CDL_TARGET "${CMAKE_CURRENT_BINARY_DIR}/${CAMKES_CDL_TARGET}.cdl")
510 # Get an absolute reference to the ADL source
Kent McLeod94369c42018-07-24 13:46:25 +1000511 get_absolute_list_source_or_binary(CAMKES_ADL_SOURCE "${adl}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100512 # Declare a common CAMKES_FLAGS that we will need to give to every invocation of camkes
513 set(CAMKES_FLAGS
514 "--import-path=${CAMKES_TOOL_BUILTIN_DIR}"
515 --platform seL4
516 --architecture ${KernelSel4Arch}
517 --default-priority ${CAmkESDefaultPriority}
518 --default-affinity ${CAmkESDefaultAffinity}
Adrian Danisec8f7092017-10-16 16:47:58 +1100519 )
Anna Lyons44adb6d2018-08-02 14:39:50 +1000520
521 if (${CAmkESDTS})
522 # Find the dts to use
523 if ("${dts_file}" STREQUAL "")
524 # no dts file set, try to find the default
525 FindDTS(dts_file ${PLATFORM})
526 elseif(NOT EXISTS "${dts_file}")
527 message(FATAL_ERROR "Could not find dts file ${dts_file}")
528 endif()
529 GenDTB("${dts_file}" dtb_file)
530 list(APPEND CAMKES_FLAGS "--dtb=${dtb_file}")
531 endif()
532
Adrian Danisec8f7092017-10-16 16:47:58 +1100533 # Build extra flags from the configuration
534 # Each of these arguments is a CONDITION FLAG_IF_CONDITION_TRUE [FLAG_IF_CONDITION_FALSE]
535 camkes_append_flags(
536 "CAmkESVerbose;--debug"
Adrian Danisec8f7092017-10-16 16:47:58 +1100537 "KernelIsMCS;--realtime"
538 "CAmkESRPCLockElision;--frpc-lock-elision;--fno-rpc-lock-elision"
539 "CAmkESSpecialiseSyscallStubs;--fspecialise-syscall-stubs;--fno-specialise-syscall-stubs"
540 "CAmkESProvideTCBCaps;--fprovide-tcb-caps;--fno-provide-tcb-caps"
541 "CAmkESSupportInit;--fsupport-init;--fno-support-init"
542 "CAmkESLargeFramePromotion;--largeframe"
543 "CAmkESDMALargeFramePromotion;--largeframe-dma"
544 "CAmkESAllowForwardReferences;--allow-forward-references"
545 "CAmkESFaultHandlers;--debug-fault-handlers"
546 "CAmkESCPP;--cpp"
547 )
548 foreach(flag IN LISTS CAMKES_ROOT_CPP_FLAGS)
549 if(NOT CAmkESCPP)
550 message(FATAL_ERROR "Given CPP_FLAGS ${CAMKES_ROOT_CPP_FLAGS} but CAmkESCPP is disabled")
551 endif()
552 list(APPEND CAMKES_FLAGS "--cpp-flag=${flag}")
553 endforeach()
554 # Retrieve any extra import paths
555 get_property(imports GLOBAL PROPERTY CAmkESExtraImportPaths)
556 foreach(import IN LISTS imports)
557 list(APPEND CAMKES_FLAGS "--import-path=${import}")
558 endforeach()
Anna Lyonsbf8f9c72018-08-02 14:43:35 +1000559 # Retrieve any template paths
Adrian Danisec8f7092017-10-16 16:47:58 +1100560 get_property(templates GLOBAL PROPERTY CAmkESTemplatePaths)
561 foreach(template IN LISTS templates)
562 list(APPEND CAMKES_FLAGS --templates "${template}")
563 endforeach()
Adrian Danis0f24c722018-03-23 11:30:23 +1100564 # Need to ensure our camkes_gen folder exists as camkes will not create the directory
565 file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/camkes_gen")
566 set(deps_file "${CMAKE_CURRENT_BINARY_DIR}/camkes_gen/deps")
Adrian Danis2bf14a02018-03-23 11:45:22 +1100567 set(invoc_file "${CMAKE_CURRENT_BINARY_DIR}/camkes_gen/last_invocation")
Adrian Daniscf76ead2018-03-23 10:57:41 +1100568 set(gen_outfile "${CMAKE_CURRENT_BINARY_DIR}/camkes-gen.cmake")
Adrian Danisbd2f3752018-03-23 11:36:52 +1100569 set(camkes_invocation
Adrian Danisec8f7092017-10-16 16:47:58 +1100570 ${CMAKE_COMMAND} -E env ${CAMKES_TOOL_ENVIRONMENT} "${CAMKES_TOOL}"
571 --file "${CAMKES_ADL_SOURCE}"
572 --item camkes-gen.cmake
Adrian Daniscf76ead2018-03-23 10:57:41 +1100573 --outfile "${gen_outfile}"
Adrian Danis0f24c722018-03-23 11:30:23 +1100574 --makefile-dependencies "${deps_file}"
Adrian Danisec8f7092017-10-16 16:47:58 +1100575 ${CAMKES_FLAGS}
Adrian Danisbd2f3752018-03-23 11:36:52 +1100576 )
Adrian Danise2e22902018-03-23 11:41:59 +1100577 # We need to determine if we actually need to regenerate. We start by assuming that we do
578 set(regen TRUE)
Adrian Danis2bf14a02018-03-23 11:45:22 +1100579 if((EXISTS "${invoc_file}") AND (EXISTS "${deps_file}") AND (EXISTS "${gen_outfile}"))
580 file(READ "${invoc_file}" old_contents)
581 if ("${old_contents}" STREQUAL "${camkes_invocation}")
582 MakefileDepsToList("${deps_file}" deps)
583 # At this point assume we do not need to regenerate, unless we found a newer file
584 set(regen FALSE)
585 foreach(dep IN LISTS deps)
586 if("${dep}" IS_NEWER_THAN "${gen_outfile}")
587 set(regen TRUE)
588 break()
589 endif()
590 endforeach()
591 endif()
592 endif()
Adrian Danise2e22902018-03-23 11:41:59 +1100593 if (regen)
Adrian Danis2bf14a02018-03-23 11:45:22 +1100594 message(STATUS "camkes-gen.cmake is out of date. Regenerating...")
Adrian Danise2e22902018-03-23 11:41:59 +1100595 execute_process(
596 # First delete the data structure cache directory as this is a new build
597 COMMAND
598 ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIRECTOR}/camkes_pickle"
599 COMMAND ${camkes_invocation}
600 RESULT_VARIABLE camkes_gen_error
601 OUTPUT_VARIABLE camkes_output
602 ERROR_VARIABLE camkes_output
603 )
Adrian Danis2bf14a02018-03-23 11:45:22 +1100604 file(WRITE "${invoc_file}" "${camkes_invocation}")
Adrian Danise2e22902018-03-23 11:41:59 +1100605 if (camkes_gen_error)
Kent McLeod6eb834f2018-07-13 12:02:07 +1000606 file(REMOVE ${gen_outfile})
Adrian Danise2e22902018-03-23 11:41:59 +1100607 message(FATAL_ERROR "Failed to generate camkes-gen.cmake: ${camkes_output}")
608 endif()
609 # Add dependencies
610 MakefileDepsToList("${deps_file}" deps)
611 set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${deps}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100612 endif()
613 # We set a property to indicate that we have done execute_process (which happens during the
614 # generation phase. This just allows us to do some debugging and detect cases where options
615 # are changed *after* this point that would have affected the execute_process
616 set_property(GLOBAL PROPERTY CAMKES_GEN_DONE TRUE)
Adrian Daniscf76ead2018-03-23 10:57:41 +1100617 include("${gen_outfile}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100618endfunction(GenerateCAmkESRootserver)
619
Adrian Danis3291bed2018-03-08 13:47:17 +1100620# Internal helper function for setting camkes component properties
621function(AppendCAmkESComponentTarget target_name)
Adrian Danisec8f7092017-10-16 16:47:58 +1100622 cmake_parse_arguments(PARSE_ARGV 1 CAMKES_COMPONENT
623 "" # Option arguments
Kent McLeodcede2f12018-07-19 18:39:48 +1000624 "CAKEML_HEAP_SIZE;CAKEML_STACK_SIZE;LINKER_LANGUAGE" # Single arguments
Adrian Danis4b2a8502018-07-02 17:02:27 +1000625 "SOURCES;CAKEML_SOURCES;INCLUDES;C_FLAGS;LD_FLAGS;LIBS" # Multiple aguments
Adrian Danisec8f7092017-10-16 16:47:58 +1100626 )
627 # Declare a target that we will set properties on
Adrian Danis3291bed2018-03-08 13:47:17 +1100628 if (NOT (TARGET "${target_name}"))
629 add_custom_target("${target_name}")
Adrian Danis810df602018-03-08 13:44:21 +1100630 endif()
Adrian Danisec8f7092017-10-16 16:47:58 +1100631 # Get absolute paths for the includes and sources
632 set(includes "")
633 set(sources "")
Adrian Danis4b2a8502018-07-02 17:02:27 +1000634 set(cakeml_sources "")
Adrian Danisec8f7092017-10-16 16:47:58 +1100635 foreach(inc IN LISTS CAMKES_COMPONENT_INCLUDES)
Kent McLeod94369c42018-07-24 13:46:25 +1000636 get_absolute_list_source_or_binary(inc "${inc}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100637 list(APPEND includes "${inc}")
638 endforeach()
639 foreach(file IN LISTS CAMKES_COMPONENT_SOURCES)
Kent McLeod94369c42018-07-24 13:46:25 +1000640 get_absolute_list_source_or_binary(file "${file}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100641 list(APPEND sources "${file}")
642 endforeach()
Adrian Danis4b2a8502018-07-02 17:02:27 +1000643 foreach(file IN LISTS CAMKES_COMPONENT_CAKEML_SOURCES)
Kent McLeod94369c42018-07-24 13:46:25 +1000644 get_absolute_list_source_or_binary(file "${file}")
Adrian Danis4b2a8502018-07-02 17:02:27 +1000645 list(APPEND cakeml_sources "${file}")
646 endforeach()
Adrian Danis3291bed2018-03-08 13:47:17 +1100647 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_INCLUDES "${includes}")
648 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_SOURCES "${sources}")
Adrian Danis4b2a8502018-07-02 17:02:27 +1000649 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_CAKEML_SOURCES "${cakeml_sources}")
Adrian Danis3291bed2018-03-08 13:47:17 +1100650 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_C_FLAGS "${CAMKES_COMPONENT_C_FLAGS}")
651 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LD_FLAGS "${CAMKES_COMPONENT_LD_FLAGS}")
652 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LIBS "${CAMKES_COMPONENT_LIBS}")
Adrian Danis4b2a8502018-07-02 17:02:27 +1000653 # Overwrite any previous CakeML heap or stack size
654 if (CAMKES_COMPONENT_CAKEML_HEAP_SIZE)
655 set_property(TARGET "${target_name}" PROPERTY COMPONENT_CAKEML_HEAP_SIZE "${CAMKES_COMPONENT_CAKEML_HEAP_SIZE}")
656 endif()
657 if (CAMKES_COMPONENT_CAKEML_STACK_SIZE)
658 set_property(TARGET "${target_name}" PROPERTY COMPONENT_CAKEML_STACK_SIZE "${CAMKES_COMPONENT_CAKEML_STACK_SIZE}")
659 endif()
Kent McLeodcede2f12018-07-19 18:39:48 +1000660 if (CAMKES_COMPONENT_LINKER_LANGUAGE)
661 set_property(TARGET "${target_name}" APPEND PROPERTY COMPONENT_LINKER_LANGUAGE "${CAMKES_COMPONENT_LINKER_LANGUAGE}")
662 endif()
Adrian Danis3291bed2018-03-08 13:47:17 +1100663endfunction(AppendCAmkESComponentTarget)
664
665# This is called by CAmkES components to declare information needed for the camkes-gen.cmake to
666# actually build them. Can be called multiple times to append additional information.
667function(DeclareCAmkESComponent name)
668 AppendCAmkESComponentTarget(CAmkESComponent_${name} ${ARGN})
Adrian Danisec8f7092017-10-16 16:47:58 +1100669endfunction(DeclareCAmkESComponent)
670
Kent McLeodd786bc22018-05-09 10:09:05 +1000671# Declare built-in components that are constructed from templates and have no source files
672DeclareCAmkESComponent(debug_server)
673DeclareCAmkESComponent(debug_serial)
674
Adrian Danis39b28602018-03-08 14:19:08 +1100675# Extend a particular instantiation of a CAmkES component with additional information. This takes
676# similar arguments to DeclareCAmkESComponent and all of the declared includes, flags etc also
677# apply to the sources from DeclareCAmkESComponent. The includes provided here will be passed
678# prior to the original includes allowing for overriding. This can be called multiple times for the
679# same instance to repeatedly extend it. Similar flags will be placed after.
680function(ExtendCAmkESComponentInstance component_name instance_name)
681 AppendCAmkESComponentTarget(CAmkESComponent_${component_name}_instance_${instance_name} ${ARGN})
682endfunction(ExtendCAmkESComponentInstance)
683
Adrian Danisec8f7092017-10-16 16:47:58 +1100684# Helper function for adding additional import paths. Largely it exists to allow list
685# files to give relative paths and have them automatically expanded to absolute paths
686# We add the import paths to a property, instead of a target, since we need to use
687# it in an `execute_process` above, which cannot take generator expressions
688function(CAmkESAddImportPath)
689 # Ensure we haven't generated the camkes-gen.cmake yet
690 get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE)
691 if (is_done)
692 message(FATAL_ERROR "Adding import path after camkes-gen.cmake has been generated")
693 endif()
694 foreach(arg IN LISTS ARGV)
Kent McLeod94369c42018-07-24 13:46:25 +1000695 get_absolute_list_source_or_binary(arg "${arg}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100696 set_property(GLOBAL APPEND PROPERTY CAmkESExtraImportPaths "${arg}")
697 endforeach()
698endfunction(CAmkESAddImportPath)
699function(CAmkESAddTemplatesPath)
700 # Ensure we haven't generated the camkes-gen.cmake yet
701 get_property(is_done GLOBAL PROPERTY CAMKES_GEN_DONE)
702 if (is_done)
703 message(FATAL_ERROR "Adding templates path after camkes-gen.cmake has been generated")
704 endif()
705 foreach(arg IN LISTS ARGV)
Kent McLeod94369c42018-07-24 13:46:25 +1000706 get_absolute_list_source_or_binary(arg "${arg}")
Adrian Danisec8f7092017-10-16 16:47:58 +1100707 set_property(GLOBAL APPEND PROPERTY CAmkESTemplatePaths "${arg}")
708 endforeach()
709endfunction(CAmkESAddTemplatesPath)