forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CMakeLists.txt
504 lines (430 loc) · 15.5 KB
/
CMakeLists.txt
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
cmake_minimum_required(VERSION 3.13)
# Set build type to reduce firmware size
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE MinSizeRel)
endif()
# Set main target and component locations
set(MICROPY_TARGET firmware)
get_filename_component(MICROPY_DIR "../.." ABSOLUTE)
if (PICO_SDK_PATH_OVERRIDE)
set(PICO_SDK_PATH ${PICO_SDK_PATH_OVERRIDE})
else()
set(PICO_SDK_PATH ../../lib/pico-sdk)
endif()
# Use the local tinyusb instead of the one in pico-sdk
set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb)
# Use the local lwip instead of the one in pico-sdk
set(PICO_LWIP_PATH ${MICROPY_DIR}/lib/lwip)
# Use the local btstack instead of the one in pico-sdk
set(PICO_BTSTACK_PATH ${MICROPY_DIR}/lib/btstack)
# Set the location of this port's directory.
set(MICROPY_PORT_DIR ${CMAKE_CURRENT_LIST_DIR})
# Set the board if it's not already set.
if(NOT MICROPY_BOARD)
set(MICROPY_BOARD RPI_PICO)
endif()
# Set the board directory and check that it exists.
if(NOT MICROPY_BOARD_DIR)
set(MICROPY_BOARD_DIR ${MICROPY_PORT_DIR}/boards/${MICROPY_BOARD})
endif()
get_filename_component(MICROPY_BOARD_DIR ${MICROPY_BOARD_DIR} ABSOLUTE)
if(NOT EXISTS ${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
message(FATAL_ERROR "Invalid MICROPY_BOARD specified: ${MICROPY_BOARD}")
endif()
set(MICROPY_USER_FROZEN_MANIFEST ${MICROPY_FROZEN_MANIFEST})
# Include board config, it may override MICROPY_FROZEN_MANIFEST
include(${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
# Set the PICO_BOARD if it's not already set (allow a board to override it).
if(NOT PICO_BOARD)
string(TOLOWER ${MICROPY_BOARD} PICO_BOARD)
endif()
# Set the amount of C heap, if it's not already set.
# If a board uses malloc then it must set this to at least 4096.
if(NOT MICROPY_C_HEAP_SIZE)
set(MICROPY_C_HEAP_SIZE 0)
endif()
# Enable extmod components that will be configured by extmod.cmake.
# A board may also have enabled additional components.
set(MICROPY_SSL_MBEDTLS ON)
# Use the local cyw43_driver instead of the one in pico-sdk
if (MICROPY_PY_NETWORK_CYW43)
set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver)
endif()
# Necessary submodules for all boards.
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mbedtls)
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb)
# Include component cmake fragments
include(${MICROPY_DIR}/py/py.cmake)
include(${MICROPY_DIR}/extmod/extmod.cmake)
include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
# Define the top-level project
project(${MICROPY_TARGET})
pico_sdk_init()
include(${MICROPY_DIR}/py/usermod.cmake)
add_executable(${MICROPY_TARGET})
set(MICROPY_QSTRDEFS_PORT
${MICROPY_PORT_DIR}/qstrdefsport.h
)
set(MICROPY_SOURCE_LIB
${MICROPY_DIR}/lib/littlefs/lfs1.c
${MICROPY_DIR}/lib/littlefs/lfs1_util.c
${MICROPY_DIR}/lib/littlefs/lfs2.c
${MICROPY_DIR}/lib/littlefs/lfs2_util.c
${MICROPY_DIR}/lib/oofatfs/ff.c
${MICROPY_DIR}/lib/oofatfs/ffunicode.c
${MICROPY_DIR}/shared/netutils/dhcpserver.c
${MICROPY_DIR}/shared/netutils/netutils.c
${MICROPY_DIR}/shared/netutils/trace.c
${MICROPY_DIR}/shared/readline/readline.c
${MICROPY_DIR}/shared/runtime/gchelper_thumb1.s
${MICROPY_DIR}/shared/runtime/gchelper_native.c
${MICROPY_DIR}/shared/runtime/interrupt_char.c
${MICROPY_DIR}/shared/runtime/mpirq.c
${MICROPY_DIR}/shared/runtime/pyexec.c
${MICROPY_DIR}/shared/runtime/stdout_helpers.c
${MICROPY_DIR}/shared/runtime/softtimer.c
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
${MICROPY_DIR}/shared/timeutils/timeutils.c
${MICROPY_DIR}/shared/tinyusb/mp_cdc_common.c
${MICROPY_DIR}/shared/tinyusb/mp_usbd.c
${MICROPY_DIR}/shared/tinyusb/mp_usbd_descriptor.c
)
set(MICROPY_SOURCE_DRIVERS
${MICROPY_DIR}/drivers/bus/softspi.c
${MICROPY_DIR}/drivers/dht/dht.c
)
set(MICROPY_SOURCE_PORT
fatfs_port.c
help.c
machine_bitstream.c
machine_i2c.c
machine_pin.c
machine_rtc.c
machine_spi.c
machine_timer.c
main.c
modrp2.c
mphalport.c
mpnetworkport.c
mpthreadport.c
pendsv.c
rp2_flash.c
rp2_pio.c
uart.c
usbd.c
msc_disk.c
mbedtls/mbedtls_port.c
${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
)
set(MICROPY_SOURCE_QSTR
${MICROPY_SOURCE_PY}
${MICROPY_DIR}/shared/readline/readline.c
${MICROPY_DIR}/shared/runtime/mpirq.c
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
${MICROPY_PORT_DIR}/machine_adc.c
${MICROPY_PORT_DIR}/machine_i2c.c
${MICROPY_PORT_DIR}/machine_pin.c
${MICROPY_PORT_DIR}/machine_rtc.c
${MICROPY_PORT_DIR}/machine_spi.c
${MICROPY_PORT_DIR}/machine_timer.c
${MICROPY_PORT_DIR}/machine_uart.c
${MICROPY_PORT_DIR}/machine_wdt.c
${MICROPY_PORT_DIR}/modrp2.c
${MICROPY_PORT_DIR}/modos.c
${MICROPY_PORT_DIR}/rp2_flash.c
${MICROPY_PORT_DIR}/rp2_pio.c
${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
)
set(PICO_SDK_COMPONENTS
cmsis_core
hardware_adc
hardware_base
hardware_clocks
hardware_dma
hardware_flash
hardware_gpio
hardware_i2c
hardware_irq
hardware_pio
hardware_pll
hardware_pwm
hardware_regs
hardware_rtc
hardware_spi
hardware_structs
hardware_sync
hardware_timer
hardware_uart
hardware_watchdog
hardware_xosc
pico_base_headers
pico_binary_info
pico_bootrom
pico_multicore
pico_platform
pico_stdio
pico_stdlib
pico_sync
pico_time
pico_unique_id
pico_util
tinyusb_common
tinyusb_device
)
if (MICROPY_PY_LWIP)
target_link_libraries(${MICROPY_TARGET} micropy_lib_lwip)
target_include_directories(${MICROPY_TARGET} PRIVATE
lwip_inc
)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_LWIP=1
)
endif()
if(MICROPY_PY_BLUETOOTH)
list(APPEND MICROPY_SOURCE_PORT mpbthciport.c)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_BLUETOOTH=1
MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1
)
endif()
if (MICROPY_PY_BLUETOOTH_CYW43)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
CYW43_ENABLE_BLUETOOTH=1
MICROPY_PY_BLUETOOTH_CYW43=1
)
if (MICROPY_BLUETOOTH_BTSTACK)
target_link_libraries(${MICROPY_TARGET}
pico_btstack_hci_transport_cyw43
)
endif()
endif()
if (MICROPY_BLUETOOTH_BTSTACK)
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/btstack)
list(APPEND MICROPY_SOURCE_PORT mpbtstackport.c)
include(${MICROPY_DIR}/extmod/btstack/btstack.cmake)
target_link_libraries(${MICROPY_TARGET} micropy_extmod_btstack)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_BLUETOOTH_BTSTACK=1
MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE=\"btstack_inc/btstack_config.h\"
)
# For modbluetooth_btstack.c includes
get_target_property(BTSTACK_INCLUDE micropy_extmod_btstack INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND MICROPY_INC_CORE ${BTSTACK_INCLUDE})
endif()
if(MICROPY_BLUETOOTH_NIMBLE)
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mynewt-nimble)
if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_DIR}/lib/mynewt-nimble/nimble/host/include/host/ble_hs.h)
message(FATAL_ERROR " mynewt-nimble not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
endif()
list(APPEND MICROPY_SOURCE_PORT mpnimbleport.c)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_BLUETOOTH_NIMBLE=1
MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=0
MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1
)
target_compile_options(${MICROPY_TARGET} PRIVATE
# TODO: This flag is currently needed to make nimble build.
-Wno-unused-but-set-variable
)
include(${MICROPY_DIR}/extmod/nimble/nimble.cmake)
target_link_libraries(${MICROPY_TARGET} micropy_extmod_nimble)
get_target_property(NIMBLE_INCLUDE micropy_extmod_nimble INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND MICROPY_INC_CORE ${NIMBLE_INCLUDE})
endif()
# tinyusb helper
target_include_directories(${MICROPY_TARGET} PRIVATE
${MICROPY_DIR}/shared/tinyusb/
)
if (MICROPY_PY_NETWORK_CYW43)
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver)
if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/cyw43-driver/src/cyw43.h)
message(FATAL_ERROR " cyw43-driver not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
endif()
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_NETWORK_CYW43=1
MICROPY_PY_SOCKET_DEFAULT_TIMEOUT_MS=30000 # default socket timeout
)
if (CMAKE_BUILD_TYPE MATCHES Debug)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
CYW43_USE_STATS=1
)
endif()
list(APPEND MICROPY_SOURCE_PORT
machine_pin_cyw43.c
)
target_link_libraries(${MICROPY_TARGET}
cyw43_driver_picow
cmsis_core
)
target_include_directories(${MICROPY_TARGET} PRIVATE
${MICROPY_DIR}/lib/cyw43-driver/
)
endif()
if (MICROPY_PY_NETWORK_NINAW10)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_NETWORK_NINAW10=1
)
target_include_directories(${MICROPY_TARGET} PRIVATE
${MICROPY_DIR}/drivers/ninaw10/
)
# Enable NINA-W10 WiFi and Bluetooth drivers.
list(APPEND MICROPY_SOURCE_DRIVERS
${MICROPY_DIR}/drivers/ninaw10/nina_bt_hci.c
${MICROPY_DIR}/drivers/ninaw10/nina_wifi_drv.c
${MICROPY_DIR}/drivers/ninaw10/nina_wifi_bsp.c
${MICROPY_DIR}/drivers/ninaw10/machine_pin_nina.c
)
endif()
if (MICROPY_PY_NETWORK_WIZNET5K)
string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k)
if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/wiznet5k/README.md)
message(FATAL_ERROR " wiznet5k not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
endif()
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_NETWORK_WIZNET5K=1
WIZCHIP_PREFIXED_EXPORTS=1
_WIZCHIP_=${MICROPY_PY_NETWORK_WIZNET5K}
WIZCHIP_YIELD=mpy_wiznet_yield
)
if (MICROPY_PY_LWIP)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket
WIZCHIP_USE_MAX_BUFFER=1
)
endif()
target_include_directories(${MICROPY_TARGET} PRIVATE
${MICROPY_DIR}/lib/wiznet5k/
${MICROPY_DIR}/lib/wiznet5k/Ethernet/
)
list(APPEND MICROPY_SOURCE_LIB
${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5100/w5100.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5100S/w5100s.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5200/w5200.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5300/w5300.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/W5500/w5500.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/socket.c
${MICROPY_DIR}/lib/wiznet5k/Ethernet/wizchip_conf.c
${MICROPY_DIR}/lib/wiznet5k/Internet/DNS/dns.c
${MICROPY_DIR}/lib/wiznet5k/Internet/DHCP/dhcp.c
)
endif()
# Add qstr sources for extmod and usermod, in case they are modified by components above.
list(APPEND MICROPY_SOURCE_QSTR
${MICROPY_SOURCE_EXTMOD}
${MICROPY_SOURCE_USERMOD}
)
# Define mpy-cross flags
set(MICROPY_CROSS_FLAGS -march=armv6m)
# Set the frozen manifest file
if (MICROPY_USER_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_USER_FROZEN_MANIFEST})
elseif (NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()
target_sources(${MICROPY_TARGET} PRIVATE
${MICROPY_SOURCE_PY}
${MICROPY_SOURCE_EXTMOD}
${MICROPY_SOURCE_LIB}
${MICROPY_SOURCE_DRIVERS}
${MICROPY_SOURCE_PORT}
)
target_link_libraries(${MICROPY_TARGET} micropy_lib_mbedtls)
target_link_libraries(${MICROPY_TARGET} usermod)
target_include_directories(${MICROPY_TARGET} PRIVATE
${MICROPY_INC_CORE}
${MICROPY_INC_USERMOD}
${MICROPY_BOARD_DIR}
"${MICROPY_PORT_DIR}"
"${CMAKE_BINARY_DIR}"
)
target_compile_options(${MICROPY_TARGET} PRIVATE
-Wall
-Werror
-g # always include debug information in the ELF
)
target_link_options(${MICROPY_TARGET} PRIVATE
-Wl,--defsym=__micropy_c_heap_size__=${MICROPY_C_HEAP_SIZE}
-Wl,--wrap=dcd_event_handler
)
set_source_files_properties(
${PICO_SDK_PATH}/src/rp2_common/pico_double/double_math.c
${PICO_SDK_PATH}/src/rp2_common/pico_float/float_math.c
PROPERTIES
COMPILE_OPTIONS "-Wno-error=uninitialized"
)
set_source_files_properties(
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/dcd_rp2040.c
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/rp2040_usb.c
PROPERTIES
COMPILE_OPTIONS "-Wno-error=array-bounds;-Wno-error=unused-but-set-variable"
)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
FFCONF_H=\"${MICROPY_OOFATFS_DIR}/ffconf.h\"
LFS1_NO_MALLOC LFS1_NO_DEBUG LFS1_NO_WARN LFS1_NO_ERROR LFS1_NO_ASSERT
LFS2_NO_MALLOC LFS2_NO_DEBUG LFS2_NO_WARN LFS2_NO_ERROR LFS2_NO_ASSERT
PICO_FLOAT_PROPAGATE_NANS=1
PICO_STACK_SIZE=0x2000
PICO_CORE1_STACK_SIZE=0
PICO_PROGRAM_NAME="MicroPython"
PICO_NO_PROGRAM_VERSION_STRING=1 # do it ourselves in main.c
MICROPY_BUILD_TYPE="${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION} ${CMAKE_BUILD_TYPE}"
PICO_NO_BI_STDIO_UART=1 # we call it UART REPL
PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1
)
target_link_libraries(${MICROPY_TARGET}
${PICO_SDK_COMPONENTS}
)
if (MICROPY_HW_ENABLE_DOUBLE_TAP)
# Enable double tap reset into bootrom.
target_link_libraries(${MICROPY_TARGET}
pico_bootsel_via_double_reset
)
endif()
# todo this is a bit brittle, but we want to move a few source files into RAM (which requires
# a linker script modification) until we explicitly add macro calls around the function
# defs to move them into RAM.
if (PICO_ON_DEVICE AND NOT PICO_NO_FLASH AND NOT PICO_COPY_TO_RAM)
pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp.ld)
endif()
pico_add_extra_outputs(${MICROPY_TARGET})
pico_find_compiler(PICO_COMPILER_SIZE ${PICO_GCC_TRIPLE}-size)
add_custom_command(TARGET ${MICROPY_TARGET}
POST_BUILD
COMMAND ${PICO_COMPILER_SIZE} --format=berkeley ${PROJECT_BINARY_DIR}/${MICROPY_TARGET}.elf
VERBATIM
)
# Collect all the include directories and compile definitions for the pico-sdk components.
foreach(comp ${PICO_SDK_COMPONENTS})
micropy_gather_target_properties(${comp})
micropy_gather_target_properties(${comp}_headers)
endforeach()
# Include the main MicroPython cmake rules.
include(${MICROPY_DIR}/py/mkrules.cmake)
set(MICROPY_BOARDS_DIR "${MICROPY_PORT_DIR}/boards")
set(GEN_PINS_AF_CSV "${MICROPY_BOARDS_DIR}/rp2_af.csv")
set(GEN_PINS_PREFIX "${MICROPY_BOARDS_DIR}/rp2_prefix.c")
set(GEN_PINS_MKPINS "${MICROPY_BOARDS_DIR}/make-pins.py")
set(GEN_PINS_SRC "${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c")
set(GEN_PINS_HDR "${MICROPY_GENHDR_DIR}/pins.h")
if(EXISTS "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv")
set(GEN_PINS_BOARD_CSV "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv")
set(GEN_PINS_CSV_ARG --board-csv "${GEN_PINS_BOARD_CSV}")
endif()
target_sources(${MICROPY_TARGET} PRIVATE
${GEN_PINS_HDR}
)
# Generate pins
add_custom_command(
OUTPUT ${GEN_PINS_HDR} ${GEN_PINS_SRC}
COMMAND ${Python3_EXECUTABLE} ${GEN_PINS_MKPINS} ${GEN_PINS_CSV_ARG} --af-csv ${GEN_PINS_AF_CSV} --prefix ${GEN_PINS_PREFIX} --output-source ${GEN_PINS_SRC} --output-header ${GEN_PINS_HDR}
DEPENDS
${GEN_PINS_AF_CSV}
${GEN_PINS_BOARD_CSV}
${GEN_PINS_MKPINS}
${GEN_PINS_PREFIX}
${MICROPY_MPVERSION}
VERBATIM
COMMAND_EXPAND_LISTS
)