-
Notifications
You must be signed in to change notification settings - Fork 71
/
camkes.cmake
825 lines (762 loc) · 29 KB
/
camkes.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
#
# 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)