zephyr/cmake/modules/extensions.cmake
Torsten Rasmussen 8dc3f85622 hwmv2: Introduce Hardware model version 2 and convert devices
This is a squash of the ``collab-hwm`` branch which converts all
in-tree boards to hardware model version 2 including build system
changes, board updates and soc conversions.

This squash is a combination of the following commits:

ca214745a1 soc: Remove soc_legacy folder and move ARM Kconfig
f12cb0979f scripts: ci: check_compliance: remove HWMv1 checks
1807bcf4d4 boards: mimx8mq_evk: port to HWMv2
3ec2299c62 soc: nxp: port imx8mq SOC to HWMv2
8ea02f4e63 boards: verdin_imx8mp: convert to HVMv2
f2eb7652ce boards: phyboard_pollux: move to HVMv2
ab509a5ee0 boards: nxp: mimx8mp_evk: port M7 core to HWMv2
06ad037f99 soc: nxp: imx8mp: port M7 core to HWMv2
3f9e706859 boards: mimx8mm_phyboard: convert to HVMv2
204372d264 boards: imx8mm_evk: port CM4 core to HWMv2
f82c961a46 soc: nxp: imx8mm: port iMX8MM M4 core to HVMv2
6987b2e305 boards: pico_pi: convert to HVMv2
84484e6707 boards: warp7: convert to HWMv2
ae443d1e3c boards: meerkat96: port to HWMv2
e3629c64e6 boards: colibri_imx7d: port to HWMv2
fc835d893d soc: nxp: convert iMX7 Dual core to HWMv2
29ef2f23eb boards: udoo_neo_full: convert to HWMv2
fd49b1749e soc: nxp: convert iMX6 SoloX core to HWMv2
1e59b7a3fd soc: nxp: imxrt11xx: only set
           CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION for M7
69bb0eb258 hwmv2: MAINTAINERS: Fix NXP maintainer yaml
1c4458890f boards: firefly: roc_rk3568_pc: Fix SMP configuration
651a4370ad boards: Fix variants and revisions
196cfda66d tests/samples: Drop default revision identifiers
6ec6b1d75a boards: Drop revision from twister identifiers for
           default revisions
b774cdd59f scripts: utils: board_v1_to_v2: drop board_legacy prefix
7aa36e6640 boards: riscv: esp32c3_luatos_core: make usb variant
fe25709a9c twister: add unit_testing soc and board
f88f211b4e scripts: ci: check_compliance: improve the "not sorted"
           command
b21a455dfb bluetooth: controller: Fix openisa checks
fdc76c48a7 workflow: compliance: Add rename limit
14ecafc67d dts: bindings: vendor-prefixes: Sort entries
dbc366c3c7 soc: nxp: lpc: Move wrong configurations
8e02c08f96 maintainers: Fix invalid paths
b1b85e2495 boards: up: Fix spaces
58cc4013b3 maintainers: Fix xen path
66ce5c0b09 boards/soc: Add missing copyright headers
bb47243254 boards: qemu: x86: Remove pointless file
2e816a8a3a samples: tests: update esp32-based board naming
9aeab17139 samples: tests: remove platform_exclude of esp32 boards
a4fe97b9de boards: shields: m5stack_core2_ext: update board name
615fcab94a samples: ipm_esp32: fix board labels and skip testing
7752f69b7f boards: legacy: remove index entry for xtensa/riscv
           boards.
3eba827956 MAINTAINERS: update Espressif entries
914362bbd5 boards: xtensa: yd_esp32: Convert to v2
a62278fd23 boards: xtensa: xiao_esp32s3: Convert to v2
b6a11ccec4 boards: xtensa: olimex_esp32_evb: Convert to v2
c1067c16d2 boards: xtensa: odroid_go: Convert to v2
b8340b0109 boards: xtensa: m5stickc_plus: Convert to v2
9d81e417be boards: xtensa: m5stack_stamps3: Convert to v2
c296672720 boards: xtensa: m5stack_core2: Convert to v2
fada12aa9d boards: xtensa: m5stack_atoms3_lite: Convert to v2
fe37ebac1e boards: xtensa: m5stack_atoms3: Convert to v2
d32828fe6a boards: xtensa: kincony_kc868_a32: Convert to v2
5afba7855b boards: xtensa: heltec_wireless_stick_lite_v3: Convert to
           v2
ca48c17723 boards: xtensa: heltec_wifi_lora32_v2: Convert to v2
db1fd4d229 boards: xtensa: esp32s3_luatos_core: Convert to v2
a78b2552eb boards: xtensa: esp32s3_devkitm: Convert to v2
cc96061d96 boards: xtensa: esp32s2_saola: Convert to v2
ed854e05d1 boards: xtensa: esp32s2_lolin_mini: Convert to v2
4fa1ae8110 boards: xtensa: esp32s2_franzininho: Convert to v2
5543040a18 boards: xtensa: esp_wrover_kit: Convert to v2
2335ae79b3 boards: xtensa: esp32_ethernet_kit: Convert to v2
f910b7ad4f boards: xtensa: esp32_devkitc_wrover: Convert to v2
32104db555 boards: xtensa: esp32_devkitc_wroom: Convert to v2
e23a41200d boards: riscv: icev_wireless: Convert to v2
3c670e4e53 boards: riscv: xiao_esp32c3: Convert to v2
fc7c6a060b boards: riscv: stamp_c3: Convert to v2
22c2edb89c boards: riscv: esp32c3_luatos_core: Convert to v2
0a96dcb778 boards: riscv: esp32c3_devkitm: Convert to v2
be1ee1c446 vendors: update vendors lists
5e6c62137f soc: espressif_esp32: Port to HWMv2
037a3b52a4 boards: Raspberry Pi pico pwm led adjustment
7277cae6fa samples: blinky_pwm: enable pwm_leds in rpi_pico overlay
da3e49d34e boards: nxp: update selection of
           FLASH_MCUX_FLEXSPI_XIP_MEM_TARGET
bc8424dd3b soc: nxp: imxrt: move FLASH_MCUX_FLEXSPI_XIP_MEM_TARGET
           to SOC level
041cb52939 soc: brcm: bcm_vk: Rename to bcnvk
576b43a95c soc: Fix SOC_FAMILY name mismatches
e8f3e6494d hwmv2: boards: intel: adsp: Fix runner after paths
           renamed
550399e927 boards: weact: stm32g431_core: Add wrongly deleted file
           back
08708c909e tests: drivers: flash: Renamed missed board rename
06dac41e68 hwmv2: Convert Seagate Faze board to hwmv2
dd8f842b40 hwmv2: nxp: update MAINTAINER paths for hwmv2
b4d1c04978 hwmv2: lpc: updated overlay and conf files in samples and
           tests
067c69089e boards: nxp: convert lpcxpresso55s69 to hwmv2
097205b40a hwmv2: Global fix of lpc54114_m4 overlay and conf files
d8cfa6fb29 boards: nxp: convert lpcxpresso54114 to hwmv2
c29ed228c6 boards: nxp: convert lpcxpresso55s36 to hwmv2
88cfd3d6ac boards: nxp: convert lpcxpresso55s28 to hwmv2
ad30c940ee boards: nxp: convert lpcxpresso55s16 to hwmv2
9e5a10ec80 boards: nxp: convert lpcxpresso55s06 to hwmv2
5650c83268 boards: nxp: convert lpcxpresso51u68 to hwmv2
82cf44be45 boards: nxp:  convert lpcxpresso11u68 to hwmv2
1a9c405a6f soc: nxp: convert LPC SOC family to hardware model V2
f2b536d253 boards: intel: doc: hwmv2: Fix some renamed paths
5ee6058710 samples/tests: Use board revisions
b76687602f boards: Add yaml files for boards missing revisions
32ae4918d0 boards: nordic: Fix board names
cc1dabca65 MAINTAINERS: Update for renamed folders
a37ddce659 soc: xilinx: Rename to xlnx
a1393a07f6 soc: xenvm: Rename to xen
813ed00f67 soc: raspberry_pi: Rename to raspberrypi
71317d6798 soc: cadence: Rename to cdns
8cb0c51ec6 soc: broadcom: Rename to brcm
2b9db15c69 soc: andes: Rename to andestech
0101216ce1 soc: altera: Rename to altr
4b4c3ca65d boards: wurth_elektronik: Rename to we
cdc3ef499f boards: ublox: Rename to u-blox
cabdd4ad05 boards: space_cubics: Rename to sc
4b5bd7ae8a boards: seeed_studio: Rename to seeed
a992785ceb boards: raspberry_pi: Rename to raspberrypi
3c1cdc20fe boards: laird_connect: Rename to lairdconnect
291c7cde2b boards: cadence: Rename to cdns
95db897526 boards: broadcom: Rename to brcm
0a47b94879 boards: beagleboard: Change to beagle
9f9f221c24 boards: andes: Rename to andestech
e7869ca38a boards: altera: Rename to altr
bf2fb5eca3 various: Change SOC_FAMILY_NRF to SOC_FAMILY_NORDIC_NRF
e25730ba56 modules: tf-m: Rename from nordic_nrf to nordic
9e3466606a boards: nordic_nrf: Rename to nordic
09a398dcc8 soc: nordic_nrf: Rename to nordic
cb8ffc74f8 boards: renode: Add documentation index
2291ff4b55 boards: arm: riscv32_virtual: Convert to v2
484b7f1996 soc: riscv_renode_virtual: Port to HWMv2
cc5c2fb0c7 soc: raspberry_pi: Fix SOC_SERIES and SOC mismatch
59cb580513 soc: arm: designstart: Fix SOC_SERIES and SOC mismatch
aa9e0de7af samples: Fix invalid links
a1480cf1cf maintainers: Fix paths
0d719e004b boards: Update documentation links
eb5c3e6f79 boards: wurth_elektronik: Drop duplicate prefix
a34a3640b7 boards: waveshare: Drop duplicate prefix
cf50e950e7 boards: weact: Drop duplicate prefix
737cfb548f boards: sparkfun: Drop duplicate prefix
505494c97a boards: segger: Drop duplicate prefix
4eaf69f37a boards: ruuvi: Drop duplicate prefix
a1335caeae boards: ronoth: Drop duplicate prefix
a9f7f30bf6 boards: raytac: Drop duplicate prefix
80db4c81b3 boards: qemu: Drop duplicate prefix
433d7e9976 boards: particle: Drop duplicate prefix
4ea79d19e7 boards: olimex: Drop duplicate prefix
fd4ae6f6a8 boards: mikroe: Drop duplicate prefix
36080549bd boards: khados: Drop duplicate prefix
169bf8ae1d boards: intel: Drop duplicate prefix
25f04d5222 boards: holyiot: Drop duplicate prefix
11c2af0de8 boards: google: Drop duplicate prefix
d5128f4016 boards: ebyte: Drop duplicate prefix
44fbc68cad boards: dragino: Drop duplicate prefix
f7fe431b44 boards: contextual_electronics: Drop duplicate prefix
9094fea63b boards: circuit_dojo: Drop duplicate prefix
b632acc1fc boards: blue_clover: Drop duplicate prefix
1a3316ebdc boards: bbc: Drop duplicate prefix
71c0344f8c boards: arduino: Drop duplicate prefix
f0176fc25f boards: altera: Drop duplicate prefix
36b920ed0f boards: adi: Drop duplicate prefix
22520368d9 boards: adafruit: Drop duplicate prefix
296acfb2bc boards: actinius: Drop duplicate prefix
55063380b7 boards: 96boards: Drop duplicate prefix
1f93394b55 boards: nxp: convert mimxrt595_evk to hardware model v2
e7a4fd2ec1 soc: nxp: rt5xx: convert RT5xx SOC to HWMv2
01942f1d11 twister: normalize platform name when storing files/data
477c8b84dd twister: tests: test with slashes in platform names
64e3e816c4 soc: Add include guards
3a7aa2fa49 gitignore: update the compliance file list
84e1c17ad9 scripts: ci: check_compliance: add a check for board yml
           file
a90f53ad57 boards: sync up the vendor tags and vendor-list
af9aa65299 dts: vendor-prefixes: add keep-sorted markers
50f0bf05a3 dts: vendor-prefixes: sort the vendor list
a10b614aa4 dts: vendor-prefixes: ensure all prefixes are lowercase
5abe735e93 manifest: update SOF sha for NXP HWMv2
9ab8f64ca9 modules: rename SOC_FAMILY_IMX
483ff8dd4d modules: mcux: remove SOC_FAMILY_NXP_ADSP
f113dd5342 samples: update board name
39b31287d9 boards: nxp: Convert i.MX ADSP boards to hardware model
           v2
1511e356a2 soc: nxp: Port i.MX ADSP family to hardware model v2
c91e25ab47 soc: mec: rename all mec1501x reference to mec15xx
1c231fd939 hwmv2: boards: Convert IMXRT boards
417cff1e60 hwmv2: soc: Port IMXRT family to HWMV2
28d4e41b1b hwmv2: clean up arm64 soc and board empty directory
2b520f83cb hwmv2: port NXP SoC LS1046A to V2
bf7899c645 hwmv2: port nxp_ls1046ardb board to V2
33f7b61866 samples/tests: Rename numaker boards
8f20ea6e93 boards: nuvoton: numaker_pfm: Split into 2 boards
7cf4ff43a1 drivers: pinctrl: imx: align with hwm v2
c68e1fea4e drivers: clock_control: ccm_rev2: align with hwm v2
           update
3b49014a0f hwmv2: move imx8mn EVK board to V2
14f344eeab hwmv2: move imx8mp EVK board to V2
40f3f8f22d hwmv2: move imx8mm EVK board to V2
10bf79ea51 hwmv2: move imx8m soc for a-core to V2
8727d5ca80 hwmv2: move imx93 EVK board to V2
c81ef01563 hwmv2: move imx93 soc to V2
5836c1b699 modules: mcux: introduce CONFIG_MCUX_CORE_SUFFIX
338f6f2bf1 doc: update board porting guide to match new hardware
           model
9639a1b5dc soc: silabs: drop useless defconfigs
981807444e soc: silabs: introduce SOC_GECKO_SDID
5d07e82485 soc: silabs: SOC_FAMILY_* replace SOC_GECKO_SERIES*
2fd081ac86 soc: silabs: align comments with soc tree
66d425f571 soc: silabs: split in families
5bd38f47a9 arch: arch: kconfig: Fix wrong placement of endmenu
00c6ef25be tests/samples: Rename overlay files for renamed boards
0c639b8378 boards: Fix bools and selections
c2ef907d1d drivers: flash: it8xxx2: Add missing Kconfigs
553de2ebc9 soc: ite: ec: it8xxx2: Fix SOC_SERIES being in wrong file
b8ec0080c2 boards: Documentation link fixes
eb7025e50f tests: Update board names for hwmv2
10ef3d4bd2 boards: silab: Add documentation index file
ba9fdaa1d6 boards: arm: efr32_radio: Convert to v2
86c8d4a0ca boards: arm: efm32pg_stk3402a: Convert to v2
575ac5cafb manifest: Update hal_silabs
87b2907304 boards: arm: efr32_thunderboard: Convert to v2
14b30055ab boards: arm: efr32mg_sltb004a: Convert to v2
0012bfc15d boards: arm: efr32xg24_dk2601b: Convert to v2
f526225ead boards: arm: efm32wg_stk3800: Convert to v2
19e7df29df boards: arm: efm32pg_stk3401a: Convert to v2
0bd7d963d6 boards: arm: efm32hg_slstk3400a: Convert to v2
795a90f9bf boards: arm: efm32gg_stk3701a: Convert to v2
43d5540be7 boards: arm: efm32gg_slwstk6121a: Convert to v2
065148d856 boards: arm: efm32gg_sltb009a: Convert to v2
1dc9a8aa17 soc: silabs_exx32: Port to HWMv2
763571e878 tests: Expand names
dae301b8a3 boards: xen: xenvm: Expand name
19e60eef36 boards: qemu: qemu_cortex_a53: Expand names
a0a7c30f28 soc: intel: intel_adsp: Fix issues
df9a4223fe scripts: ci: introduce soc name check in check_compliance
ed401abaff soc: emsdsp: align SoC name defined in soc.yml to Kconfig
           SOC setting
fc78e5eaa4 MAINTAINERS: update RISC-V arch area paths
4e586958ff boards: convert QEMU RISC-V 64 bit board to Zephyr HWMv2
f4c31a2b86 boards: convert QEMU RV32E board to Zephyr HWMv2
5b2ffc652b boards: convert QEMU RISC-V 32 bit board to Zephyr HWMv2
5db061a4c6 soc/riscv: convert the QEMU virt RISCV-32 SoC to HWMv2
6547845e9d boards: convert SparkFun RED-V Things Plus to Zephyr
           HWMv2
95a1f96399 boards: convert SiFive HiFive Unmatched to Zephyr HWMv2
e563eb0a62 soc/sifive/sifive_freedom: add SiFive Freedom FU740 SoC
8914bc58b6 boards: convert SiFive HiFive Unleashed to Zephyr HWMv2
7e8de1e781 soc/sifive/sifive_freedom: add SiFive Freedom U540 SoC
bfcc2ed18f boards: convert SiFive HiFive1 Rev. B to Zephyr HWMv2
330fc38f9f boards: convert SiFive HiFive1 to Zephyr HWMv2
b9e06f4c38 soc/sifive/sifive_freedom: add SiFive Freedom E310 SoC
4b90b30b9d scripts: west_commands: completion: Add hwmv2 complete to
           fish
0f6842e2fa scripts: west_commands: completion: Add hwmv2 complete to
           zsh
b2af1e1737 scripts: west: list_boards: Fix hwmv2 output
686a4b78b8 scripts: west_commands: completion: Add hwmv2 complete to
           bash
396b6bb856 soc: nxp: fix typo in SoC name
765299c627 soc: broadcom: align SoC names defined in soc.yml to
           Kconfig SOC setting
7efd46eb41 soc: arm: align SoC names defined in soc.yml to Kconfig
           SOC setting
505cbc5c42 soc: mec: align SoC names defined in soc.yml to Kconfig
           SOC setting
951a140701 soc: ti: define SOC name in Kconfig
a795d28810 snippets: Initial HWMv2 support
f9a957e6f6 boards: nordic: nrf9160dk: Fix missing nrf52840 config
df994e7ee8 soc: xilinx: zync7000: Remove xilinx from soc series name
8dfabd56ca soc: cypress: Add protection guard to file
447b951593 tests: kernel: tickless: Remove old board name
bad5dfa71f boards: nordic: nrf5340dk: Fix board names
ad2e863f39 soc: atmel: Use new family prefix
3f08e714b2 soc: intel_adsp: hwmv2: Align SOC_SERIES_INTEL_ACE name
           and value
6734597a76 soc: intel_adsp_cavs: hwmv2: Align SOC_SERIES name and
           value
2908af0bcc boards: nrf51dk/dongle: change SoC to nRF51822
d1ceb29fca soc: align CONFIG_SOC values to match soc.yml names
4768ccaf70 tests: drivers: gpio: gpio_api_1pin: exclude hifive1
ebdb0879ad boards: nxp: s32z2xxdc2: convert to hwmv2
ae82580d08 boards: nxp: mr_canhubk3: convert to hwmv2
c5f0defbae boards: nxp: ucans32k1sic: convert to hwmv2
1e46cabce6 soc: nxp: convert NXP S32 family to hwmv2
f2f85133f2 soc: stm32: Rename series path
86642f4e78 soc: stm32: Rename Kconfig SOC_SERIES symbols
c61e807896 soc: stm32: Cleanup Kconfig.defconfig files
ca46c8abc9 tests: Fix board names
fbfed5f48f maintainers: Update synopsys entries
8cd8b1cc47 boards: synopsys: Add documentation index
6f6cc57a04 boards: arc: hsdk4xd: Convert to v2
c4c14a54ca soc: snps_arc_hsdk4xd: Port to HWMv2
06c2054e5c boards: arc: iotdk: Convert to v2
ff0e0fce1b soc: snps_arc_iot: Port to HWMv2
334264c46a boards: arc: emsdp: Convert to v2
8b947a0e91 soc: snps_emsdp: Port to HWMv2
990417bbde tests: Update board names for hwmv2
e12719154a boards: arc: em_starterkit: Convert to v2
437a430fbe soc: snps_emsk: Port to HWMv2
f93387f968 boards: arc: hsdk: Convert to v2
1cf2498b13 soc: snps_arc_hsdk: Port to HWMv2
47abe81256 boards: arc: nsim: Convert to v2
1e33786dc4 soc: snps_nsim: Port to HWMv2
7f081914db boards: arc: qemu_arc: Convert to v2
bc97349dbd soc: snps_qemu: Port to HWMv2
a9902ff58e boards: Use zephyr_file for file links
126e1a4e72 boards: Fix invalid documentation links
899f0257c3 boards: stm32wb: Restore missing .defconfig files
790c10b1ee soc: x86/atom: imply mmu, do not select it
faee62088d boards: x86: remove qemu_x86_tiny_768
c34d186a57 x86: atom: remove soc.h with unused content
1be3a9e9d3 x86: remove legacy ia32, use atom instead
60e6b400f9 boards: qemu: move qemu_x86 -> x86
c4fbac27e8 boards: infineon: Add documentation index
b4dd29a9c4 maintainers: Update paths for hwmv2
380f5fdb2b boards: cypress: Add documentation index
9de981be05 boards: arm: xmc47_relax_kit: Convert to v2
6394e8a348 boards: arm: xmc45_relax_kit: Convert to v2
04dbf17e19 soc: xmc_4xxx: Port to HWMv2
c9731f1bce boards: arm: cy8cproto_063_ble: Convert to v2
53d41869d1 boards: arm: cy8cproto_062_4343w: Convert to v2
46c4f01427 boards: arm: cy8ckit_062s4: Convert to v2
d285e19cf2 boards: arm: cy8ckit_062_wifi_bt: Convert to v2
2bebd7298c boards: arm: cy8ckit_062_ble: Convert to v2
af243274c2 soc: psoc6 and psoc_6: Port to HWMv2
105a2bae84 cmake: modules: boards: Fix board deprecation for HWMv2
dca54e000a cmake: modules: boards: Enhance board aliases for HWMv2
fc314e8e3f cmake: modules: boards: Fix BOARD_ALIAS
9a7c2ce6d5 soc: gaisler: Move Kconfig file
1ac56d0501 soc: soc_legacy: mips: Remove out file
c054381a7a boards: adjust few boards/ paths
4d93b8d9fd boards: convert all microchip MEC boards to hwmv2
ab2fcb1245 soc: convert microchip_mec to hwmv2
ead4b57a7b soc: arm64: intel_socfpga: hwmv2: Rename SoCs
d4c143d306 MAINTAINERS: intel_socfpga: Adjust to HWMv2 move
70a66ac03a boards: arm64: intel_socfpga: Move boards to
           subdirectories
8a85c07799 boards: arm64: intel_socfpga_agilex5_socdk: move to HWMv2
8c253a99fc boards: arm64: intel_socfpga_agilex_socdk: move to HWMv2
ab883b8019 soc: arm64: intel_socfpga: Move and convert to HWMv2
7c8b7a153b soc: arm: intel_socfpga_std: Rename with HWMv2
8dc2b911f6 soc: board: intel_socfpga_std: Align names to 'Cyclone V'
402366117a soc: arm: intel_socfpga_std: Align board subdirectory
f0a8d12745 boards: arm: cyclonev_socdk: Move to HWMv2
2271f17a86 soc: arm: intel_socfpga_std: Move and convert to HWMv2
841c2a9d99 boards: riscv: beaglev_fire: Convert to v2
3b314531ab boards: riscv: mpfs_icicle: Convert to v2
d4ea2bf70b boards: riscv: m2gl025_miv: Convert to v2
5256e9fcc3 soc: microchip_miv: Port to HWMv2
18e5cf1d51 maintainers: Update path for hwmv2
eab8628f98 boards: arm: qemu_cortex_m3: Convert to v2
1532f2fee1 soc: ti_lm3s6965: Port to HWMv2
430ca6a475 maintainers: Update ambiq paths
a9b9b41b91 boards: ambiq: Add index
db0271ecbb boards: arm: apollo4p_blue_kxr_evb: Convert to v2
957e2b2061 boards: arm: apollo4p_evb: Convert to v2
5a90a44454 soc: ambiq: Port to HWMv2
a20c113fbd boards: nxp: convert ip_k66f to hwmv2
34e3852a54 boards: nxp: convert usb_kw24d512 to hwmv2
20ad604de6 boards: nxp: convert twr_kv58f220m to hwmv2
2e2a7b7656 boards: nxp: twr_ke18f: convert to hwmv2
f7dcc2eb5e boards: nxp: convert rddrone_fmuk66 to hwmv2
b58e90a2e9 boards: nxp: convert hexiwear to hwmv2
aae6e9e454 boards: nxp: frdm_kw41z: convert to hwmv2
1d3baac2d6 boards: nxp: convert frdm_kl25z to hwmv2
3b1d21483f boards: nxp: frdm_k82f: port to hwmv2
6046e6ded9 boards: nxp: port frdm_k64f to hwmv2
0a7bf9fd79 boards: nxp: port frdm_k22f to hwmv2
dce697c823 boards: nxp: add toctree placeholder
666a353409 soc: nxp: kinetis: convert kinetis SOC family to hardware
           model V2
89f0a6034b maintainers: Update paths for renesas boards/socs
004bd43c48 tests/samples/snippets: Update board names for hwmv2
a6d756923d boards: arm and arm64: rcar_h3ulcb: Convert to v2
3801216b8d boards: arm64: rcar_salvator_xs_m3: Convert to v2
b7cc30aaea boards: arm: rcar_h3_salvatorx_cr7: Convert to v2
866427ea29 boards: arm: arduino_uno_r4: Convert to v2
2689b3f0ee soc: ra: Port to HWMv2
e7ebc727c8 boards: arm: da1469x_dk_pro: Convert to v2
903265b2bb boards: arm: da14695_dk_usb: Convert to v2
529a78ed51 soc: smartbond: Port to HWMv2
97cf636ae0 boards: arm: rcar_spider_cr52: Convert to v2
6d0c53f3a1 soc: rcar: Port to HWMv2
44e0aa0668 soc: renesas: rzt2m: Move folder structure for more SoCs
85238fc205 boards: misc: Fixed STM32 based boards doc links
dffc08af56 boards: riscv: niosv_m: move and convert to HWMv2
545093abe4 boards: riscv: niosv_g: move and convert to HWMv2
ecfa192f1b soc: riscv: intel_niosv: move and convert to HWMv2
fd1e8cdc30 hwmv2: sof: intel_adsp: submanifest provisional link
8bf067e625 doc: boards: intel_adsp: Re-order pages
4833275ccd MAINTAINERS: intel_adsp: Adjust to HWMv2 move
b9a70e5ea2 soc: intel_adsp: tools: pylint compliance workaround
18c70cc4bf hwmv2: tests: boards: intel_adsp: Adjust board names
ca52baf9de hwmv2: boards: intel_adsp: Overhaul board configurations
d1b3bcce64 soc: boards: xtensa: intel_adsp_ace: Rename with HWMv2
f362a8ae2c doc: soc: boards: intel_adsp_cavs25: Rename with HWMv2
51dee5da92 tests: samples: boards: intel_adsp_cavs25: Rename with
           HWMv2
e66c35e0d0 boards: xtensa: intel_adsp_cavs25: Rename board with
           HWMv2
d1491a4810 soc: boards: xtensa: intel_adsp_cavs25: Rename with HWMv2
fa0fca79c4 scripts: west: runners: intel_adsp: Adjust path to HWMv2
acd18bfaf7 boards: xtensa: intel_adsp_ace20_lnl: move and convert to
           HWMv2
546c94b958 boards: xtensa: intel_adsp_ace15_mtpm: move and convert
           to HWMv2
8aab718c3e boards: xtensa: intel_adsp_cavs25_tgph: change to board
           variant
30f17424a4 boards: xtensa: intel_adsp_cavs25: move and convert to
           HWMv2
35a97cb524 soc: xtensa: intel_adsp: HWMv2 workaround for SOF config
fdc20fdff6 soc: xtensa: intel_adsp: move and convert to HWMv2
22dc2b6391 cmake: improved board handling for revisions
2f1e33a2e6 cmake: improve arch error message for invalid arch
           selection
c47c37d3db sample: basic: blinky_pwm: Exclude rpi_pico w variant
7a788b9a18 boards: raspberry_pi: rpi_pico: Use full name for w
           variant
7046b92d41 tests: atmel_sam: adc: Fix sam4e_xpro adc build
253ee9638c tests: atmel_sam0: Update platform name
ccb4c63324 samples: atmel_sam0: Update platform name
2d4acf9230 boards: arduino_nano_33_iot: Convert to HWMv2
a60d28969a boards: arduino_mkrzero: Convert to HWMv2
0409e51d3f boards: arduino_zero: Convert to HWMv2
1b2528df1b boards: wio_terminal: Convert to HWMv2
af1096e7ca boards: ev11l78a: Convert to HWMv2
0b1db9c53d boards: adafruit_trinket_m0: Convert to HWMv2
e9874671e2 boards: adafruit_itsybitsy_m4_express: Convert to HWMv2
ba6c014071 boards: adafruit_grand_central_m4_express: Convert to
           HWMv2
33ad4a51ca boards: adafruit_feather_m0_lora: Convert to HWMv2
9812f3d54e boards: adafruit_feather_m0_basic_proto: Convert to HWMv2
c76b1fbeca boards: serpente: Convert to HWMv2
649789e433 boards: seeeduino_xiao: Convert to HWMv2
6b3bdb7364 boards: same54_xpro: Convert to HWMv2
93dda5ee4b boards: samr34_xpro: Convert to HWMv2
e48e1f5d5b boards: samc21n_xpro: Convert to HWMv2
f11cf73df1 boards: saml21_xpro: Convert to HWMv2
ac73ed6dcd boards: samd20_xpro: Convert to HWMv2
0fdbe3552e boards: samd21_xpro: Convert to HWMv2
854cff3905 boards: samr21_xpro: Convert to HWMv2
a87ea5bc0a soc: atmel: sam0: Port to HWMv2
706e5d27cd boards: riscv: neorv32: Convert to v2
d1edcdd088 soc: neorv32: Port to HWMv2
0f7add89ca boards: native_sim/posix: Add 64bit versions as variants
b6edad8d68 soc: soc_legacy: remove the arm/st_stm32 folder
c58e0822a6 boards: Convert nucleo_f207zg to HWM v2
b987093a80 soc: v2: stm32: Migrate STM32F2 series
2096fd4652 samples: bluetooth: hci_uart: Fix wrongly converted board
           names
830f9c5a82 MAINTAINERS: Update Atmel entries
527cd9d8cd CODEOWNERS: Update Atmel entries
83af7d0c1c samples: atmel_sam: Update platform name
fd9b84d457 tests: atmel_sam: Update platform name
3c72fe863c boards: arduino_due: Convert to HWMv2
37dfacbf9e boards: RoboKit1: Convert to HWMv2
1108d7b0ed boards: sam_v71_xult: Convert to HWMv2
bed44a5c28 boards: sam_e70_xplained: Convert to HWMv2
40448c5a9f boards: sam4s_xplained: Convert to HWMv2
31273692c0 boards: sam4l_ek: Convert to HWMv2
35b5d33ef0 boards: sam4e_xpro: Convert to HWMv2
3b84b9910a soc: atmel: Port SAM family to HWMv2
da00d0e7b9 boards: Convert nucleo_wba55cg to HWM v2
fb2103f89e boards: Convert nucleo_wba52cg to HWM v2
1f9a533fbc soc: st: stm32: Migrate STM32WBA series
3f92f65b28 boards: fix documentation for alientek and blues boards
7646b74aaf boards: stm32l4: doc: add zephyr_file to defconfig path
fea54ddcd9 boards: Convert adi_eval_adin2111ebz to HWM v2
d47f1878b1 boards: Convert adi_eval_adin1110ebz to HWM v2
ae42be236b boards: Convert swan_r5 to HWM v2
83bd1a9ecc boards: Convert stm32l4r9i_disco to HWM v2
39c26f09ed boards: Convert stm32l496g_disco to HWM v2
29d03c970b boards: Convert stm32l476g_disco to HWM v2
74acec315c boards: Convert sensortile_box to HWM v2
fee6d8676e boards: Convert pandora_stm32l475 to HWM v2
008b5d9392 boards: Convert nucleo_l4r5zi to HWM v2
24e357d623 boards: Convert nucleo_l4a6zg to HWM v2
2c5f9dcce0 boards: Convert nucleo_l496zg to HWM v2
4da061646f boards: Convert nucleo_l476rg to HWM v2
15956a69b8 tests: drivers: flash: stm32: update platform name
80324f7707 boards: Convert nucleo_l452re_p to HWM v2
9893e0d111 boards: Convert nucleo_l452re to HWM v2
46f92b227b boards: Convert nucleo_l433rc_p to HWM v2
ed5d1bb4cd boards: Convert nucleo_l432kc to HWM v2
325f95ec20 boards: Convert nucleo_l412rb_p to HWM v2
d055676307 boards: Convert disco_l475_iot1 to HWM v2
c7a415d92c boards: Convert b_l4s5i_iot01a to HWM v2
d15144f582 soc: st: stm32: Migrate STM32L4 series
a63ff71bcb boards: nrf_bsim: Add new nrf5340 board definitions
b53c6f412c boards: nrf_bsim: Remove redundant option setting
83eb4fc069 MAINTAINERS: intel_ish: Adjust to HWMv2 move
715685b19f boards: x86: intel_ish: move and convert intel_ish boards
           to HWMv2
5b9ef94106 soc: x86: intel_ish: move and convert to HWMv2
12b297707a boards: Convert stm32wb5mmg to HWM v2
cdcea932bc boards: Convert stm32wb5mm_dk to HWM v2
0a3ae2b223 boards: Convert nucleo_wb55rg to HWM v2
20b4ce17d5 soc: st: stm32: Migrate STM32WB series
47c65400d6 soc: st: stm32: fix stm32l0 family
59ec56f9e6 boards: Convert stm32h573i_dk to HWM v2
dc5977dbba boards: Convert nucleo_h563zi to HWM v2
a6e4928543 soc: st: stm32: Migrate STM32H5 series
99f248e048 soc: stm32u5: Fix references after conversion to hw
           modelv2
15f16834e6 boards: Convert stm32u5a9j_dk to HWM v2
c1ee449ef1 boards: Convert sensortile_box_pro to HWM v2
db4deddf9d boards: Convert nucleo_u5a5zj_q to HWM v2
2fd3ed43d2 boards: Convert nucleo_u575zi_q to HWM v2
902fceb173 boards: Convert b_u585i_iot02a to HWM v2
d716ca1a10 soc: st: Migrate stm32u5 series to new hw model
b7abc89428 hwmv2: boards: x86: doc: Adjust common docs to new
           locations
69b334f54b MAINTAINERS: Change paths to native and nrf*bsim boards
614611a528 boards: nrf*_bsim: Convert to HW model v2
5821b9ec2e board: native_sim/posix: Convert to hwmv2
04cbad174e soc: native: Convert to HWMv2
24ca0febfc boards: nrf_bsim: Fix path to pinctrl_soc.h
9a32559a2d cmake: FindHostTools: Fix for hwmv2 for host based
           targets
c4b11e0251 boards: longan_nano: port to HWMv2
97edd05be3 boards: gd32vf103c_starter: port to HWMv2
9cf624c410 boards: gd32vf103v_eval: port to HWMv2
b40bf25e5e soc: gd_gd32: reorganize folders
71600d7e95 soc: gd_gd32: move pinctrl_soc.h content back to soc
           folder
2bd84a1bc5 soc: gd_gd32: port gd32vf103 series to HWMv2
9dc342143b boards: doc: fix a bunch of broken reference
10392d693d doc: boards: split out shields
b2def8ed3a boards: acrn: fix title
bf7d3efe78 boards: riscv: tlsr9518adk80d: Convert to v2
c579770e1d soc: telink_tlsr: Port to HWMv2
9131540109 soc: stm32h7: Couple of tests fixes following migration
2efcefc089 boards: Convert stm32h7b3i_dk to HWM v2
d9b295a85b boards: Convert stm32h750b_dk to HWM v2
a2f56bdcd5 boards: Convert stm32h747i_disco to HWM v2
00314155df boards: Convert stm32h735g_disco to HWM v2
b08819dff7 boards: Convert nucleo_h7a3zi_q to HWM v2
56456c16e5 boards: Convert nucleo_h753zi to HWM v2
91f9198dc4 boards: Convert nucleo_h745zi_q to HWM v2
96f1bafbf9 boards: Convert nucleo_h743zi to HWM v2
b290f25baa boards: Convert nucleo_h723zg to HWM v2
9fbe6bf191 boards: Convert fk7b0m1_vbt6 to HWM v2
44bcfe57c7 boards: Convert arduino_portenta_h7 to HWM v2
4c86af7eae boards: Convert arduino_opta_m4 to HWM v2
b4f852f738 boards: Convert arduino_giga_r1 to HWM v2
bac9789264 soc: st: Migrate stm32h7 series to new hw model
a954e1722d boards: stm32l0: Cleanup board _defconfig files after
           migration
7e8515b241 boards: Convert ronoth_lodev to HWM v2
25246c21ef boards: Convert nucleo_l073rz to HWM v2
09396eb2e6 boards: Convert nucleo_l053r8 to HWM v2
70c004fd83 boards: Convert nucleo_l031k6 to HWM v2
e3daa98e79 boards: Convert nucleo_l011k4 to HWM v2
a2de60c6da boards: Convert dragino_nbsn95 to HWM v2
e877ce9cec boards: Convert dragino_lsn50 to HWM v2
2b50218c23 boards: Convert b_l072z_lrwan1 to HWM v2
4a65f55916 soc: st: Migrate stm32l0 series to new hw model
cc6e6be01f boards: fix few leftover ITE board references
a837303268 soc: stm32: Protect Kconfig symbols by SOC_FAMILY_STM32
88e5959f17 hwm2: Fix unit_testing: it is also a legacy board by now
95e06e8663 cmake: Fix uses of old SOC path
d517d3cc24 soc: set linker script for ra4m1
68f9aeddab soc: ite: add SOC_SERIES_ITE_IT8XXX2 guards around ITE
           options
ccf4f48f01 boards: convert ite boards to hwmv2
4a6e286a3b soc: convert ite_ec to hwmv2
12e375f826 doc: handle arch / soc / board docs in new hardware model
b4db917de9 boards: Add documentation index files
d6e0d27efe samples: bluetooth: hci_uart: Fix wrong named files
bc16a7a727 tests: Update board names for hwmv2
2834883843 boards: riscv: rv32m1_vega: Convert to v2
9c68231ba9 soc: openisa_rv32m1: Port to HWMv2
986e9619fd soc: starfive_jh71xx: Port to HWMv2
e82932e787 boards: riscv: litex_vexriscv: Convert to v2
cb9339f88f soc: litex_vexriscv: Port to HWMv2
1cd4c34654 boards: riscv: opentitan_earlgrey: Convert to v2
92eadf06b8 soc: opentitan: Port to HWMv2
a8659e170b boards: riscv: titanium_ti60_f225: Convert to v2
359133d725 soc: efinix_sapphire: Port to HWMv2
6d466429ed soc: soc_legacy: riscv: litex_vexriscv: Add updated paths
a1ff441eb3 boards: riscv: adp_xc7k_ae350: Convert to v2
ef82a8255c soc: ae350: Port to HWMv2
282204758a samples: boards: stm32: ccm: fix include path
8ca9341195 samples: basic: threads: fix broken reference
8a947f446d boards: nrf52840dk: fix rst syntax
324cb41153 boards: nordic_nrf: fix broken references
963c74df1c boards: intel_(ish|adl|ehl|rpl), up_squared: fix include
           paths
8d518ce504 boards: legacy: drop empty folders
0fef0cef5b boards: mps2: fix table formatting
e52ccc244f boards: add HWMv2 board index
c7426eca5e boards: arm: add legacy tag
1eba9d8a8f boards: acrn: create vendor folder
8d92edc727 tests: kernel: Adjust qemu_x86_tiny_768 configuration
           HWMv2
75117d1b2d scripts: ensure posix path is used with --cmakeformat
0b0384b56a maintainers: update paths after HWMv2 changes
c1b77b223d boards: arm: pan1783: Convert to v2
91a077b2ab boards: posix: nrf_bsim: Update paths
413b6c2a40 cmake: modules: configuration_files: Add board identifier
           overlay file
4f572ba24f treewide: Update board names for hwmv2
cb348c7edf boards: arm: nrf54l15pdk_nrf54l15: Convert to v2
811ad90566 boards: arm: nrf54h20pdk_nrf54h20: Convert to v2
d44ef90cf8 soc: nordic_nrf: Migrate nRF54H/nRF54L to v2 and fix nrf
c860f205de boards: arm: nrf9151dk_nrf9151: Convert to v2
fba98a1763 soc: nordic_nrf: Migrate nRF9151 to v2
5c156a2d35 boards: arm: 96b_carbon_nrf51: Convert to v2
cfc47a3a4b boards: arm: nrf9161dk_nrf9161: Convert to v2
37129b4e44 boards: arm: nrf9131ek_nrf9131: Convert to v2
a923beba5d boards: arm: bl5340_dvk: Convert to v2
d242b2703b boards: arm: raytac_mdbt53v_db_40_nrf5340: Convert to v2
9c80d4e644 boards: arm: raytac_mdbt53_db_40: Convert to v2
28268c4938 boards: arm: nrf5340_audio_dk_nrf5340: Convert to v2
33ad2b5bc6 boards: arm: thingy53_nrf5340: Convert to v2
40daa94f2d boards: arm: nrf9160_innblue22: Convert to v2
2b0dbb9d51 boards: arm: nrf9160_innblue21: Convert to v2
ee6f7697ac boards: arm: sparkfun_thing_plus_nrf9160: Convert to v2
594e4bad6b boards: arm: circuitdojo_feather_nrf9160: Convert to v2
a5803ba099 boards: arm: actinius_icarus: Convert to v2
db8c275456 boards: arm: actinius_icarus_bee: Convert to v2
30177cf53d boards: arm: actinius_icarus_som: Convert to v2
486504cf24 boards: arm: actinius_icarus_som_dk: Convert to v2
dd0672a64c boards: arm: nrf9160dk_*: Convert to v2
c1565b3d14 boards: arm: xiao_ble: Convert to v2
6dd2723314 boards: arm: qemu_cortex_m0: Convert to v2
ee1ce24a42 boards: arm: bbc_microbit: Convert to v2
1952d559f2 boards: arm: rm1xx_dvk: Convert to v2
9e12c3d8bd boards: arm: nrf51dongle_nrf51422: Convert to v2
0ffbc1da33 boards: arm: nrf51_blenano: Convert to v2
be52dfb7b6 boards: arm: nrf51_vbluno51: Convert to v2
4c29d1827f boards: arm: nrf51_ble400: Convert to v2
5b4a9556fd boards: arm: raytac_mdbt53_db_40_nrf5340: Fix typo
69e5d87a15 boards: arm: contextualelectronics_abc: Convert to v2
5e4ace1bbe boards: arm: degu_evk: Convert to v2
2762460a64 boards: arm: pan1781_evb: Convert to v2
fdc3913e76 boards: arm: ubx_evkninab1_nrf52832: Convert to v2
9c9c3a09a1 boards: arm: holyiot_yj16019: Convert to v2
109edc296f boards: arm: blueclover_plt_demo_v2_nrf52832: Convert to
           v2
7bfcdbbe8f boards: arm: decawave_dwm1001_dev: Convert to v2
0fbb543983 boards: arm: acn52832: Convert to v2
073e0f8080 boards: arm: we_proteus2ev_nrf52832: Convert to v2
197a19f396 boards: arm: ebyte_e73_tbb_nrf52832: Convert to v2
1616fc8ae5 boards: arm: nrf52_vbluno52: Convert to v2
5622077738 boards: arm: nrf52_sparkfun: Convert to v2
a6289516e4 boards: arm: 96b_nitrogen: Convert to v2
439d836883 boards: arm: nrf52_blenano2: Convert to v2
16e65f09c4 boards: arm: arduino_nicla_sense_me: Convert to v2
862efd5a21 boards: arm: thingy52_nrf52832: Convert to v2
dede0f6cd3 boards: arm: nrf52_adafruit_feather: Convert to v2
91e864ea29 boards: arm: nrf52832_mdk: Convert to v2
47ec3e416b boards: arm: ruuvi_ruuvitag: Convert to v2
52f797a227 boards: arm: pinetime_devkit0: Convert to v2
433db339f9 boards: arm: ubx_evkannab1_nrf52832: Convert to v2
a646d3f2d5 boards: arm: ubx_bmd300eval_nrf52832: Convert to v2
d0d434bf86 cmake: print identifier instead of variant
c3f5ed8157 boards: arm: we_proteus3ev_nrf52840: Convert to v2
eecff8ee7a boards: arm: nrf52840_mdk_usb_dongle: Convert to v2
34507614f6 boards: arm: nrf52840_mdk: Convert to v2
f02b56cb96 boards: arm: nrf52840_blip: Convert to v2
600c55c92a boards: arm: nrf52840_papyr: Convert to v2
f294bfc5e4 boards: arm: reel_board: Convert to v2
882524d2a0 boards: arm: nrf21540dk_nrf52840: Convert to v2
4bce0e9b39 boards: arm: nrf52840dongle_nrf52840: Convert to v2
d0229c771f boards: arm: particle_argon: Convert to v2
23a0570e64 boards: arm: particle_boron: Convert to v2
b6d3e1764f boards: arm: particle_xenon: Convert to v2
499f3e7902 boards: arm: rak5010_nrf52840: Convert to v2
9ae6b1804d boards: arm: rak4631_nrf52840: Convert to v2
fe2c90da5c boards: arm: pinnacle_100_dvk: Convert to v2
3d4d46698c boards: arm: ubx_evkninab3_nrf52840: Convert to v2
b1afbf0158 boards: arm: ubx_bmd380eval_nrf52840: Convert to v2
9f9897c872 boards: arm: ubx_bmd345eval_nrf52840: Convert to v2
f7fb2030c7 boards: arm: ubx_bmd340eval_nrf52840: Convert to v2
7186432662 boards: arm: raytac_mdbt50q_db_40_nrf52840: Convert to v2
32c4bdc0c4 boards: arm: pan1780_evb: Convert to v2
7b64c638a8 boards: arm: pan1770_evb: Convert to v2
156ee8ad8a boards: arm: mg100: Convert to v2
3d33dadeb0 boards: arm: arduino_nano_33_ble: Convert to v2
4fee7371d2 boards: arm: adafruit_itsybitsy_nrf52840: Convert to v2
ad37a0c222 boards: arm: adafruit_feather_nrf52840: Convert to v2
cf85b7169f boards: arm: bt510: Convert to v2
44b67ac430 boards: arm: bt610: Convert to v2
7dbb65d371 boards: arm: ubx_evkninab4_nrf52833: Convert to v2
5e79cb957d boards: arm: raytac_mdbt50q_db_33_nrf52833: Convert to v2
12bd83a218 boards: arm: pan1782_evb: Convert to v2
1a135ec352 boards: arm: bbc_microbit_v2: Convert to v2
4dbe97e5ea boards: arm: nrf52833dk: Convert to v2
d632b90043 boards: arm: ubx_bmd360eval_nrf52811: Convert to v2
cc1a30f24b boards: arm: we_ophelia1ev_nrf52805: Convert to v2
df0df9000b boards: arm: ubx_bmd330eval_nrf52810: Convert to v2
d2c7972a9a boards: arm: nrf52dk: Convert to v2
202c2bf447 boards: arm: bl654_sensor_board: Convert to v2
c3e36f2042 boards: arm: bl654_usb: Convert to v2
b9dd58aea1 boards: arm: bl654_dvk: Convert to v2
0e1898b093 boards: arm: bl653_dvk: Convert to v2
286f4a7524 boards: arm: bl652_dvk: Convert to v2
d1709cdb37 boards: update nRF51dk board to board scheme v2.
8f040cff2c boards: Update nrf5340dk_nrf5340 to HWMv2 scheme
8c90fae8e0 boards: update nRF52840dk_nrf52840/nrf52811 board to
           board scheme v2.
c828dcc60e boards: common: openocd-nrf5: Add HWMv2 support
c79f1b0d94 kconfig: soc: adopt Nordic SoC series to support hw model
           v2 scheme
3584b30fc1 tests: Update board names for hwmv2
94024d940e boards: arm: arty_a7: Convert to v2
8053c3a8df boards: arm: scobc_module1: Convert to v2
d5473b76fe soc: designstart: Port to HWMv2
f5792b05e7 boards: arm: fvp_baser_aemv8r_aarch32: Convert to v2
ff202daa8e soc: fvp_aemv8r_aarch32: Port to HWMv2
e66cbc2945 boards: arm: v2m_musca_s1: Convert to v2
33b47b2edb boards: arm: v2m_musca_b1: Convert to v2
baeebd31d2 soc: musca: Port to HWMv2
73b257a3f9 boards: arm: v2m_beetle: Convert to v2
85de0888ec soc: beetle: Port to HWMv2
867960a891 manifest: Update modules
6ca677ed3a boards: arm: mps2: Convert to v2
bcf4ad19d4 twister: build_dir: convert / to _ to support hwmv2
0ac386683f soc: Kconfig.v2: Add SOC_PART_NUMBER
9242c3c78f soc: stm32: soc.yml: reorder series
248d17f160 boards: stm32: cleanup
0a67265e99 boards: stm32: fix for boards with revisions
f8d44317ee soc: stm32l5: Rename overlays for nucleo_l552ze_q ns
           target.
400343d17e soc: stm32: Set default on USE_DT_CODE_PARTITION
d783ef549a soc: stm32l5: Update stm32l5 non secure targets in
           various places
643aeac552 boards: Convert stm32l562e_dk to HWM v2
e601d64344 boards: Convert nucleo_l552ze_q to HWM v2
2f7a387b32 soc: st: Migrate stm32l5 series to new hw model
519752efcd boards: xenvm: doc: Remove reference to deleted file
06263dd717 boards: xenvm: Unset HEAP_MEM_POOL_SIZE in gicv3 variant
66b0df5526 boards: qemu_cortex_a53: Fix Kconfig warnings in SMP
           variant
fa07bd9419 boards: mps3: Fix non-secure variant
8f6f0726dd boards: Move xenvm under xen
7b155a7031 boards: Raspberry Pi vendor fix
804697afa5 boards: Move 96b_aerocore to 96boards
d2f001e320 boards: x86: acrn: move and convert to HWMv2
ec7f7b3c30 tests: kernel: qemu_x86: adjust to the HWMv2
89dfcddc7e boards: x86: qemu_x86_tiny@768: change to board variant
eb724eb6a7 boards: x86: qemu_x86: optimize default HWMv2
           configurations
6f1043cde6 boards: x86: qemu_x86: move and convert to HWMv2
cab924cbfb soc: x86: ia32: move and convert to HWMv2
237fdff918 soc: x86: lakemont: move and convert to HWMv2
03042b7704 boards: move 96b_carbon to 96boards folder
767b94414e boards: rename vendor seeed to seeed_studio
07fa3a3d79 boards: Convert olimex_lora_stm32wl_devkit to HWM v2
ba01d3beca boards: Convert nucleo_wl55jc to HWM v2
7ce84f4041 boards: Convert lora_e5_mini to HWM v2
b988bae576 boards: Convert lora_e5_dev_board to HWM v2
6fbf39c726 soc: v2: stm32: Migrate STM32WL series
4a41878442 soc: st: stm32g4: add missing include
1e79ba15f6 boards: Convert weact_stm32g431_core to HWM v2
ffdcb60185 boards: Convert nucleo_g474re to HWM v2
d6acb08d3e boards: Convert nucleo_g431rb to HWM v2
90e592ffd1 boards: Convert b_g474e_dpow1 to HWM v2
eb8a7e3441 soc: st: stm32: Migrate STM32G4 series
ada469f237 tests: Update board names for hwmv2
0342433187 boards: arm: npcx9m6f_evb: Convert to v2
c10248d964 boards: arm: npcx7m6fb_evb: Convert to v2
21ddc5e6a6 boards: arm: npcx4m8f_evb: Convert to v2
5500f3ef21 soc: npcx*: Port to HWMv2
e7baf09ede soc: m48x: Port to HWMv2
5bae4a6480 boards: arm: numaker_pfm_m467: Convert to v2
3b0bd70c8c soc: m46x: Port to HWMv2
d52eab9e83 boards: Convert stm32g081b_eval to HWM v2
6f2835cb11 boards: Convert stm32g071b_disco to HWM v2
ca36d331d2 boards: Convert stm32g0316_disco to HWM v2
662cc4e09b boards: Convert nucleo_g0b1re to HWM v2
dd9bc29769 boards: Convert nucleo_g071rb to HWM v2
353da23ffb boards: Convert nucleo_g070rb to HWM v2
acc932b424 boards: Convert nucleo_g031k8 to HWM v2
cea9b140fd boards: Convert google_twinkie_v2 to HWM v2
52e025943a soc: st: stm32: Migrate STM32G0 series
1c7347686a ci: update check_compliance to not create duplicate lines
           in Kconfig
9debd98799 hwmv2: boards: up_squared_pro_700: Add missed intel_adl
           changes
adab07c42f boards: Convert msp_exp432p401r_launchxl to HWM v2
642aacdcdf soc: ti_simplelink: Add missing SoC
48637066d3 boards: Fix file paths in documentation
e983bc2a23 samples/tests: Fix mps3 board name
61e0f32716 boards: Convert stm32f3_seco_d23 to HWM v2
a1688ff641 boards: Convert stm32f3_disco to HWM v2
35fb228599 boards: Convert stm32373c_eval to HWM v2
10e5d1122b boards: Convert nucleo_f334r8 to HWM v2
c319cb19f0 boards: Convert nucleo_f303re to HWM v2
11725ccac1 boards: Convert nucleo_f303k8 to HWM v2
400f7f6a4f boards: Convert nucleo_f302r8 to HWM v2
8d84861390 soc: v2: stm32: Migrate STM32F3 series
85b9eee7e8 boards: arm: kv260_r5: Convert to v2
dafbd638e4 boards: arm: mercury_xu: Convert to v2
3ecd12f415 boards: arm: qemu_cortex_r5: Convert to v2
5db2390e9d soc: xilinx_zyncmp: Port to HWMv2
9ba8195cdc boards: arm: qemu_cortex_a9: Convert to v2
8e94b85361 boards: arm: zybo: Convert to v2
c970127fc2 soc: xilinx_zynq7000: Port to HWMv2
394c75373c boards: arm: ast1030_evb: Convert to v2
f2a1cc8714 soc: ast10x0: Port to HWMv2
28f3f25945 boards: arm: cc3235sf_launchxl: Convert to v2
c3e480f740 boards: arm: cc3220sf_launchxl: Convert to v2
fd5847123f boards: arm: beagleconnect_freedom: Convert to v2
76ba9a0587 boards: arm: cc1352p1_launchxl: Convert to v2
719baa8850 boards: arm: cc1352r1_launchxl: Convert to v2
5060a61ae1 boards: arm: cc1352r_sensortag: Convert to v2
99584be1c5 boards: arm: cc26x2r1_launchxl: Convert to v2
2dc8933942 soc: ti_simplelink: Port to HWMv2
a5b004663b scripts/utils/board_v1_to_v2.py: couple of fixes
77c2c333e5 boards: move 96b_stm32_sensor_mez to 96boards
c14ff98650 boards: stm32f411e_disco: delete obsolete file
bcdc268ccf boards: Convert stm32mp157c_dk2 to HWM v2
0c8ba92e1f boards: Convert 96b_avenger96 to HWM v2
b54fe33077 soc: v2: stm32: Migrate STM32MP1 series
2ba3639b2a boards: Convert nucleo_c031c6 to HWM v2
dbc5ed79f5 soc: st: stm32: Migrate STM32C0 series
ce6d493aa3 boards: Convert stm32l1_disco to HWM v2
a28086a9ca boards: Convert nucleo_l152re to HWM v2
1b2a511d06 boards: Convert 96b_wistrio to HWM v2
ce281f09ab soc: v2: stm32: Migrate STM32L1 series
cdb5364fd7 boards: Convert stm32f769i_disco to HWM v2
768f173dcb boards: Convert stm32f7508_dk to HWM v2
21bbbbd9cb boards: Convert stm32f746g_disco to HWM v2
bab4265693 boards: Convert stm32f723e_disco to HWM v2
58f8fe82ba boards: Convert nucleo_f767zi to HWM v2
37e9084070 boards: Convert nucleo_f756zg to HWM v2
d467e7053a boards: Convert nucleo_f746zg to HWM v2
5f2808d7cc boards: Convert nucleo_f722ze to HWM v2
bbb73e7550 soc: st: Migrate stm32f7 series to new hw model
e9094afc4d soc: st: stm32: stm32f4: change SOC_STM32F405XG to
           SOC_STM32F405XX
a1712cdd53 boards: Convert stm32f4_disco to HWM v2
5be404b365 boards: Convert stm32f469i_disco to HWM v2
baaa697ab2 boards: Convert stm32f429i_disc1 to HWM v2
69ecab3c90 boards: Convert stm32f412g_disco to HWM v2
2a572e3fb0 boards: Convert stm32f411e_disco to HWM v2
ecfbf42757 boards: Convert stm32f401_mini to HWM v2
e0191d03bb boards: Convert steval_fcu001v1 to HWM v2
4454648976 boards: Convert segger_trb_stm32f407 to HWM v2
f0ad6ee6b8 boards: Convert olimex_stm32_p405 to HWM v2
1f5e228ec8 boards: Convert olimex_stm32_h407 to HWM v2
834bdb615e boards: Convert olimex_stm32_h405 to HWM v2
8f27fa8de2 boards: Convert olimex_stm32_e407 to HWM v2
f8633a9038 boards: Convert nucleo_f446ze to HWM v2
07e0bd2c07 boards: Convert nucleo_f446re to HWM v2
24d7f625dc boards: Convert nucleo_f429zi to HWM v2
157a8cde53 boards: Convert nucleo_f413zh to HWM v2
4ec99c31b0 boards: Convert nucleo_f412zg to HWM v2
a21546140a boards: Convert nucleo_f411re to HWM v2
43f01ab6de boards: Convert nucleo_f410rb to HWM v2
60c16bcb8b boards: Convert nucleo_f401re to HWM v2
2db228d730 boards: Convert mikroe_mini_m4_for_stm32 to HWM v2
73fc26225c boards: Convert mikroe_clicker_2 to HWM v2
6b62d90114 boards: Convert google_dragonclaw to HWM v2
fa845af309 boards: Convert blackpill_f411ce to HWM v2
5c8c3c3be0 boards: Convert blackpill_f401ce to HWM v2
3c02db1290 boards: Convert blackpill_f401cc to HWM v2
7eeb723cb7 boards: Convert black_f407zg_pro to HWM v2
4f9461d068 boards: Convert black_f407ve to HWM v2
a821de8532 boards: Convert az3166_iotdevkit to HWM v2
ba580c7236 boards: Convert adi_sdp_k1 to HWM v2
eb272ddf19 boards: Convert adafruit_feather_stm32f405 to HWM v2
58ed121c3a boards: Convert 96b_stm32_sensor_mez to HWM v2
b0d70959d3 boards: Convert 96b_neonkey to HWM v2
b1088baadc boards: Convert 96b_carbon to HWM v2
18d867b0a9 boards: Convert 96b_argonkey to HWM v2
ee6ede7119 boards: Convert 96b_aerocore2 to HWM v2
b48e70ead9 soc: v2: stm32: Migrate STM32F4 series
14d2b955da cmake: convert path to CMake style before writing Kconfig
           files
9c4ac6a202 boards: posix: bsim: Update paths
14b57f56d7 tests: drivers: gpio: gpio_ite_it8xxx2_v2: Temp fix
f3b173be18 scripts: board_v1_to_v2: Update following move to
           boards_legacy
05b50f6691 cmake: CMake soc dir variable improvements for HWMv2
a188e01a12 hwmv2: move all ported boards and socs to their final
           location
22c53e97b5 hwmv2: move all non-ported legacy boards and socs to
           legacy folders
53f3b181b0 soc: ti_k3: Port to HWMv2
9f19a2075a soc: rk3568: Port to HWMv2
b8928b1628 soc: rk3399: Port to HWMv2
cda3a74868 boards: arm64: qemu_kvm_arm64: Convert to v2
70d704bd20 soc: x86: atom: move and convert to HWMv2
4789e1068e boards: x86: intel_rpl: move and convert raptor_lake
           boards to HWMv2
384307e3dc soc: x86: raptor_lake: move and convert to HWMv2
ed025df674 boards: x86: intel_ehl: move and convert elkhart_lake
           boards to HWMv2
994b6e1731 soc: x86: elkhart_lake: move and convert to HWMv2
73b30a04cf boards: x86: up_squared_pro_7000: move and convert to
           HWMv2
83b133c207 boards: x86: intel_adl: move and convert alder_lake
           boards to HWMv2
847a12f1e4 soc: alder_lake: move and convert to HWMv2
67f4c8d2a1 samples: up_squared: adjust gpio_counter to HWMv2
5326b5bfc0 boards: x86: up_squared: move and convert to HWMv2
cfd5e691b4 soc: apollo_lake: move and convert to HWMv2
ac9c235741 boards: xtensa: qemu_xtensa: Convert to v2
f198c3a761 ci: update to osource for soc/Kconfig.defconfig files
e438e6cad4 ci: add SOC_SERIES_ as false positive in
           check_compliance.py
95e34da7c1 soc: v2: Convert st_stm32 to st/stm32
313717df76 soc: mps3: Fix missing family
392c3969ed boards: arm: am62x_m4: Convert to v2
8f245d764d tests: Update board names for hwmv2
8f71bb7b4f boards: arm64: khadas_edgev: Convert to v2
e27d23aad0 soc: rk3399: Port to HWMv2
80823b860e boards: arm64: roc_rk3568_pc: Convert to v2
72e4483dec soc: rk3568: Port to HWMv2
bed94669e3 boards: arm64: phycore_am62x_a53: Convert to v2
c01af5a7b8 soc: ti_k3: Port to HWMv2
1e563b4ca3 boards: arm64: xenvm: Convert to v2
76e484adae soc: xenvm: Port to HWMv2
34412f7fe2 boards: arm64: rpi_4b: Convert to v2
9be50e2ca9 soc: bcm2711: Port to HWMv2
bbbed12c2f boards: arm64: qemu_kvm_arm64: Convert to v2
4f5ec7ff8f soc: qemu_virt_arm64: Port to HWMv2
d8d1b9f200 boards: arm64: qemu_cortex_a53: Convert to v2
30bd34b31e soc: qemu_cortex_a53: Port to HWMv2
c20d0dcbb6 boards: arm64: fvp_baser_aemv8r: Convert to v2
02ed6af463 boards: arm64: fvp_base_revc_2xaemv8a: Convert to v2
1b175003a4 soc: fvp_aemv8*: Port to HWMv2
de231b911d boards: v2: Clean up obsolete comments
aa9597f6d9 boards: Convert waveshare_open103z to HWM v2
9644828c81 boards: Convert stm32vl_disco to HWM v2
86ab2bd430 boards: Convert stm32_min_dev to HWM v2
d88d3ddcc4 boards: Convert stm32f103_mini to HWM v2
0ccc0204e1 boards: Convert stm3210c_eval to HWM v2
dd9972d782 boards: Convert olimex_stm32_h103 to HWM v2
a2c2e1406d boards: Convert olimexino_stm32 to HWM v2
2d9c62e118 boards: Convert nucleo_f103rb to HWM v2
e8ba99dc59 soc: v2: stm32: Migrate STM32F1 series
9a93916604 tests: Update board names for hwmv2
9c4d94844d boards: arm: bcm958401m2: Convert to v2
feaf4ffba1 boards: arm: bcm958402m2: Convert to v2
87f0827121 soc: bcm_vk: Port to HWMv2
4526be24a5 boards: arm: quick_feather: Convert to v2
cd921d2b97 boards: arm: qomu: Convert to v2
b3c04051fc soc: quicklogic_eos_s3: Port to HWMv2
a73a9e7533 boards: v2: Clean up obsolete comments
8d87bcc167 boards: Convert stm32f0_disco to HWM v2
1933585785 boards: Convert stm32f072_eval to HWM v2
6f9fe5429d boards: Convert stm32f072b_disco to HWM v2
9dc78e4025 boards: Convert stm32f030_demo to HWM v2
35113e8923 boards: Convert nucleo_f091rc to HWM v2
b276aee9a4 boards: Convert nucleo_f070rb to HWM v2
795f8d611b boards: Convert nucleo_f042k6 to HWM v2
2d82646443 boards: Convert nucleo_f031k6 to HWM v2
959786f12d boards: Convert nucleo_f030r8 to HWM v2
81670db2e9 boards: Convert legend to HWM v2
8980430aad boards: Convert google_kukui to HWM v2
ac020f66e0 dts: stm32f0: fix few warnings
5140e4551a boards: v2: doc: Add vendors
77d640e0c9 soc: v2: stm32: Migrate STM32F0 series
0131e1c159 soc: v2: Add st_stm32 structure and common folder
36b63787a7 boards: v2: Add documentation index for converted boards
ae02fc5047 boards: sparc: qemu_leon3: Convert to v2
f38f7bb223 boards: sparc: gr716a: Convert to v2
d3cca3580e soc: gr716a: Port to HWMv2
6a8a0c1647 boards: sparc: generic_leon3: Convert to v2
faf22185ce soc: leon3: Port to HWMv2
e94762ecdc tests: Update board names for hwmv2
9afcc27e05 boards: xtensa: qemu_xtensa: Convert to v2
3e4a17018f soc: dc233c: Port to HWMv2
9188fdcd78 boards: xtensa: xt-sim: Convert to v2
fcaa41cb5d soc: xtensa_sample_controller: Port to HWMv2
dbc413f7f7 scripts: board_v1_to_v2: Fix CONFIG_SOC_SERIES_ exclusion
6be3d4bc80 kconfig: remove Kconfig BOARD_RPI_PICO_W safe guard.
f4442fa698 boards: v2: Add documentation index for converted boards
ec5fbd67f7 boards: nios2: qemu_nios2: Convert to v2
d3ef220460 soc: nios2-qemu: Port to HWMv2
a223f284b5 boards: nios2: altera_max10: Convert to v2
c381edcb73 soc: nios2f-zephyr: Port to HWMv2
97401c7d2a boards: mips: qemu_malta: Convert to v2
e7a3243a24 soc: qemu_malta: Port to HWMv2
bec82c690d boards: v2: Add documentation index for converted boards
94f6f9b636 boards: arm: w5500_evb_pico: Convert to v2
209235ab6e boards: arm: sparkfun_pro_micro_rp2040: Convert to v2
e5b1885907 boards: arm: adafruit_qt_py_rp2040: Convert to v2
4c750818f9 boards: arm: adafruit_kb2040: Convert to v2
8d3896caa4 boards: arm: rpi_pico: Convert to v2
42cff42c42 soc: rpi_pico: Port to HWMv2
c2df4ca9cb scripts: improve yaml schema and board.yml validation for
           revisions
3970f90f71 cmake: clear BOARD_CACHE when invalid board identifier is
           given
3a70ee9ccd cmake: improve board revision handling
3cda715fae scripts: board_v1_to_v2: Don't add select
           CONFIG_SOC_SERIES_FOO
dc56a543f3 scripts: board_v1_to_v2: Add License + copyright
87147f88c4 cmake: prefer cache BOARD_IDENTIFIER over extracting from
           BOARD
65f5dc5b8c cmake: fail when board identifier is applied in legacy hw
           model
7db2b6efd8 cmake: cache BOARD_IDENTIFIER to preserve it between
           CMake invocations
85dddac5a2 scripts: using extend in list_boards for variant list
6ae5c4e7fd scripts: utils: add board v1->v2 conversion utility
ef834a12d0 maintainers: update Renesas RZT2M path
3ab7830625 boards: renesas: add documentation entry
a0c2ca0491 boards: arm: add documentation entry
27ff3654b7 boards: gigadevice: add documentation entry
6e02f43c0a maintainers: update GD32 paths
1bfcf1d974 boards: gd32l233r_eval: convert to HWMv2
6e621ee43f boards: gd32f470i_eval: convert to HWMv2
219b149768 boards: gd32f450z_eval: convert to HWMv2
91c52b0d39 boards: gd32f450v_start: convert to HWMv2
f0e0a973f6 boards: gd32f407v_start: convert to HWMv2
6f592b64c9 boards: gd32f403z_eval: convert to HWMv2
4bcb4b2ac8 boards: gd32f350r_eval: convert to HWMv2
fdc7ed6eb0 boards: gd32e507z_eval: convert to HWMv2
770376250d boards: gd32e507v_start: convert to HWMv2
a6d8b92e86 boards: gd32e103v_eval: convert to HWMv2
a5f8e5daa1 boards: gd32a503v_eval: convert to HWMv2
5ee799cc5f boards: gd32f450i_eval: convert to HWMv2
8aa8ce4ac8 soc: gigadevice: port to HWMv2
4e203c14c7 cmake: enhanced board entry file handling
312265ee04 scripts: make SoC field mandatory in board.yml
c12ae3bcbc boards: update Renesas rzt2m board.yml to contain SoC
           information
c5321c1dbe cmake: make SoC optional for boards containing a single
           SoC
bcc06c60ae scripts: support SoC list output for boards
db9e46010c twister: update testcase.yaml and sample.yaml to
           mps3/an547 identifier
a988adee7d boards: update arm mps3 an547 board to HWMv2 scheme
7dc2c9db0c soc: use HWMv2 for arm mps3 SoC
c506675b7c boards: update Renesas Starter Kit+ for RZ/T2M board to
           HWMv2 scheme
3abb792073 soc: use HWMv2 for renesas_rzt2m SoC
4f52bc646e cmake: support hw model v2 in arch/Kconfig tree
a712b5005b scripts: extend kconfig compliance to verify board / SoC
           scheme v2
baa55141a1 twister: update twister testplan.py to handle HWMv2
           boards
1f026f70eb boards: extend list_boards.py and update boards CMake
           module
bd854a3af8 cmake: introduce arch and soc cmake modules for hw model
           v2
c9edefa8fd arch: add existing archs to archs.yml for HWMv2 support
61bbfb5ba2 scripts: introduce list_hardware.py for listing of
           architectures and SoCs
a4d1980c35 build: board/ soc: introduce hw model v2 scheme

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
Signed-off-by: Dmitrii Golovanov <dmitrii.golovanov@intel.com>
Signed-off-by: David Leach <david.leach@nxp.com>
Signed-off-by: Emilio Benavente <emilio.benavente@nxp.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Signed-off-by: Iuliana Prodan <iuliana.prodan@nxp.com>
Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Signed-off-by: Filip Kokosinski <fkokosinski@antmicro.com>
Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
Signed-off-by: Manuel Argüelles <manuel.arguelles@nxp.com>
Signed-off-by: Erwan Gouriou <erwan.gouriou@st.com>
Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
Signed-off-by: Francois Ramu <francois.ramu@st.com>
Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Signed-off-by: Abderrahmane Jarmouni <abderrahmane.jarmouni-ext@st.com>
Signed-off-by: Yves Vandervennet <yves.vandervennet@nxp.com>
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
2024-03-02 16:56:33 -05:00

5228 lines
182 KiB
CMake

# SPDX-License-Identifier: Apache-2.0
include_guard(GLOBAL)
include(user_cache)
# Dependencies on CMake modules from the CMake distribution.
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
########################################################
# Table of contents
########################################################
# 1. Zephyr-aware extensions
# 1.1. zephyr_*
# 1.2. zephyr_library_*
# 1.2.1 zephyr_interface_library_*
# 1.3. generate_inc_*
# 1.4. board_*
# 1.5. Misc.
# 2. Kconfig-aware extensions
# 2.1 Misc
# 3. CMake-generic extensions
# 3.1. *_ifdef
# 3.2. *_ifndef
# 3.3. *_option compiler compatibility checks
# 3.3.1 Toolchain integration
# 3.4. Debugging CMake
# 3.5. File system management
# 4. Devicetree extensions
# 4.1 dt_*
# 4.2. *_if_dt_node
# 4.3 zephyr_dt_*
# 5. Zephyr linker functions
# 5.1. zephyr_linker*
# 6 Function helper macros
# 7 Linkable loadable extensions (llext)
########################################################
# 1. Zephyr-aware extensions
########################################################
# 1.1. zephyr_*
#
# The following methods are for modifying the CMake library[0] called
# "zephyr". zephyr is a catch-all CMake library for source files that
# can be built purely with the include paths, defines, and other
# compiler flags that all zephyr source files use.
# [0] https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
#
# Example usage:
# zephyr_sources(
# random_esp32.c
# utils.c
# )
#
# Is short for:
# target_sources(zephyr PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}/random_esp32.c
# ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
# )
#
# As a very high-level introduction here are two call graphs that are
# purposely minimalistic and incomplete.
#
# zephyr_library_cc_option()
# |
# v
# zephyr_library_compile_options() --> target_compile_options()
#
#
# zephyr_cc_option() ---> target_cc_option()
# |
# v
# zephyr_cc_option_fallback() ---> target_cc_option_fallback()
# |
# v
# zephyr_compile_options() ---> target_compile_options()
#
# https://cmake.org/cmake/help/latest/command/target_sources.html
function(zephyr_sources)
foreach(arg ${ARGV})
if(IS_DIRECTORY ${arg})
message(FATAL_ERROR "zephyr_sources() was called on a directory")
endif()
target_sources(zephyr PRIVATE ${arg})
endforeach()
endfunction()
# https://cmake.org/cmake/help/latest/command/target_include_directories.html
function(zephyr_include_directories)
target_include_directories(zephyr_interface INTERFACE ${ARGV})
endfunction()
# https://cmake.org/cmake/help/latest/command/target_include_directories.html
function(zephyr_system_include_directories)
target_include_directories(zephyr_interface SYSTEM INTERFACE ${ARGV})
endfunction()
# https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
function(zephyr_compile_definitions)
target_compile_definitions(zephyr_interface INTERFACE ${ARGV})
endfunction()
# https://cmake.org/cmake/help/latest/command/target_compile_options.html
function(zephyr_compile_options)
target_compile_options(zephyr_interface INTERFACE ${ARGV})
endfunction()
# https://cmake.org/cmake/help/latest/command/target_link_libraries.html
function(zephyr_link_libraries)
target_link_libraries(zephyr_interface INTERFACE ${ARGV})
endfunction()
function(zephyr_libc_link_libraries)
set_property(TARGET zephyr_interface APPEND PROPERTY LIBC_LINK_LIBRARIES ${ARGV})
endfunction()
# See this file section 3.1. target_cc_option
function(zephyr_cc_option)
foreach(arg ${ARGV})
target_cc_option(zephyr_interface INTERFACE ${arg})
endforeach()
endfunction()
function(zephyr_cc_option_fallback option1 option2)
target_cc_option_fallback(zephyr_interface INTERFACE ${option1} ${option2})
endfunction()
function(zephyr_ld_options)
target_ld_options(zephyr_interface INTERFACE ${ARGV})
endfunction()
# Getter functions for extracting build information from
# zephyr_interface. Returning lists, and strings is supported, as is
# requesting specific categories of build information (defines,
# includes, options).
#
# The naming convention follows:
# zephyr_get_${build_information}_for_lang${format}(lang x [STRIP_PREFIX])
# Where
# the argument 'x' is written with the result
# and
# ${build_information} can be one of
# - include_directories # -I directories
# - system_include_directories # -isystem directories
# - compile_definitions # -D'efines
# - compile_options # misc. compiler flags
# and
# ${format} can be
# - the empty string '', signifying that it should be returned as a list
# - _as_string signifying that it should be returned as a string
# and
# ${lang} can be one of
# - C
# - CXX
# - ASM
#
# STRIP_PREFIX
#
# By default the result will be returned ready to be passed directly
# to a compiler, e.g. prefixed with -D, or -I, but it is possible to
# omit this prefix by specifying 'STRIP_PREFIX' . This option has no
# effect for 'compile_options'.
#
# e.g.
# zephyr_get_include_directories_for_lang(ASM x)
# writes "-Isome_dir;-Isome/other/dir" to x
function(zephyr_get_include_directories_for_lang_as_string lang i)
zephyr_get_include_directories_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
set(${i} ${str_of_flags} PARENT_SCOPE)
endfunction()
function(zephyr_get_system_include_directories_for_lang_as_string lang i)
zephyr_get_system_include_directories_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
set(${i} ${str_of_flags} PARENT_SCOPE)
endfunction()
function(zephyr_get_compile_definitions_for_lang_as_string lang i)
zephyr_get_compile_definitions_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
set(${i} ${str_of_flags} PARENT_SCOPE)
endfunction()
function(zephyr_get_compile_options_for_lang_as_string lang i)
zephyr_get_compile_options_for_lang(${lang} list_of_flags DELIMITER " ")
convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
set(${i} ${str_of_flags} PARENT_SCOPE)
endfunction()
function(zephyr_get_include_directories_for_lang lang i)
zephyr_get_parse_args(args ${ARGN})
get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
process_flags(${lang} flags output_list)
string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
if(NOT ARGN)
set(result_output_list "-I$<JOIN:${genexp_output_list},$<SEMICOLON>-I>")
elseif(args_STRIP_PREFIX)
# The list has no prefix, so don't add it.
set(result_output_list ${output_list})
elseif(args_DELIMITER)
set(result_output_list "-I$<JOIN:${genexp_output_list},${args_DELIMITER}-I>")
endif()
set(${i} ${result_output_list} PARENT_SCOPE)
endfunction()
function(zephyr_get_system_include_directories_for_lang lang i)
zephyr_get_parse_args(args ${ARGN})
get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES)
process_flags(${lang} flags output_list)
string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
set_ifndef(args_DELIMITER "$<SEMICOLON>")
set(result_output_list "$<$<BOOL:${genexp_output_list}>:-isystem$<JOIN:${genexp_output_list},${args_DELIMITER}-isystem>>")
set(${i} ${result_output_list} PARENT_SCOPE)
endfunction()
function(zephyr_get_compile_definitions_for_lang lang i)
zephyr_get_parse_args(args ${ARGN})
get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_COMPILE_DEFINITIONS)
process_flags(${lang} flags output_list)
string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
set_ifndef(args_DELIMITER "$<SEMICOLON>")
set(result_output_list "-D$<JOIN:${genexp_output_list},${args_DELIMITER}-D>")
set(${i} ${result_output_list} PARENT_SCOPE)
endfunction()
function(zephyr_get_compile_options_for_lang lang i)
zephyr_get_parse_args(args ${ARGN})
get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_COMPILE_OPTIONS)
process_flags(${lang} flags output_list)
string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
set_ifndef(args_DELIMITER "$<SEMICOLON>")
set(result_output_list "$<JOIN:${genexp_output_list},${args_DELIMITER}>")
set(${i} ${result_output_list} PARENT_SCOPE)
endfunction()
# This function writes a dict to it's output parameter
# 'return_dict'. The dict has information about the parsed arguments,
#
# Usage:
# zephyr_get_parse_args(foo ${ARGN})
# print(foo_STRIP_PREFIX) # foo_STRIP_PREFIX might be set to 1
function(zephyr_get_parse_args return_dict)
foreach(x ${ARGN})
if(DEFINED single_argument)
set(${single_argument} ${x} PARENT_SCOPE)
unset(single_argument)
else()
if(x STREQUAL STRIP_PREFIX)
set(${return_dict}_STRIP_PREFIX 1 PARENT_SCOPE)
elseif(x STREQUAL NO_SPLIT)
set(${return_dict}_NO_SPLIT 1 PARENT_SCOPE)
elseif(x STREQUAL DELIMITER)
set(single_argument ${return_dict}_DELIMITER)
endif()
endif()
endforeach()
endfunction()
function(process_flags lang input output)
# The flags might contains compile language generator expressions that
# look like this:
# $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
# $<$<COMPILE_LANGUAGE:CXX>:$<OTHER_EXPRESSION>>
#
# Flags that don't specify a language like this apply to all
# languages.
#
# See COMPILE_LANGUAGE in
# https://cmake.org/cmake/help/v3.3/manual/cmake-generator-expressions.7.html
#
# To deal with this, we apply a regex to extract the flag and also
# to find out if the language matches.
#
# If this doesn't work out we might need to ban the use of
# COMPILE_LANGUAGE and instead partition C, CXX, and ASM into
# different libraries
set(languages C CXX ASM)
set(tmp_list "")
foreach(flag ${${input}})
set(is_compile_lang_generator_expression 0)
foreach(l ${languages})
if(flag MATCHES "<COMPILE_LANGUAGE:${l}>:([^>]+)>")
set(updated_flag ${CMAKE_MATCH_1})
set(is_compile_lang_generator_expression 1)
if(${l} STREQUAL ${lang})
# This test will match in case there are more generator expressions in the flag.
# As example: $<$<COMPILE_LANGUAGE:C>:$<OTHER_EXPRESSION>>
# $<$<OTHER_EXPRESSION:$<COMPILE_LANGUAGE:C>:something>>
string(REGEX MATCH "(\\\$<)[^\\\$]*(\\\$<)[^\\\$]*(\\\$<)" IGNORE_RESULT ${flag})
if(CMAKE_MATCH_2)
# Nested generator expressions are used, just substitute `$<COMPILE_LANGUAGE:${l}>` to `1`
string(REGEX REPLACE "\\\$<COMPILE_LANGUAGE:${l}>" "1" updated_flag ${flag})
endif()
list(APPEND tmp_list ${updated_flag})
break()
endif()
endif()
endforeach()
if(NOT is_compile_lang_generator_expression)
# SHELL is used to avoid de-duplication, but when process flags
# then this tag must be removed to return real compile/linker flags.
if(flag MATCHES "SHELL:[ ]*(.*)")
separate_arguments(flag UNIX_COMMAND ${CMAKE_MATCH_1})
endif()
# Flags may be placed inside generator expression, therefore any flag
# which is not already a generator expression must have commas converted.
if(NOT flag MATCHES "\\\$<.*>")
string(REPLACE "," "$<COMMA>" flag "${flag}")
endif()
list(APPEND tmp_list ${flag})
endif()
endforeach()
set(${output} ${tmp_list} PARENT_SCOPE)
endfunction()
function(convert_list_of_flags_to_string_of_flags ptr_list_of_flags string_of_flags)
# Convert the list to a string so we can do string replace
# operations on it and replace the ";" list separators with a
# whitespace so the flags are spaced out
string(REPLACE ";" " " locally_scoped_string_of_flags "${${ptr_list_of_flags}}")
# Set the output variable in the parent scope
set(${string_of_flags} ${locally_scoped_string_of_flags} PARENT_SCOPE)
endfunction()
macro(get_property_and_add_prefix result target property prefix)
zephyr_get_parse_args(args ${ARGN})
if(args_STRIP_PREFIX)
set(maybe_prefix "")
else()
set(maybe_prefix ${prefix})
endif()
get_property(target_property TARGET ${target} PROPERTY ${property})
foreach(x ${target_property})
list(APPEND ${result} ${maybe_prefix}${x})
endforeach()
endmacro()
# 1.2 zephyr_library_*
#
# Zephyr libraries use CMake's library concept and a set of
# assumptions about how zephyr code is organized to cut down on
# boilerplate code.
#
# A Zephyr library can be constructed by the function zephyr_library
# or zephyr_library_named. The constructors create a CMake library
# with a name accessible through the variable ZEPHYR_CURRENT_LIBRARY.
#
# The variable ZEPHYR_CURRENT_LIBRARY should seldom be needed since
# the zephyr libraries have methods that modify the libraries. These
# methods have the signature: zephyr_library_<target-function>
#
# The methods are wrappers around the CMake target_* functions. See
# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
# documentation on the underlying target_* functions.
#
# The methods modify the CMake target_* API to reduce boilerplate;
# PRIVATE is assumed
# The target is assumed to be ZEPHYR_CURRENT_LIBRARY
#
# When a flag that is given through the zephyr_* API conflicts with
# the zephyr_library_* API then precedence will be given to the
# zephyr_library_* API. In other words, local configuration overrides
# global configuration.
# Constructor with a directory-inferred name
macro(zephyr_library)
zephyr_library_get_current_dir_lib_name(${ZEPHYR_BASE} lib_name)
zephyr_library_named(${lib_name})
endmacro()
# Determines what the current directory's lib name would be according to the
# provided base and writes it to the argument "lib_name"
macro(zephyr_library_get_current_dir_lib_name base lib_name)
# Remove the prefix (/home/sebo/zephyr/driver/serial/CMakeLists.txt => driver/serial/CMakeLists.txt)
file(RELATIVE_PATH name ${base} ${CMAKE_CURRENT_LIST_FILE})
# Remove the filename (driver/serial/CMakeLists.txt => driver/serial)
get_filename_component(name ${name} DIRECTORY)
# Replace / with __ (driver/serial => driver__serial)
string(REGEX REPLACE "/" "__" name ${name})
# Replace : with __ (C:/zephyrproject => C____zephyrproject)
string(REGEX REPLACE ":" "__" name ${name})
set(${lib_name} ${name})
endmacro()
# Constructor with an explicitly given name.
macro(zephyr_library_named name)
# This is a macro because we need add_library() to be executed
# within the scope of the caller.
set(ZEPHYR_CURRENT_LIBRARY ${name})
add_library(${name} STATIC "")
zephyr_append_cmake_library(${name})
target_link_libraries(${name} PUBLIC zephyr_interface)
endmacro()
# Provides amend functionality to a Zephyr library for out-of-tree usage.
#
# When called from a Zephyr module, the corresponding zephyr library defined
# within Zephyr will be looked up.
#
# Note, in order to ensure correct library when amending, the folder structure in the
# Zephyr module must resemble the structure used in Zephyr, as example:
#
# Example: to amend the zephyr library created in
# ZEPHYR_BASE/drivers/entropy/CMakeLists.txt
# add the following file:
# ZEPHYR_MODULE/drivers/entropy/CMakeLists.txt
# with content:
# zephyr_library_amend()
# zephyr_library_sources(...)
#
# It is also possible to use generator expression when amending to Zephyr
# libraries.
#
# For example, in case it is required to expose the Zephyr library's folder as
# include path then the following is possible:
# zephyr_library_amend()
# zephyr_library_include_directories($<TARGET_PROPERTY:SOURCE_DIR>)
#
# See the CMake documentation for more target properties or generator
# expressions.
#
macro(zephyr_library_amend)
# This is a macro because we need to ensure the ZEPHYR_CURRENT_LIBRARY and
# following zephyr_library_* calls are executed within the scope of the
# caller.
if(NOT ZEPHYR_CURRENT_MODULE_DIR)
message(FATAL_ERROR "Function only available for Zephyr modules.")
endif()
zephyr_library_get_current_dir_lib_name(${ZEPHYR_CURRENT_MODULE_DIR} lib_name)
set(ZEPHYR_CURRENT_LIBRARY ${lib_name})
endmacro()
function(zephyr_link_interface interface)
target_link_libraries(${interface} INTERFACE zephyr_interface)
endfunction()
#
# zephyr_library versions of normal CMake target_<func> functions
# Note, paths passed to this function must be relative in order
# to support the library relocation feature of zephyr_code_relocate
#
function(zephyr_library_sources source)
target_sources(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
endfunction()
function(zephyr_library_include_directories)
target_include_directories(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${ARGN})
endfunction()
function(zephyr_library_link_libraries item)
target_link_libraries(${ZEPHYR_CURRENT_LIBRARY} PUBLIC ${item} ${ARGN})
endfunction()
function(zephyr_library_compile_definitions item)
target_compile_definitions(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${item} ${ARGN})
endfunction()
function(zephyr_library_compile_options item)
# The compiler is relied upon for sane behaviour when flags are in
# conflict. Compilers generally give precedence to flags given late
# on the command line. So to ensure that zephyr_library_* flags are
# placed late on the command line we create a dummy interface
# library and link with it to obtain the flags.
#
# Linking with a dummy interface library will place flags later on
# the command line than the the flags from zephyr_interface because
# zephyr_interface will be the first interface library that flags
# are taken from.
string(MD5 uniqueness "${ARGV}")
set(lib_name options_interface_lib_${uniqueness})
if (NOT TARGET ${lib_name})
# Create the unique target only if it doesn't exist.
add_library( ${lib_name} INTERFACE)
target_compile_options(${lib_name} INTERFACE ${item} ${ARGN})
endif()
target_link_libraries(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${lib_name})
endfunction()
function(zephyr_library_cc_option)
foreach(option ${ARGV})
string(MAKE_C_IDENTIFIER check${option} check)
zephyr_check_compiler_flag(C ${option} ${check})
if(${${check}})
zephyr_library_compile_options(${option})
endif()
endforeach()
endfunction()
function(zephyr_library_add_dependencies)
add_dependencies(${ZEPHYR_CURRENT_LIBRARY} ${ARGN})
endfunction()
# Add the existing CMake library 'library' to the global list of
# Zephyr CMake libraries. This is done automatically by the
# constructor but must be called explicitly on CMake libraries that do
# not use a zephyr library constructor.
function(zephyr_append_cmake_library library)
if(TARGET zephyr_prebuilt)
message(WARNING
"zephyr_library() or zephyr_library_named() called in Zephyr CMake "
"application mode. `${library}` will not be treated as a Zephyr library."
"To create a Zephyr library in Zephyr CMake kernel mode consider "
"creating a Zephyr module. See more here: "
"https://docs.zephyrproject.org/latest/guides/modules.html"
)
endif()
set_property(GLOBAL APPEND PROPERTY ZEPHYR_LIBS ${library})
endfunction()
# Add the imported library 'library_name', located at 'library_path' to the
# global list of Zephyr CMake libraries.
function(zephyr_library_import library_name library_path)
add_library(${library_name} STATIC IMPORTED GLOBAL)
set_target_properties(${library_name}
PROPERTIES IMPORTED_LOCATION
${library_path}
)
zephyr_append_cmake_library(${library_name})
endfunction()
# Place the current zephyr library in the application memory partition.
#
# The partition argument is the name of the partition where the library shall
# be placed.
#
# Note: Ensure the given partition has been defined using
# K_APPMEM_PARTITION_DEFINE in source code.
function(zephyr_library_app_memory partition)
set_property(TARGET zephyr_property_target
APPEND PROPERTY COMPILE_OPTIONS
"-l" $<TARGET_FILE_NAME:${ZEPHYR_CURRENT_LIBRARY}> "${partition}")
endfunction()
# Configure a Zephyr library specific property.
#
# Usage:
# zephyr_library_property(<property> <value>)
#
# Current Zephyr library specific properties that are supported:
# ALLOW_EMPTY <TRUE:FALSE>: Allow a Zephyr library to be empty.
# An empty Zephyr library will generate a CMake
# configure time warning unless `ALLOW_EMPTY` is TRUE.
function(zephyr_library_property)
set(single_args "ALLOW_EMPTY")
cmake_parse_arguments(LIB_PROP "" "${single_args}" "" ${ARGN})
if(LIB_PROP_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_library_property(${ARGV0} ...) given unknown arguments: ${FILE_UNPARSED_ARGUMENTS}")
endif()
foreach(arg ${single_args})
if(DEFINED LIB_PROP_${arg})
set_property(TARGET ${ZEPHYR_CURRENT_LIBRARY} PROPERTY ${arg} ${LIB_PROP_${arg}})
endif()
endforeach()
endfunction()
# 1.2.1 zephyr_interface_library_*
#
# A Zephyr interface library is a thin wrapper over a CMake INTERFACE
# library. The most important responsibility of this abstraction is to
# ensure that when a user KConfig-enables a library then the header
# files of this library will be accessible to the 'app' library.
#
# This is done because when a user uses Kconfig to enable a library he
# expects to be able to include its header files and call its
# functions out-of-the box.
#
# A Zephyr interface library should be used when there exists some
# build information (include directories, defines, compiler flags,
# etc.) that should be applied to a set of Zephyr libraries and 'app'
# might be one of these libraries.
#
# Zephyr libraries must explicitly call
# zephyr_library_link_libraries(<interface_library>) to use this build
# information. 'app' is treated as a special case for usability
# reasons; a Kconfig option (CONFIG_APP_LINK_WITH_<interface_library>)
# should exist for each interface_library and will determine if 'app'
# links with the interface_library.
#
# This API has a constructor like the zephyr_library API has, but it
# does not have wrappers over the other cmake target functions.
macro(zephyr_interface_library_named name)
add_library(${name} INTERFACE)
set_property(GLOBAL APPEND PROPERTY ZEPHYR_INTERFACE_LIBS ${name})
endmacro()
# 1.3 generate_inc_*
# These functions are useful if there is a need to generate a file
# that can be included into the application at build time. The file
# can also be compressed automatically when embedding it.
#
# See tests/application_development/gen_inc_file for an example of
# usage.
function(generate_inc_file
source_file # The source file to be converted to hex
generated_file # The generated file
)
add_custom_command(
OUTPUT ${generated_file}
COMMAND
${PYTHON_EXECUTABLE}
${ZEPHYR_BASE}/scripts/build/file2hex.py
${ARGN} # Extra arguments are passed to file2hex.py
--file ${source_file}
> ${generated_file} # Does pipe redirection work on Windows?
DEPENDS ${source_file}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endfunction()
function(generate_inc_file_for_gen_target
target # The cmake target that depends on the generated file
source_file # The source file to be converted to hex
generated_file # The generated file
gen_target # The generated file target we depend on
# Any additional arguments are passed on to file2hex.py
)
generate_inc_file(${source_file} ${generated_file} ${ARGN})
# Ensure 'generated_file' is generated before 'target' by creating a
# dependency between the two targets
add_dependencies(${target} ${gen_target})
endfunction()
function(generate_inc_file_for_target
target # The cmake target that depends on the generated file
source_file # The source file to be converted to hex
generated_file # The generated file
# Any additional arguments are passed on to file2hex.py
)
# Ensure 'generated_file' is generated before 'target' by creating a
# 'custom_target' for it and setting up a dependency between the two
# targets
# But first create a unique name for the custom target
generate_unique_target_name_from_filename(${generated_file} generated_target_name)
add_custom_target(${generated_target_name} DEPENDS ${generated_file})
generate_inc_file_for_gen_target(${target} ${source_file} ${generated_file} ${generated_target_name} ${ARGN})
endfunction()
# 1.4. board_*
#
# This section is for extensions related to Zephyr board handling.
#
# Zephyr board extensions current contains:
# - Board runners
# - Board revision
# Zephyr board runners:
# Zephyr board runner extension functions control Zephyr's board runners
# from the build system. The Zephyr build system has targets for
# flashing and debugging supported boards. These are wrappers around a
# "runner" Python subpackage that is part of Zephyr's "west" tool.
#
# This section provides glue between CMake and the Python code that
# manages the runners.
function(_board_check_runner_type type) # private helper
if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG")))
message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG")
endif()
endfunction()
# This function sets the runner for the board unconditionally. It's
# meant to be used from application CMakeLists.txt files.
#
# NOTE: Usually board_set_xxx_ifnset() is best in board.cmake files.
# This lets the user set the runner at cmake time, or in their
# own application's CMakeLists.txt.
#
# Usage:
# board_set_runner(FLASH pyocd)
#
# This would set the board's flash runner to "pyocd".
#
# In general, "type" is FLASH or DEBUG, and "runner" is the name of a
# runner.
function(board_set_runner type runner)
_board_check_runner_type(${type})
if (DEFINED BOARD_${type}_RUNNER)
message(STATUS "overriding ${type} runner ${BOARD_${type}_RUNNER}; it's now ${runner}")
endif()
set(BOARD_${type}_RUNNER ${runner} PARENT_SCOPE)
endfunction()
# This macro is like board_set_runner(), but will only make a change
# if that runner is currently not set.
#
# See also board_set_flasher_ifnset() and board_set_debugger_ifnset().
macro(board_set_runner_ifnset type runner)
_board_check_runner_type(${type})
# This is a macro because set_ifndef() works at parent scope.
# If this were a function, that would be this function's scope,
# which wouldn't work.
set_ifndef(BOARD_${type}_RUNNER ${runner})
endmacro()
# A convenience macro for board_set_runner(FLASH ${runner}).
macro(board_set_flasher runner)
board_set_runner(FLASH ${runner})
endmacro()
# A convenience macro for board_set_runner(DEBUG ${runner}).
macro(board_set_debugger runner)
board_set_runner(DEBUG ${runner})
endmacro()
# A convenience macro for board_set_runner_ifnset(FLASH ${runner}).
macro(board_set_flasher_ifnset runner)
board_set_runner_ifnset(FLASH ${runner})
endmacro()
# A convenience macro for board_set_runner_ifnset(DEBUG ${runner}).
macro(board_set_debugger_ifnset runner)
board_set_runner_ifnset(DEBUG ${runner})
endmacro()
# This function is intended for board.cmake files and application
# CMakeLists.txt files.
#
# Usage from board.cmake files:
# board_runner_args(runner "--some-arg=val1" "--another-arg=val2")
#
# The build system will then ensure the command line used to
# create the runner contains:
# --some-arg=val1 --another-arg=val2
#
# Within application CMakeLists.txt files, ensure that all calls to
# board_runner_args() are part of a macro named app_set_runner_args(),
# like this, which is defined before calling 'find_package(Zephyr)':
# macro(app_set_runner_args)
# board_runner_args(runner "--some-app-setting=value")
# endmacro()
#
# The build system tests for the existence of the macro and will
# invoke it at the appropriate time if it is defined.
#
# Any explicitly provided settings given by this function override
# defaults provided by the build system.
function(board_runner_args runner)
string(MAKE_C_IDENTIFIER ${runner} runner_id)
# Note the "_EXPLICIT_" here, and see below.
set_property(GLOBAL APPEND PROPERTY BOARD_RUNNER_ARGS_EXPLICIT_${runner_id} ${ARGN})
endfunction()
# This function is intended for internal use by
# boards/common/runner.board.cmake files.
#
# Basic usage:
# board_finalize_runner_args(runner)
#
# This ensures the build system captures all arguments added in any
# board_runner_args() calls, and otherwise finishes registering a
# runner for use.
#
# Extended usage:
# board_runner_args(runner "--some-arg=default-value")
#
# This provides common or default values for arguments. These are
# placed before board_runner_args() calls, so they generally take
# precedence, except for arguments which can be given multiple times
# (use these with caution).
function(board_finalize_runner_args runner)
# If the application provided a macro to add additional runner
# arguments, handle them.
if(COMMAND app_set_runner_args)
app_set_runner_args()
endif()
# Retrieve the list of explicitly set arguments.
string(MAKE_C_IDENTIFIER ${runner} runner_id)
get_property(explicit GLOBAL PROPERTY "BOARD_RUNNER_ARGS_EXPLICIT_${runner_id}")
# Note no _EXPLICIT_ here. This property contains the final list.
set_property(GLOBAL APPEND PROPERTY BOARD_RUNNER_ARGS_${runner_id}
# Default arguments from the common runner file come first.
${ARGN}
# Arguments explicitly given with board_runner_args() come
# next, so they take precedence over the common runner file.
${explicit}
# Arguments given via the CMake cache come last of all. Users
# can provide variables in this way from the CMake command line.
${BOARD_RUNNER_ARGS_${runner_id}}
)
# Add the finalized runner to the global property list.
set_property(GLOBAL APPEND PROPERTY ZEPHYR_RUNNERS ${runner})
endfunction()
function(board_set_rimage_target target)
set(RIMAGE_TARGET ${target} CACHE STRING "rimage target")
zephyr_check_cache(RIMAGE_TARGET)
endfunction()
# Zephyr board revision:
#
# This section provides a function for revision checking.
# Usage:
# board_check_revision(FORMAT <LETTER | NUMBER | MAJOR.MINOR.PATCH>
# [EXACT]
# [DEFAULT_REVISION <revision>]
# [HIGHEST_REVISION <revision>]
# )
#
# Zephyr board extension function.
#
# This function can be used in `boards/<board>/revision.cmake` to check a user
# requested revision against available board revisions.
#
# The function will check the revision from `-DBOARD=<board>@<revision>` that
# is provided by the user according to the arguments.
# When `EXACT` is not specified, this function will set the Zephyr build system
# variable `ACTIVE_BOARD_REVISION` with the selected revision.
#
# FORMAT <LETTER | NUMBER | MAJOR.MINOR.PATCH>: Specify the revision format.
# LETTER: Revision format is a single letter from A - Z.
# NUMBER: Revision format is a single integer number.
# MAJOR.MINOR.PATCH: Revision format is three numbers, separated by `.`,
# `x.y.z`. Trailing zeroes may be omitted on the
# command line, which means:
# 1.0.0 == 1.0 == 1
#
# OPTIONAL: Revision specifier is optional. If revision is not provided the base
# board will be used. If both `EXACT` and `OPTIONAL` are given, then
# specifying the revision is optional, but if it is given then the
# `EXACT` requirements apply. Mutually exclusive with `DEFAULT_REVISION`.
#
# EXACT: Revision is required to be an exact match. As example, available revisions are:
# 0.1.0 and 0.3.0, and user provides 0.2.0, then an error is reported
# when `EXACT` is given.
# If `EXACT` is not provided, then closest lower revision will be selected
# as the active revision, which in the example will be `0.1.0`.
#
# DEFAULT_REVISION: Provides a default revision to use when user has not selected
# a revision number. If no default revision is provided then
# user will be printed with an error if no revision is given
# on the command line.
#
# HIGHEST_REVISION: Allows to specify highest valid revision for a board.
# This can be used to ensure that a newer board cannot be used
# with an older Zephyr. As example, if current board supports
# revisions 0.x.0-0.99.99 and 1.0.0-1.99.99, and it is expected
# that current board implementation will not work with board
# revision 2.0.0, then HIGHEST_REVISION can be set to 1.99.99,
# and user will be printed with an error if using
# `<board>@2.0.0` or higher.
# This field is not needed when `EXACT` is used.
#
# VALID_REVISIONS: A list of valid revisions for this board.
# If this argument is not provided, then each Kconfig fragment
# of the form ``<board>_<revision>.conf`` in the board folder
# will be used as a valid revision for the board.
#
function(board_check_revision)
set(options OPTIONAL EXACT)
set(single_args FORMAT DEFAULT_REVISION HIGHEST_REVISION)
set(multi_args VALID_REVISIONS)
cmake_parse_arguments(BOARD_REV "${options}" "${single_args}" "${multi_args}" ${ARGN})
string(TOUPPER ${BOARD_REV_FORMAT} BOARD_REV_FORMAT)
if(DEFINED BOARD_REV_DEFAULT_REVISION AND BOARD_REV_OPTIONAL)
message(FATAL_ERROR "Arguments BOARD_REVISION and OPTIONAL are mutually exclusive")
endif()
if(NOT DEFINED BOARD_REVISION)
if(BOARD_REV_OPTIONAL)
return()
elseif(DEFINED BOARD_REV_DEFAULT_REVISION)
set(BOARD_REVISION ${BOARD_REV_DEFAULT_REVISION})
set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
else()
message(FATAL_ERROR "No board revision specified, Board: `${BOARD}` \
requires a revision. Please use: `-DBOARD=${BOARD}@<revision>`")
endif()
endif()
if(DEFINED BOARD_REV_HIGHEST_REVISION)
if(((BOARD_REV_FORMAT STREQUAL LETTER) AND
(BOARD_REVISION STRGREATER BOARD_REV_HIGHEST_REVISION)) OR
((BOARD_REV_FORMAT STREQUAL NUMBER) AND
(BOARD_REVISION GREATER BOARD_REV_HIGHEST_REVISION)) OR
((BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$") AND
(BOARD_REVISION VERSION_GREATER BOARD_REV_HIGHEST_REVISION))
)
message(FATAL_ERROR "Board revision `${BOARD_REVISION}` greater than \
highest supported revision `${BOARD_REV_HIGHEST_REVISION}`. \
Please specify a valid board revision.")
endif()
endif()
if(BOARD_REV_FORMAT STREQUAL LETTER)
set(revision_regex "([A-Z])")
elseif(BOARD_REV_FORMAT STREQUAL NUMBER)
set(revision_regex "([0-9]+)")
elseif(BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$")
set(revision_regex "((0|[1-9][0-9]*)(\.[0-9]+)(\.[0-9]+))")
# We allow loose <board>@<revision> typing on command line.
# so append missing zeroes.
if(BOARD_REVISION MATCHES "((0|[1-9][0-9]*)(\.[0-9]+)?(\.[0-9]+)?)")
if(NOT CMAKE_MATCH_3)
set(BOARD_REVISION ${BOARD_REVISION}.0)
set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
endif()
if(NOT CMAKE_MATCH_4)
set(BOARD_REVISION ${BOARD_REVISION}.0)
set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
endif()
endif()
else()
message(FATAL_ERROR "Invalid format specified for \
`board_check_revision(FORMAT <LETTER | NUMBER | MAJOR.MINOR.PATCH>)`")
endif()
if(NOT (BOARD_REVISION MATCHES "^${revision_regex}$"))
message(FATAL_ERROR "Invalid revision format used for `${BOARD_REVISION}`. \
Board `${BOARD}` uses revision format: ${BOARD_REV_FORMAT}.")
endif()
if(NOT DEFINED BOARD_REV_VALID_REVISIONS)
file(GLOB revision_candidates LIST_DIRECTORIES false RELATIVE ${BOARD_DIR}
${BOARD_DIR}/${BOARD}_*.conf
)
string(REPLACE "." "_" underscore_revision_regex ${revision_regex})
set(file_revision_regex "${BOARD}_${underscore_revision_regex}.conf")
foreach(candidate ${revision_candidates})
if(${candidate} MATCHES "${file_revision_regex}")
string(REPLACE "_" "." FOUND_BOARD_REVISION ${CMAKE_MATCH_1})
list(APPEND BOARD_REV_VALID_REVISIONS ${FOUND_BOARD_REVISION})
endif()
endforeach()
endif()
if(${BOARD_REVISION} IN_LIST BOARD_REV_VALID_REVISIONS)
# Found exact match.
return()
endif()
if(NOT BOARD_REV_EXACT)
foreach(TEST_REVISION ${BOARD_REV_VALID_REVISIONS})
if((BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$") AND
(${BOARD_REVISION} VERSION_GREATER_EQUAL ${TEST_REVISION}) AND
(${TEST_REVISION} VERSION_GREATER_EQUAL "${ACTIVE_BOARD_REVISION}")
)
set(ACTIVE_BOARD_REVISION ${TEST_REVISION})
elseif((BOARD_REV_FORMAT STREQUAL LETTER) AND
(${BOARD_REVISION} STRGREATER ${TEST_REVISION}) AND
(${TEST_REVISION} STRGREATER "${ACTIVE_BOARD_REVISION}")
)
set(ACTIVE_BOARD_REVISION ${TEST_REVISION})
elseif((BOARD_REV_FORMAT STREQUAL NUMBER) AND
(${BOARD_REVISION} GREATER ${TEST_REVISION}) AND
(${TEST_REVISION} GREATER "${ACTIVE_BOARD_REVISION}")
)
set(ACTIVE_BOARD_REVISION ${TEST_REVISION})
endif()
endforeach()
endif()
if(BOARD_REV_EXACT OR NOT DEFINED ACTIVE_BOARD_REVISION)
message(FATAL_ERROR "Board revision `${BOARD_REVISION}` for board \
`${BOARD}` not found. Please specify a valid board revision.")
endif()
set(ACTIVE_BOARD_REVISION ${ACTIVE_BOARD_REVISION} PARENT_SCOPE)
endfunction()
# 1.5. Misc.
# zephyr_check_compiler_flag is a part of Zephyr's toolchain
# infrastructure. It should be used when testing toolchain
# capabilities and it should normally be used in place of the
# functions:
#
# check_compiler_flag
# check_c_compiler_flag
# check_cxx_compiler_flag
#
# See check_compiler_flag() for API documentation as it has the same
# API.
#
# It is implemented as a wrapper on top of check_compiler_flag, which
# again wraps the CMake-builtin's check_c_compiler_flag and
# check_cxx_compiler_flag.
#
# It takes time to check for compatibility of flags against toolchains
# so we cache the capability test results in USER_CACHE_DIR (This
# caching comes in addition to the caching that CMake does in the
# build folder's CMakeCache.txt)
function(zephyr_check_compiler_flag lang option check)
# Check if the option is covered by any hardcoded check before doing
# an automated test.
zephyr_check_compiler_flag_hardcoded(${lang} "${option}" _${check} exists)
if(exists)
set(${check} ${_${check}} PARENT_SCOPE)
return()
endif()
# Locate the cache directory
set_ifndef(
ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR
${USER_CACHE_DIR}/ToolchainCapabilityDatabase
)
# The toolchain capability database/cache is maintained as a
# directory of files. The filenames in the directory are keys, and
# the file contents are the values in this key-value store.
# We need to create a unique key wrt. testing the toolchain
# capability. This key must include everything that can affect the
# toolchain test.
#
# Also, to fit the key into a filename we calculate the MD5 sum of
# the key.
# The 'cacheformat' must be bumped if a bug in the caching mechanism
# is detected and all old keys must be invalidated.
set(cacheformat 3)
set(key_string "")
set(key_string "${key_string}${cacheformat}_")
set(key_string "${key_string}${TOOLCHAIN_SIGNATURE}_")
set(key_string "${key_string}${lang}_")
set(key_string "${key_string}${option}_")
set(key_string "${key_string}${CMAKE_REQUIRED_FLAGS}_")
string(MD5 key "${key_string}")
# Check the cache
set(key_path ${ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR}/${key})
if(EXISTS ${key_path})
file(READ
${key_path} # File to be read
key_value # Output variable
LIMIT 1 # Read at most 1 byte ('0' or '1')
)
set(${check} ${key_value} PARENT_SCOPE)
return()
endif()
# Flags that start with -Wno-<warning> can not be tested by
# check_compiler_flag, they will always pass, but -W<warning> can be
# tested, so to test -Wno-<warning> flags we test -W<warning>
# instead.
if("${option}" MATCHES "-Wno-(.*)")
string(REPLACE "-Wno-" "-W" possibly_translated_option "${option}")
else()
set(possibly_translated_option ${option})
endif()
check_compiler_flag(${lang} "${possibly_translated_option}" inner_check)
set(${check} ${inner_check} PARENT_SCOPE)
# Populate the cache
if(NOT (EXISTS ${key_path}))
# This is racy. As often with race conditions, this one can easily be
# made worse and demonstrated with a simple delay:
# execute_process(COMMAND "sleep" "5")
# Delete the cache, add the sleep above and run twister with a
# large number of JOBS. Once it's done look at the log.txt file
# below and you will see that concurrent cmake processes created the
# same files multiple times.
# While there are a number of reasons why this race seems both very
# unlikely and harmless, let's play it safe anyway and write to a
# private, temporary file first. All modern filesystems seem to
# support at least one atomic rename API and cmake's file(RENAME
# ...) officially leverages that.
string(RANDOM LENGTH 8 tempsuffix)
file(
WRITE
"${key_path}_tmp_${tempsuffix}"
${inner_check}
)
file(
RENAME
"${key_path}_tmp_${tempsuffix}" "${key_path}"
)
# Populate a metadata file (only intended for trouble shooting)
# with information about the hash, the toolchain capability
# result, and the toolchain test.
file(
APPEND
${ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR}/log.txt
"${inner_check} ${key} ${key_string}\n"
)
endif()
endfunction()
function(zephyr_check_compiler_flag_hardcoded lang option check exists)
# Various flags that are not supported for CXX may not be testable
# because they would produce a warning instead of an error during
# the test. Exclude them by toolchain-specific blocklist.
if((${lang} STREQUAL CXX) AND ("${option}" IN_LIST CXX_EXCLUDED_OPTIONS))
set(${check} 0 PARENT_SCOPE)
set(${exists} 1 PARENT_SCOPE)
else()
# There does not exist a hardcoded check for this option.
set(${exists} 0 PARENT_SCOPE)
endif()
endfunction(zephyr_check_compiler_flag_hardcoded)
# zephyr_linker_sources(<location> [SORT_KEY <sort_key>] <files>)
#
# <files> is one or more .ld formatted files whose contents will be
# copied/included verbatim into the given <location> in the global linker.ld.
# Preprocessor directives work inside <files>. Relative paths are resolved
# relative to the calling file, like zephyr_sources().
# Subsequent calls to zephyr_linker_sources with the same file(s) will remove
# these from the original location. Only the last call is considered.
# <location> is one of
# NOINIT Inside the noinit output section.
# RWDATA Inside the data output section.
# RODATA Inside the rodata output section.
# ROM_START Inside the first output section of the image. This option is
# currently only available on ARM Cortex-M, ARM Cortex-R,
# x86, ARC, openisa_rv32m1, and RISC-V.
# RAM_SECTIONS Inside the RAMABLE_REGION GROUP, not initialized.
# DATA_SECTIONS Inside the RAMABLE_REGION GROUP, initialized.
# RAMFUNC_SECTION Inside the RAMFUNC RAMABLE_REGION GROUP, not initialized.
# NOCACHE_SECTION Inside the NOCACHE section
# ITCM_SECTION Inside the itcm section.
# DTCM_SECTION Inside the dtcm data section.
# SECTIONS Near the end of the file. Don't use this when linking into
# RAMABLE_REGION, use RAM_SECTIONS instead.
# PINNED_RODATA Similar to RODATA but pinned in memory.
# PINNED_RAM_SECTIONS
# Similar to RAM_SECTIONS but pinned in memory.
# PINNED_DATA_SECTIONS
# Similar to DATA_SECTIONS but pinned in memory.
# <sort_key> is an optional key to sort by inside of each location. The key must
# be alphanumeric, and the keys are sorted alphabetically. If no key is
# given, the key 'default' is used. Keys are case-sensitive.
#
# Use NOINIT, RWDATA, and RODATA unless they don't work for your use case.
#
# When placing into NOINIT, RWDATA, RODATA, ROM_START, RAMFUNC_SECTION,
# NOCACHE_SECTION, DTCM_SECTION or ITCM_SECTION the contents of the files will
# be placed inside an output section, so assume the section definition is
# already present, e.g.:
# _mysection_start = .;
# KEEP(*(.mysection));
# _mysection_end = .;
# _mysection_size = ABSOLUTE(_mysection_end - _mysection_start);
#
# When placing into SECTIONS, RAM_SECTIONS or DATA_SECTIONS, the files must
# instead define their own output sections to achieve the same thing:
# SECTION_PROLOGUE(.mysection,,)
# {
# _mysection_start = .;
# KEEP(*(.mysection))
# _mysection_end = .;
# } GROUP_LINK_IN(ROMABLE_REGION)
# _mysection_size = _mysection_end - _mysection_start;
#
# Note about the above examples: If the first example was used with RODATA, and
# the second with SECTIONS, the two examples do the same thing from a user
# perspective.
#
# Friendly reminder: Beware of the different ways the location counter ('.')
# behaves inside vs. outside section definitions.
function(zephyr_linker_sources location)
# Set up the paths to the destination files. These files are #included inside
# the global linker.ld.
set(snippet_base "${__build_dir}/include/generated")
set(sections_path "${snippet_base}/snippets-sections.ld")
set(ram_sections_path "${snippet_base}/snippets-ram-sections.ld")
set(data_sections_path "${snippet_base}/snippets-data-sections.ld")
set(rom_start_path "${snippet_base}/snippets-rom-start.ld")
set(noinit_path "${snippet_base}/snippets-noinit.ld")
set(rwdata_path "${snippet_base}/snippets-rwdata.ld")
set(rodata_path "${snippet_base}/snippets-rodata.ld")
set(ramfunc_path "${snippet_base}/snippets-ramfunc-section.ld")
set(nocache_path "${snippet_base}/snippets-nocache-section.ld")
set(itcm_path "${snippet_base}/snippets-itcm-section.ld")
set(dtcm_path "${snippet_base}/snippets-dtcm-section.ld")
set(pinned_ram_sections_path "${snippet_base}/snippets-pinned-ram-sections.ld")
set(pinned_data_sections_path "${snippet_base}/snippets-pinned-data-sections.ld")
set(pinned_rodata_path "${snippet_base}/snippets-pinned-rodata.ld")
# Clear destination files if this is the first time the function is called.
get_property(cleared GLOBAL PROPERTY snippet_files_cleared)
if (NOT DEFINED cleared)
file(WRITE ${sections_path} "")
file(WRITE ${ram_sections_path} "")
file(WRITE ${data_sections_path} "")
file(WRITE ${rom_start_path} "")
file(WRITE ${noinit_path} "")
file(WRITE ${rwdata_path} "")
file(WRITE ${rodata_path} "")
file(WRITE ${ramfunc_path} "")
file(WRITE ${nocache_path} "")
file(WRITE ${itcm_path} "")
file(WRITE ${dtcm_path} "")
file(WRITE ${pinned_ram_sections_path} "")
file(WRITE ${pinned_data_sections_path} "")
file(WRITE ${pinned_rodata_path} "")
set_property(GLOBAL PROPERTY snippet_files_cleared true)
endif()
# Choose destination file, based on the <location> argument.
if ("${location}" STREQUAL "SECTIONS")
set(snippet_path "${sections_path}")
elseif("${location}" STREQUAL "RAM_SECTIONS")
set(snippet_path "${ram_sections_path}")
elseif("${location}" STREQUAL "DATA_SECTIONS")
set(snippet_path "${data_sections_path}")
elseif("${location}" STREQUAL "ROM_START")
set(snippet_path "${rom_start_path}")
elseif("${location}" STREQUAL "NOINIT")
set(snippet_path "${noinit_path}")
elseif("${location}" STREQUAL "RWDATA")
set(snippet_path "${rwdata_path}")
elseif("${location}" STREQUAL "RODATA")
set(snippet_path "${rodata_path}")
elseif("${location}" STREQUAL "RAMFUNC_SECTION")
set(snippet_path "${ramfunc_path}")
elseif("${location}" STREQUAL "NOCACHE_SECTION")
set(snippet_path "${nocache_path}")
elseif("${location}" STREQUAL "ITCM_SECTION")
dt_has_chosen(HAS_ITCM PROPERTY "zephyr,itcm")
if(NOT HAS_ITCM)
message(FATAL_ERROR "Trying to link snippet into itcm but no itcm available. "
"Add `zephyr,itcm` to the device tree if supported on your device or choose another "
"location.")
endif()
set(snippet_path "${itcm_path}")
elseif("${location}" STREQUAL "DTCM_SECTION")
dt_has_chosen(HAS_DTCM PROPERTY "zephyr,dtcm")
if(NOT HAS_DTCM)
message(FATAL_ERROR "Trying to link snippet into dtcm but no dtcm available. "
"Add `zephyr,dtcm` to the device tree if supported on your device or choose another "
"location.")
endif()
set(snippet_path "${dtcm_path}")
elseif("${location}" STREQUAL "PINNED_RAM_SECTIONS")
set(snippet_path "${pinned_ram_sections_path}")
elseif("${location}" STREQUAL "PINNED_DATA_SECTIONS")
set(snippet_path "${pinned_data_sections_path}")
elseif("${location}" STREQUAL "PINNED_RODATA")
set(snippet_path "${pinned_rodata_path}")
else()
message(fatal_error "Must choose valid location for linker snippet.")
endif()
cmake_parse_arguments(L "" "SORT_KEY" "" ${ARGN})
set(SORT_KEY default)
if(DEFINED L_SORT_KEY)
set(SORT_KEY ${L_SORT_KEY})
endif()
foreach(file IN ITEMS ${L_UNPARSED_ARGUMENTS})
# Resolve path.
if(IS_ABSOLUTE ${file})
set(path ${file})
else()
set(path ${CMAKE_CURRENT_SOURCE_DIR}/${file})
endif()
if(IS_DIRECTORY ${path})
message(FATAL_ERROR "zephyr_linker_sources() was called on a directory")
endif()
# Find the relative path to the linker file from the include folder.
file(RELATIVE_PATH relpath ${ZEPHYR_BASE}/include ${path})
# Create strings to be written into the file
set (include_str "/* Sort key: \"${SORT_KEY}\" */#include \"${relpath}\"")
# Remove line from other snippet file, if already used
get_property(old_path GLOBAL PROPERTY "snippet_files_used_${relpath}")
if (DEFINED old_path)
file(STRINGS ${old_path} lines)
list(FILTER lines EXCLUDE REGEX ${relpath})
string(REPLACE ";" "\n;" lines "${lines}") # Add newline to each line.
file(WRITE ${old_path} ${lines} "\n")
endif()
set_property(GLOBAL PROPERTY "snippet_files_used_${relpath}" ${snippet_path})
# Add new line to existing lines, sort them, and write them back.
file(STRINGS ${snippet_path} lines) # Get current lines (without newlines).
list(APPEND lines ${include_str})
list(SORT lines)
string(REPLACE ";" "\n;" lines "${lines}") # Add newline to each line.
file(WRITE ${snippet_path} ${lines} "\n")
endforeach()
endfunction(zephyr_linker_sources)
# Helper macro for conditionally calling zephyr_code_relocate() when a
# specific Kconfig symbol is enabled. See zephyr_code_relocate() description
# for supported arguments.
macro(zephyr_code_relocate_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_code_relocate(${ARGN})
endif()
endmacro()
# Helper function for CONFIG_CODE_DATA_RELOCATION
# This function may either be invoked with a list of files, or a library
# name to relocate.
#
# The FILES directive will relocate a list of files (wildcards supported)
# This directive will relocate file1. and file2.c to SRAM:
# zephyr_code_relocate(FILES file1.c file2.c LOCATION SRAM)
# Note, files can also be passed as a comma separated list to support using
# cmake generator arguments
#
# The LIBRARY directive will relocate a library
# This directive will relocate the target my_lib to SRAM:
# zephyr_code_relocate(LIBRARY my_lib SRAM)
#
# The following optional arguments are supported:
# - NOCOPY: this flag indicates that the file data does not need to be copied
# at boot time (For example, for flash XIP).
# - NOKEEP: suppress the generation of KEEP() statements in the linker script,
# to allow any unused code in the given files/library to be discarded.
# - PHDR [program_header]: add program header. Used on Xtensa platforms.
function(zephyr_code_relocate)
set(options NOCOPY NOKEEP)
set(single_args LIBRARY LOCATION PHDR)
set(multi_args FILES)
cmake_parse_arguments(CODE_REL "${options}" "${single_args}"
"${multi_args}" ${ARGN})
# Argument validation
if(CODE_REL_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_code_relocate(${ARGV0} ...) "
"given unknown arguments: ${CODE_REL_UNPARSED_ARGUMENTS}")
endif()
if((NOT CODE_REL_FILES) AND (NOT CODE_REL_LIBRARY))
message(FATAL_ERROR
"zephyr_code_relocate() requires either FILES or LIBRARY be provided")
endif()
if(CODE_REL_FILES AND CODE_REL_LIBRARY)
message(FATAL_ERROR "zephyr_code_relocate() only accepts "
"one argument between FILES and LIBRARY")
endif()
if(NOT CODE_REL_LOCATION)
message(FATAL_ERROR "zephyr_code_relocate() requires a LOCATION argument")
endif()
if(CODE_REL_LIBRARY)
# Use cmake generator expression to convert library to file list,
# supporting relative and absolute paths
set(genex_src_dir "$<TARGET_PROPERTY:${CODE_REL_LIBRARY},SOURCE_DIR>")
set(genex_src_list "$<TARGET_PROPERTY:${CODE_REL_LIBRARY},SOURCES>")
if(CMAKE_HOST_WIN32)
# Note that this assumes windows absolute filenames start with a letter and colon, this does
# not support \\x network paths and is untested under the likes of msys2/cygwin
set(src_list_abs "$<FILTER:${genex_src_list},INCLUDE,^[A-Za-z]\:>")
set(src_list_rel "$<FILTER:${genex_src_list},EXCLUDE,^[A-Za-z]\:>")
else()
set(src_list_abs "$<FILTER:${genex_src_list},INCLUDE,^/>")
set(src_list_rel "$<FILTER:${genex_src_list},EXCLUDE,^/>")
endif()
set(src_list "${genex_src_dir}/$<JOIN:${src_list_rel},$<SEMICOLON>${genex_src_dir}/>")
set(nonempty_src_list "$<$<BOOL:${src_list_rel}>:${src_list}>")
set(sep_list "$<$<AND:$<BOOL:${src_list_abs}>,$<BOOL:${src_list_rel}>>:$<SEMICOLON>>")
set(file_list "${src_list_abs}${sep_list}${nonempty_src_list}")
else()
# Check if CODE_REL_FILES is a generator expression, if so leave it
# untouched.
string(GENEX_STRIP "${CODE_REL_FILES}" no_genex)
if(CODE_REL_FILES STREQUAL no_genex)
# no generator expression in CODE_REL_FILES, check if list of files
# is absolute
foreach(file ${CODE_REL_FILES})
if(NOT IS_ABSOLUTE ${file})
set(file ${CMAKE_CURRENT_SOURCE_DIR}/${file})
endif()
list(APPEND file_list ${file})
endforeach()
else()
# Generator expression is present in file list. Leave the list untouched.
set(file_list ${CODE_REL_FILES})
endif()
endif()
if(NOT CODE_REL_NOCOPY)
set(flag_list COPY)
else()
set(flag_list NOCOPY)
endif()
if(CODE_REL_NOKEEP)
list(APPEND flag_list NOKEEP)
endif()
if(CODE_REL_PHDR)
set(CODE_REL_LOCATION "${CODE_REL_LOCATION}\ :${CODE_REL_PHDR}")
endif()
# We use the "|" character to separate code relocation directives, instead of
# using set_property(APPEND) to produce a ";"-separated CMake list. This way,
# each directive can embed multiple CMake lists, representing flags and files,
# the latter of which can come from generator expressions.
get_property(code_rel_str TARGET code_data_relocation_target
PROPERTY COMPILE_DEFINITIONS)
set_property(TARGET code_data_relocation_target
PROPERTY COMPILE_DEFINITIONS
"${code_rel_str}|${CODE_REL_LOCATION}:${flag_list}:${file_list}")
endfunction()
# Usage:
# check_dtc_flag("-Wtest" DTC_WARN_TEST)
#
# Writes 1 to the output variable 'ok' if
# the flag is supported, otherwise writes 0.
#
# using
function(check_dtc_flag flag ok)
execute_process(
COMMAND
${DTC} ${flag} -v
ERROR_QUIET
OUTPUT_QUIET
RESULT_VARIABLE dtc_check_ret
)
if (dtc_check_ret EQUAL 0)
set(${ok} 1 PARENT_SCOPE)
else()
set(${ok} 0 PARENT_SCOPE)
endif()
endfunction()
# Function to round number to next power of two.
#
# Usage:
# pow2round(<variable>)
#
# Example:
# set(test 2)
# pow2round(test)
# # test is still 2
#
# set(test 5)
# pow2round(test)
# # test is now 8
#
# Arguments:
# n = Variable containing the number to round
function(pow2round n)
math(EXPR x "${${n}} & (${${n}} - 1)")
if(${x} EQUAL 0)
return()
endif()
math(EXPR ${n} "${${n}} | (${${n}} >> 1)")
math(EXPR ${n} "${${n}} | (${${n}} >> 2)")
math(EXPR ${n} "${${n}} | (${${n}} >> 4)")
math(EXPR ${n} "${${n}} | (${${n}} >> 8)")
math(EXPR ${n} "${${n}} | (${${n}} >> 16)")
math(EXPR ${n} "${${n}} | (${${n}} >> 32)")
math(EXPR ${n} "${${n}} + 1")
set(${n} ${${n}} PARENT_SCOPE)
endfunction()
# Function to create a build string based on BOARD, BOARD_REVISION, and BUILD
# type.
#
# This is a common function to ensure that build strings are always created
# in a uniform way.
# A single string is returned containing the full build string constructed from
# all arguments.
#
# When MERGE is supplied a list of build strings will be returned with the full
# build string as first item in the list.
# The full order of build strings returned in the list will be:
# - Full build string, including identifier and revision
# - Build string with board variants removed in addition
# - Build string with cpuset removed in addition
# - Build string with soc removed in addition
#
# If BUILD is supplied, then build type will be appended to each entry in the
# list above.
# If REVISION is supplied or obtained as system wide setting a build string
# with the sanitized revision string will be added in addition to the
# non-revisioned entry for each entry.
#
# Usage:
# zephyr_build_string(<out-variable>
# BOARD <board>
# [BOARD_IDENTIFIER <identifier>]
# [BOARD_REVISION <revision>]
# [BUILD <type>]
# [MERGE [REVERSE]]
# )
#
# <out-variable>: Output variable where the build string will be returned.
# BOARD <board>: Board name to use when creating the build string.
# BOARD_REVISION <revision>: Board revision to use when creating the build string.
# BUILD <type>: Build type to use when creating the build string.
# MERGE: Return a list of build identifiers instead of a single build string.
# REVERSE: Reverse the list before returning it.
#
# Examples
# calling
# zephyr_build_string(build_string BOARD alpha BUILD debug)
# will return the string `alpha_debug` in `build_string` parameter.
#
# calling
# zephyr_build_string(build_string BOARD alpha BOARD_REVISION 1.0.0 BUILD debug)
# will return the string `alpha_1_0_0_debug` in `build_string` parameter.
#
# calling
# zephyr_build_string(build_string BOARD alpha BOARD_IDENTIFIER /soc/bar)
# will return the string `alpha_soc_bar` in `build_string` parameter.
#
# calling
# zephyr_build_string(build_string BOARD alpha BOARD_REVISION 1.0.0 BOARD_IDENTIFIER /soc/bar MERGE)
# will return a list of the following strings
# `alpha_soc_bar_1_0_0;alpha_soc_bar;alpha_soc_1_0_0;alpha_soc;alpha_1_0_0;alpha` in `build_string` parameter.
#
function(zephyr_build_string outvar)
set(options MERGE REVERSE)
set(single_args BOARD BOARD_IDENTIFIER BOARD_REVISION BUILD)
cmake_parse_arguments(BUILD_STR "${options}" "${single_args}" "" ${ARGN})
if(BUILD_STR_UNPARSED_ARGUMENTS)
message(FATAL_ERROR
"zephyr_build_string(${ARGV0} <val> ...) given unknown arguments:"
" ${BUILD_STR_UNPARSED_ARGUMENTS}"
)
endif()
if(DEFINED BUILD_STR_BOARD_REVISION AND NOT BUILD_STR_BOARD)
message(FATAL_ERROR
"zephyr_build_string(${ARGV0} <list> BOARD_REVISION ${BUILD_STR_BOARD_REVISION} ...)"
" given without BOARD argument, please specify BOARD"
)
endif()
if(DEFINED BUILD_STR_BOARD_IDENTIFIER AND NOT BUILD_STR_BOARD)
message(FATAL_ERROR
"zephyr_build_string(${ARGV0} <list> BOARD_IDENTIFIER ${BUILD_STR_BOARD_IDENTIFIER} ...)"
" given without BOARD argument, please specify BOARD"
)
endif()
string(REPLACE "/" ";" str_segment_list "${BUILD_STR_BOARD}${BUILD_STR_BOARD_IDENTIFIER}")
string(REPLACE "." "_" revision_string "${BUILD_STR_BOARD_REVISION}")
string(JOIN "_" ${outvar} ${str_segment_list} ${revision_string} ${BUILD_STR_BUILD})
if(BUILD_STR_MERGE)
if(DEFINED BUILD_STR_BOARD_REVISION)
string(JOIN "_" variant_string ${str_segment_list} ${BUILD_STR_BUILD})
list(APPEND ${outvar} "${variant_string}")
endif()
list(POP_BACK str_segment_list)
while(NOT str_segment_list STREQUAL "")
if(DEFINED BUILD_STR_BOARD_REVISION)
string(JOIN "_" variant_string ${str_segment_list} ${revision_string} ${BUILD_STR_BUILD})
list(APPEND ${outvar} "${variant_string}")
endif()
string(JOIN "_" variant_string ${str_segment_list} ${BUILD_STR_BUILD})
list(APPEND ${outvar} "${variant_string}")
list(POP_BACK str_segment_list)
endwhile()
endif()
if(BUILD_STR_REVERSE)
list(REVERSE ${outvar})
endif()
# This updates the provided outvar in parent scope (callers scope)
set(${outvar} ${${outvar}} PARENT_SCOPE)
endfunction()
# Function to add header file(s) to the list to be passed to syscall generator.
function(zephyr_syscall_header)
foreach(one_file ${ARGV})
if(EXISTS ${one_file})
set(header_file ${one_file})
elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${one_file})
set(header_file ${CMAKE_CURRENT_SOURCE_DIR}/${one_file})
else()
message(FATAL_ERROR "Syscall header file not found: ${one_file}")
endif()
target_sources(
syscalls_interface INTERFACE
${header_file}
)
target_include_directories(
syscalls_interface INTERFACE
${header_file}
)
add_dependencies(
syscalls_interface
${header_file}
)
unset(header_file)
endforeach()
endfunction()
# Function to add header file(s) to the list to be passed to syscall generator
# if condition is true.
function(zephyr_syscall_header_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_syscall_header(${ARGN})
endif()
endfunction()
# Verify blobs fetched using west. If the sha256 checksum isn't valid, a warning/
# fatal error message is printed (depends on REQUIRED flag).
#
# Usage:
# zephyr_blobs_verify(<MODULE module|FILES file [files...]> [REQUIRED])
#
# Example:
# zephyr_blobs_verify(MODULE my_module REQUIRED) # verify all blobs in my_module and fail on error
# zephyr_blobs_verify(FILES img/file.bin) # verify a single file and print on error
function(zephyr_blobs_verify)
cmake_parse_arguments(BLOBS_VERIFY "REQUIRED" "MODULE" "FILES" ${ARGN})
if((DEFINED BLOBS_VERIFY_MODULE) EQUAL (DEFINED BLOBS_VERIFY_FILES))
message(FATAL_ERROR "Either MODULE or FILES required when calling ${CMAKE_CURRENT_FUNCTION}")
endif()
if(NOT WEST)
return()
endif()
execute_process(
COMMAND ${WEST} blobs list ${BLOBS_VERIFY_MODULE} --format "{status} {abspath}"
OUTPUT_VARIABLE BLOBS_LIST_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
if(${BLOBS_VERIFY_REQUIRED})
set(msg_lvl FATAL_ERROR)
else()
set(msg_lvl WARNING)
endif()
string(REPLACE "\n" ";" BLOBS_LIST ${BLOBS_LIST_OUTPUT})
if(DEFINED BLOBS_VERIFY_FILES)
foreach(file ${BLOBS_VERIFY_FILES})
# Resolve path.
if(IS_ABSOLUTE ${file})
file(REAL_PATH "${file}" real_path)
else()
file(REAL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${file}" real_path)
endif()
file(TO_NATIVE_PATH ${real_path} path)
message(VERBOSE "Verifying blob \"${path}\"")
# Each path that has a correct sha256 is prefixed with an A
if(NOT "A ${path}" IN_LIST BLOBS_LIST)
message(${msg_lvl} "Blob for path \"${path}\" isn't valid.")
endif()
endforeach()
else()
foreach(blob ${BLOBS_LIST})
separate_arguments(blob)
list(GET blob 0 status)
list(GET blob 1 path)
message(VERBOSE "Verifying blob \"${path}\"")
if(NOT "${status}" STREQUAL "A")
message(${msg_lvl} "Blob for path \"${path}\" isn't valid. Update with: west blobs fetch ${BLOBS_VERIFY_MODULE}")
endif()
endforeach()
endif()
endfunction()
########################################################
# 2. Kconfig-aware extensions
########################################################
#
# Kconfig is a configuration language developed for the Linux
# kernel. The below functions integrate CMake with Kconfig.
#
# 2.1 Misc
#
# import_kconfig(<prefix> <kconfig_fragment> [<keys>] [TARGET <target>])
#
# Parse a KConfig fragment (typically with extension .config) and
# introduce all the symbols that are prefixed with 'prefix' into the
# CMake namespace. List all created variable names in the 'keys'
# output variable if present.
#
# <prefix> : symbol prefix of settings in the Kconfig fragment.
# <kconfig_fragment>: absolute path to the config fragment file.
# <keys> : output variable which will be populated with variable
# names loaded from the kconfig fragment.
# TARGET <target> : set all symbols on <target> instead of adding them to the
# CMake namespace.
function(import_kconfig prefix kconfig_fragment)
cmake_parse_arguments(IMPORT_KCONFIG "" "TARGET" "" ${ARGN})
file(
STRINGS
${kconfig_fragment}
DOT_CONFIG_LIST
ENCODING "UTF-8"
)
foreach (LINE ${DOT_CONFIG_LIST})
if("${LINE}" MATCHES "^(${prefix}[^=]+)=([ymn]|.+$)")
# Matched a normal value assignment, like: CONFIG_NET_BUF=y
# Note: if the value starts with 'y', 'm', or 'n', then we assume it's a
# bool or tristate (we don't know the type from <kconfig_fragment> alone)
# and we only match the first character. This is to align with Kconfiglib.
set(CONF_VARIABLE_NAME "${CMAKE_MATCH_1}")
set(CONF_VARIABLE_VALUE "${CMAKE_MATCH_2}")
elseif("${LINE}" MATCHES "^# (${prefix}[^ ]+) is not set")
# Matched something like: # CONFIG_FOO is not set
# This is interpreted as: CONFIG_FOO=n
set(CONF_VARIABLE_NAME "${CMAKE_MATCH_1}")
set(CONF_VARIABLE_VALUE "n")
else()
# Ignore this line.
# Note: we also ignore assignments which don't have the desired <prefix>.
continue()
endif()
# If the provided value is n, then the corresponding CMake variable or
# target property will be unset.
if("${CONF_VARIABLE_VALUE}" STREQUAL "n")
if(DEFINED IMPORT_KCONFIG_TARGET)
set_property(TARGET ${IMPORT_KCONFIG_TARGET} PROPERTY "${CONF_VARIABLE_NAME}")
else()
unset("${CONF_VARIABLE_NAME}" PARENT_SCOPE)
endif()
list(REMOVE_ITEM keys "${CONF_VARIABLE_NAME}")
continue()
endif()
# Otherwise, the variable/property will be set to the provided value.
# For string values, we also remove the surrounding quotation marks.
if("${CONF_VARIABLE_VALUE}" MATCHES "^\"(.*)\"$")
set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
endif()
if(DEFINED IMPORT_KCONFIG_TARGET)
set_property(TARGET ${IMPORT_KCONFIG_TARGET} PROPERTY "${CONF_VARIABLE_NAME}" "${CONF_VARIABLE_VALUE}")
else()
set("${CONF_VARIABLE_NAME}" "${CONF_VARIABLE_VALUE}" PARENT_SCOPE)
endif()
list(APPEND keys "${CONF_VARIABLE_NAME}")
endforeach()
if(DEFINED IMPORT_KCONFIG_TARGET)
set_property(TARGET ${IMPORT_KCONFIG_TARGET} PROPERTY "kconfigs" "${keys}")
endif()
list(LENGTH IMPORT_KCONFIG_UNPARSED_ARGUMENTS unparsed_length)
if(unparsed_length GREATER 0)
if(unparsed_length GREATER 1)
# Two mandatory arguments and one optional, anything after that is an error.
list(GET IMPORT_KCONFIG_UNPARSED_ARGUMENTS 1 first_invalid)
message(FATAL_ERROR "Unexpected argument after '<keys>': import_kconfig(... ${first_invalid})")
endif()
set(${IMPORT_KCONFIG_UNPARSED_ARGUMENTS} "${keys}" PARENT_SCOPE)
endif()
endfunction()
########################################################
# 3. CMake-generic extensions
########################################################
#
# These functions extend the CMake API in a way that is not particular
# to Zephyr. Primarily they work around limitations in the CMake
# language to allow cleaner build scripts.
# 3.1. *_ifdef
#
# Functions for conditionally executing CMake functions with oneliners
# e.g.
#
# if(CONFIG_FFT)
# zephyr_library_source(
# fft_32.c
# fft_utils.c
# )
# endif()
#
# Becomes
#
# zephyr_source_ifdef(
# CONFIG_FFT
# fft_32.c
# fft_utils.c
# )
#
# More Generally
# "<function-name>_ifdef(CONDITION args)"
# Becomes
# """
# if(CONDITION)
# <function-name>(args)
# endif()
# """
#
# ifdef functions are added on an as-need basis. See
# https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
# a list of available functions.
function(add_subdirectory_ifdef feature_toggle source_dir)
if(${${feature_toggle}})
add_subdirectory(${source_dir} ${ARGN})
endif()
endfunction()
function(target_sources_ifdef feature_toggle target scope item)
if(${${feature_toggle}})
target_sources(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_compile_definitions_ifdef feature_toggle target scope item)
if(${${feature_toggle}})
target_compile_definitions(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_include_directories_ifdef feature_toggle target scope item)
if(${${feature_toggle}})
target_include_directories(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_link_libraries_ifdef feature_toggle target item)
if(${${feature_toggle}})
target_link_libraries(${target} ${item} ${ARGN})
endif()
endfunction()
function(add_compile_option_ifdef feature_toggle option)
if(${${feature_toggle}})
add_compile_options(${option})
endif()
endfunction()
function(target_compile_option_ifdef feature_toggle target scope option)
if(${feature_toggle})
target_compile_options(${target} ${scope} ${option})
endif()
endfunction()
function(target_cc_option_ifdef feature_toggle target scope option)
if(${feature_toggle})
target_cc_option(${target} ${scope} ${option})
endif()
endfunction()
function(zephyr_library_sources_ifdef feature_toggle source)
if(${${feature_toggle}})
zephyr_library_sources(${source} ${ARGN})
endif()
endfunction()
function(zephyr_sources_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_sources(${ARGN})
endif()
endfunction()
function(zephyr_cc_option_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_cc_option(${ARGN})
endif()
endfunction()
function(zephyr_ld_option_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_ld_options(${ARGN})
endif()
endfunction()
function(zephyr_link_libraries_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_link_libraries(${ARGN})
endif()
endfunction()
function(zephyr_compile_options_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_compile_options(${ARGN})
endif()
endfunction()
function(zephyr_compile_definitions_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_compile_definitions(${ARGN})
endif()
endfunction()
function(zephyr_include_directories_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_include_directories(${ARGN})
endif()
endfunction()
function(zephyr_library_compile_definitions_ifdef feature_toggle item)
if(${${feature_toggle}})
zephyr_library_compile_definitions(${item} ${ARGN})
endif()
endfunction()
function(zephyr_library_include_directories_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_library_include_directories(${ARGN})
endif()
endfunction()
function(zephyr_library_compile_options_ifdef feature_toggle item)
if(${${feature_toggle}})
zephyr_library_compile_options(${item} ${ARGN})
endif()
endfunction()
function(zephyr_link_interface_ifdef feature_toggle interface)
if(${${feature_toggle}})
target_link_libraries(${interface} INTERFACE zephyr_interface)
endif()
endfunction()
function(zephyr_library_link_libraries_ifdef feature_toggle item)
if(${${feature_toggle}})
zephyr_library_link_libraries(${item})
endif()
endfunction()
function(zephyr_linker_sources_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_linker_sources(${ARGN})
endif()
endfunction()
function(zephyr_library_add_dependencies_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_library_add_dependencies(${ARGN})
endif()
endfunction()
macro(list_append_ifdef feature_toggle list)
if(${${feature_toggle}})
list(APPEND ${list} ${ARGN})
endif()
endmacro()
# 3.2. *_ifndef
# See 3.1 *_ifdef
function(set_ifndef variable value)
if(NOT ${variable})
set(${variable} ${value} ${ARGN} PARENT_SCOPE)
endif()
endfunction()
function(add_subdirectory_ifndef feature_toggle source_dir)
if(NOT ${feature_toggle})
add_subdirectory(${source_dir} ${ARGN})
endif()
endfunction()
function(target_sources_ifndef feature_toggle target scope item)
if(NOT ${feature_toggle})
target_sources(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_compile_definitions_ifndef feature_toggle target scope item)
if(NOT ${feature_toggle})
target_compile_definitions(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_include_directories_ifndef feature_toggle target scope item)
if(NOT ${feature_toggle})
target_include_directories(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
function(target_link_libraries_ifndef feature_toggle target item)
if(NOT ${feature_toggle})
target_link_libraries(${target} ${item} ${ARGN})
endif()
endfunction()
function(add_compile_option_ifndef feature_toggle option)
if(NOT ${feature_toggle})
add_compile_options(${option})
endif()
endfunction()
function(target_compile_option_ifndef feature_toggle target scope option)
if(NOT ${feature_toggle})
target_compile_options(${target} ${scope} ${option})
endif()
endfunction()
function(target_cc_option_ifndef feature_toggle target scope option)
if(NOT ${feature_toggle})
target_cc_option(${target} ${scope} ${option})
endif()
endfunction()
function(zephyr_library_sources_ifndef feature_toggle source)
if(NOT ${feature_toggle})
zephyr_library_sources(${source} ${ARGN})
endif()
endfunction()
function(zephyr_sources_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_sources(${ARGN})
endif()
endfunction()
function(zephyr_cc_option_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_cc_option(${ARGN})
endif()
endfunction()
function(zephyr_ld_option_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_ld_options(${ARGN})
endif()
endfunction()
function(zephyr_link_libraries_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_link_libraries(${ARGN})
endif()
endfunction()
function(zephyr_compile_options_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_compile_options(${ARGN})
endif()
endfunction()
function(zephyr_compile_definitions_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_compile_definitions(${ARGN})
endif()
endfunction()
function(zephyr_include_directories_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_include_directories(${ARGN})
endif()
endfunction()
function(zephyr_library_compile_definitions_ifndef feature_toggle item)
if(NOT ${feature_toggle})
zephyr_library_compile_definitions(${item} ${ARGN})
endif()
endfunction()
function(zephyr_library_include_directories_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_library_include_directories(${ARGN})
endif()
endfunction()
function(zephyr_library_compile_options_ifndef feature_toggle item)
if(NOT ${feature_toggle})
zephyr_library_compile_options(${item} ${ARGN})
endif()
endfunction()
function(zephyr_link_interface_ifndef feature_toggle interface)
if(NOT ${feature_toggle})
target_link_libraries(${interface} INTERFACE zephyr_interface)
endif()
endfunction()
function(zephyr_library_link_libraries_ifndef feature_toggle item)
if(NOT ${feature_toggle})
zephyr_library_link_libraries(${item})
endif()
endfunction()
function(zephyr_linker_sources_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_linker_sources(${ARGN})
endif()
endfunction()
function(zephyr_library_add_dependencies_ifndef feature_toggle)
if(NOT ${feature_toggle})
zephyr_library_add_dependencies(${ARGN})
endif()
endfunction()
macro(list_append_ifndef feature_toggle list)
if(NOT ${feature_toggle})
list(APPEND ${list} ${ARGN})
endif()
endmacro()
# 3.3. *_option Compiler-compatibility checks
#
# Utility functions for silently omitting compiler flags when the
# compiler lacks support. *_cc_option was ported from KBuild, see
# cc-option in
# https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt
# Writes 1 to the output variable 'ok' for the language 'lang' if
# the flag is supported, otherwise writes 0.
#
# lang must be C or CXX
#
# TODO: Support ASM
#
# Usage:
#
# check_compiler_flag(C "-Wall" my_check)
# print(my_check) # my_check is now 1
function(check_compiler_flag lang option ok)
if(NOT DEFINED CMAKE_REQUIRED_QUIET)
set(CMAKE_REQUIRED_QUIET 1)
endif()
string(MAKE_C_IDENTIFIER
"check${option}_${lang}_${CMAKE_REQUIRED_FLAGS}"
${ok}
)
if(${lang} STREQUAL C)
check_c_compiler_flag("${option}" ${${ok}})
else()
check_cxx_compiler_flag("${option}" ${${ok}})
endif()
if(${${${ok}}})
set(ret 1)
else()
set(ret 0)
endif()
set(${ok} ${ret} PARENT_SCOPE)
endfunction()
function(target_cc_option target scope option)
target_cc_option_fallback(${target} ${scope} ${option} "")
endfunction()
# Support an optional second option for when the first option is not
# supported.
function(target_cc_option_fallback target scope option1 option2)
if(CONFIG_CPP)
foreach(lang C CXX)
# For now, we assume that all flags that apply to C/CXX also
# apply to ASM.
zephyr_check_compiler_flag(${lang} ${option1} check)
if(${check})
target_compile_options(${target} ${scope}
$<$<COMPILE_LANGUAGE:${lang}>:${option1}>
$<$<COMPILE_LANGUAGE:ASM>:${option1}>
)
elseif(option2)
target_compile_options(${target} ${scope}
$<$<COMPILE_LANGUAGE:${lang}>:${option2}>
$<$<COMPILE_LANGUAGE:ASM>:${option2}>
)
endif()
endforeach()
else()
zephyr_check_compiler_flag(C ${option1} check)
if(${check})
target_compile_options(${target} ${scope} ${option1})
elseif(option2)
target_compile_options(${target} ${scope} ${option2})
endif()
endif()
endfunction()
function(target_ld_options target scope)
zephyr_get_parse_args(args ${ARGN})
list(REMOVE_ITEM ARGN NO_SPLIT)
foreach(option ${ARGN})
if(args_NO_SPLIT)
set(option ${ARGN})
endif()
string(JOIN "" check_identifier "check" ${option})
string(MAKE_C_IDENTIFIER ${check_identifier} check)
set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
string(JOIN " " CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${option})
zephyr_check_compiler_flag(C "" ${check})
set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS})
target_link_libraries_ifdef(${check} ${target} ${scope} ${option})
if(args_NO_SPLIT)
break()
endif()
endforeach()
endfunction()
# 3.3.1 Toolchain integration
#
# 'toolchain_parse_make_rule' is a function that parses the output of
# 'gcc -M'.
#
# The argument 'input_file' is in input parameter with the path to the
# file with the dependency information.
#
# The argument 'include_files' is an output parameter with the result
# of parsing the include files.
function(toolchain_parse_make_rule input_file include_files)
file(STRINGS ${input_file} input)
# The file is formatted like this:
# empty_file.o: misc/empty_file.c \
# nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts \
# nrf52840_qiaa.dtsi
# The dep file will contain `\` for line continuation.
# This results in `\;` which is then treated a the char `;` instead of
# the element separator, so let's get the pure `;` back.
string(REPLACE "\;" ";" input_as_list ${input})
# Pop the first line and treat it specially
list(POP_FRONT input_as_list first_input_line)
string(FIND ${first_input_line} ": " index)
math(EXPR j "${index} + 2")
string(SUBSTRING ${first_input_line} ${j} -1 first_include_file)
# Remove whitespace before and after filename and convert to CMake path.
string(STRIP "${first_include_file}" first_include_file)
file(TO_CMAKE_PATH "${first_include_file}" first_include_file)
set(result "${first_include_file}")
# Remove whitespace before and after filename and convert to CMake path.
foreach(file ${input_as_list})
string(STRIP "${file}" file)
file(TO_CMAKE_PATH "${file}" file)
list(APPEND result "${file}")
endforeach()
set(${include_files} ${result} PARENT_SCOPE)
endfunction()
# 'check_set_linker_property' is a function that check the provided linker
# flag and only set the linker property if the check succeeds
#
# This function is similar in nature to the CMake set_property function, but
# with the extension that it will check that the linker supports the flag before
# setting the property.
#
# APPEND: Flag indicated that the property should be appended to the existing
# value list for the property.
# TARGET: Name of target on which to add the property (commonly: linker)
# PROPERTY: Name of property with the value(s) following immediately after
# property name
function(check_set_linker_property)
set(options APPEND)
set(single_args TARGET)
set(multi_args PROPERTY)
cmake_parse_arguments(LINKER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(LINKER_PROPERTY_APPEND)
set(APPEND "APPEND")
endif()
list(GET LINKER_PROPERTY_PROPERTY 0 property)
list(REMOVE_AT LINKER_PROPERTY_PROPERTY 0)
set(option ${LINKER_PROPERTY_PROPERTY})
string(MAKE_C_IDENTIFIER check${option} check)
set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${option}")
zephyr_check_compiler_flag(C "" ${check})
set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS})
if(${${check}})
set_property(TARGET ${LINKER_PROPERTY_TARGET} ${APPEND} PROPERTY ${property} ${option})
endif()
endfunction()
# 'set_compiler_property' is a function that sets the property for the C and
# C++ property targets used for toolchain abstraction.
#
# This function is similar in nature to the CMake set_property function, but
# with the extension that it will set the property on both the compile and
# compiler-cpp targets.
#
# APPEND: Flag indicated that the property should be appended to the existing
# value list for the property.
# PROPERTY: Name of property with the value(s) following immediately after
# property name
function(set_compiler_property)
set(options APPEND)
set(multi_args PROPERTY)
cmake_parse_arguments(COMPILER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(COMPILER_PROPERTY_APPEND)
set(APPEND "APPEND")
set(APPEND-CPP "APPEND")
endif()
set_property(TARGET compiler ${APPEND} PROPERTY ${COMPILER_PROPERTY_PROPERTY})
set_property(TARGET compiler-cpp ${APPEND} PROPERTY ${COMPILER_PROPERTY_PROPERTY})
endfunction()
# 'check_set_compiler_property' is a function that check the provided compiler
# flag and only set the compiler or compiler-cpp property if the check succeeds
#
# This function is similar in nature to the CMake set_property function, but
# with the extension that it will check that the compiler supports the flag
# before setting the property on compiler or compiler-cpp targets.
#
# To test flags together, such as '-Wformat -Wformat-security', an option group
# can be specified by using shell-like quoting along with a 'SHELL:' prefix.
# The 'SHELL:' prefix will be dropped before testing, so that
# '"SHELL:-Wformat -Wformat-security"' becomes '-Wformat -Wformat-security' for
# testing.
#
# APPEND: Flag indicated that the property should be appended to the existing
# value list for the property.
# PROPERTY: Name of property with the value(s) following immediately after
# property name
function(check_set_compiler_property)
set(options APPEND)
set(multi_args PROPERTY)
cmake_parse_arguments(COMPILER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(COMPILER_PROPERTY_APPEND)
set(APPEND "APPEND")
set(APPEND-CPP "APPEND")
endif()
list(GET COMPILER_PROPERTY_PROPERTY 0 property)
list(REMOVE_AT COMPILER_PROPERTY_PROPERTY 0)
foreach(option ${COMPILER_PROPERTY_PROPERTY})
if(${option} MATCHES "^SHELL:")
string(REGEX REPLACE "^SHELL:" "" option ${option})
separate_arguments(option UNIX_COMMAND ${option})
endif()
if(CONFIG_CPP)
zephyr_check_compiler_flag(CXX "${option}" check)
if(${check})
set_property(TARGET compiler-cpp ${APPEND-CPP} PROPERTY ${property} ${option})
set(APPEND-CPP "APPEND")
endif()
endif()
zephyr_check_compiler_flag(C "${option}" check)
if(${check})
set_property(TARGET compiler ${APPEND} PROPERTY ${property} ${option})
set(APPEND "APPEND")
endif()
endforeach()
endfunction()
# 3.4. Debugging CMake
# Usage:
# print(BOARD)
#
# will print: "BOARD: nrf52dk"
function(print arg)
message(STATUS "${arg}: ${${arg}}")
endfunction()
# Usage:
# assert(ZEPHYR_TOOLCHAIN_VARIANT "ZEPHYR_TOOLCHAIN_VARIANT not set.")
#
# will cause a FATAL_ERROR and print an error message if the first
# expression is false
macro(assert test comment)
if(NOT ${test})
message(FATAL_ERROR "Assertion failed: ${comment}")
endif()
endmacro()
# Usage:
# assert_not(OBSOLETE_VAR "OBSOLETE_VAR has been removed; use NEW_VAR instead")
#
# will cause a FATAL_ERROR and print an error message if the first
# expression is true
macro(assert_not test comment)
if(${test})
message(FATAL_ERROR "Assertion failed: ${comment}")
endif()
endmacro()
# Usage:
# assert_exists(CMAKE_READELF)
#
# will cause a FATAL_ERROR if there is no file or directory behind the
# variable
macro(assert_exists var)
if(NOT EXISTS ${${var}})
message(FATAL_ERROR "No such file or directory: ${var}: '${${var}}'")
endif()
endmacro()
# 3.5. File system management
function(generate_unique_target_name_from_filename filename target_name)
get_filename_component(basename ${filename} NAME)
string(REPLACE "." "_" x ${basename})
string(REPLACE "@" "_" x ${x})
string(MD5 unique_chars ${filename})
set(${target_name} gen_${x}_${unique_chars} PARENT_SCOPE)
endfunction()
# Usage:
# zephyr_file(<mode> <arg> ...)
#
# Zephyr file function extension.
# This function currently supports the following <modes>
#
# APPLICATION_ROOT <path>: Check all paths in provided variable, and convert
# those paths that are defined with `-D<path>=<val>`
# to absolute path, relative from `APPLICATION_SOURCE_DIR`
# Issue an error for any relative path not specified
# by user with `-D<path>`
#
# returns an updated list of absolute paths
#
# Usage:
# zephyr_file(CONF_FILES <paths> [DTS <list>] [KCONF <list>]
# [BOARD <board> [BOARD_REVISION <revision>] | NAMES <name> ...]
# [BUILD <type>] [SUFFIX <suffix>] [REQUIRED]
# )
#
# CONF_FILES <paths>: Find all configuration files in the list of paths and
# return them in a list. If paths is empty then no configuration
# files are returned. Configuration files will be:
# - DTS: Overlay files (.overlay)
# - Kconfig: Config fragments (.conf)
# - defconfig: defconfig files (_defconfig)
# The conf file search will return existing configuration
# files for the current board.
# CONF_FILES takes the following additional arguments:
# BOARD <board>: Find configuration files for specified board.
# BOARD_REVISION <revision>: Find configuration files for specified board
# revision. Requires BOARD to be specified.
#
# If no board is given the current BOARD and
# BOARD_REVISION will be used, unless NAMES are
# specified.
#
# NAMES <name1> [name2] ... List of file names to look for and instead of
# creating file names based on board settings.
# Only the first match found in <paths> will be
# returned in the <list>
#
# DTS <list>: List to append DTS overlay files in <path> to
# KCONF <list>: List to append Kconfig fragment files in <path> to
# DEFCONF <list>: List to append _defconfig files in <path> to
# BUILD <type>: Build type to include for search.
# For example:
# BUILD debug, will look for <board>_debug.conf
# and <board>_debug.overlay, instead of <board>.conf
# SUFFIX <name>: Suffix name to check for instead of the default name
# but with a fallback to the default name if not found.
# For example:
# SUFFIX fish, will look for <file>_fish.conf and use
# if found but will use <file>.conf if not found
# REQUIRED: Option to indicate that the <list> specified by DTS or KCONF
# must contain at least one element, else an error will be raised.
#
function(zephyr_file)
set(file_options APPLICATION_ROOT CONF_FILES)
if((ARGC EQUAL 0) OR (NOT (ARGV0 IN_LIST file_options)))
message(FATAL_ERROR "No <mode> given to `zephyr_file(<mode> <args>...)` function,\n \
Please provide one of following: APPLICATION_ROOT, CONF_FILES")
endif()
if(${ARGV0} STREQUAL APPLICATION_ROOT)
set(single_args APPLICATION_ROOT)
elseif(${ARGV0} STREQUAL CONF_FILES)
set(options REQUIRED)
set(single_args BOARD BOARD_REVISION BOARD_IDENTIFIER DTS KCONF DEFCONFIG BUILD SUFFIX)
set(multi_args CONF_FILES NAMES)
endif()
cmake_parse_arguments(FILE "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(FILE_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_file(${ARGV0} <val> ...) given unknown arguments: ${FILE_UNPARSED_ARGUMENTS}")
endif()
if(FILE_APPLICATION_ROOT)
# Note: user can do: `-D<var>=<relative-path>` and app can at same
# time specify `list(APPEND <var> <abs-path>)`
# Thus need to check and update only CACHED variables (-D<var>).
set(CACHED_PATH $CACHE{${FILE_APPLICATION_ROOT}})
foreach(path ${CACHED_PATH})
# The cached variable is relative path, i.e. provided by `-D<var>` or
# `set(<var> CACHE)`, so let's update current scope variable to absolute
# path from `APPLICATION_SOURCE_DIR`.
if(NOT IS_ABSOLUTE ${path})
set(abs_path ${APPLICATION_SOURCE_DIR}/${path})
list(FIND ${FILE_APPLICATION_ROOT} ${path} index)
if(NOT ${index} LESS 0)
list(REMOVE_AT ${FILE_APPLICATION_ROOT} ${index})
list(INSERT ${FILE_APPLICATION_ROOT} ${index} ${abs_path})
endif()
endif()
endforeach()
# Now all cached relative paths has been updated.
# Let's check if anyone uses relative path as scoped variable, and fail
foreach(path ${${FILE_APPLICATION_ROOT}})
if(NOT IS_ABSOLUTE ${path})
message(FATAL_ERROR
"Relative path encountered in scoped variable: ${FILE_APPLICATION_ROOT}, value=${path}\n \
Please adjust any `set(${FILE_APPLICATION_ROOT} ${path})` or `list(APPEND ${FILE_APPLICATION_ROOT} ${path})`\n \
to absolute path using `\${CMAKE_CURRENT_SOURCE_DIR}/${path}` or similar. \n \
Relative paths are only allowed with `-D${ARGV1}=<path>`")
endif()
endforeach()
# This updates the provided argument in parent scope (callers scope)
set(${FILE_APPLICATION_ROOT} ${${FILE_APPLICATION_ROOT}} PARENT_SCOPE)
endif()
if(FILE_CONF_FILES)
if(DEFINED FILE_BOARD_REVISION AND NOT FILE_BOARD)
message(FATAL_ERROR
"zephyr_file(${ARGV0} <path> BOARD_REVISION ${FILE_BOARD_REVISION} ...)"
" given without BOARD argument, please specify BOARD"
)
endif()
if(NOT DEFINED FILE_BOARD)
# Defaulting to system wide settings when BOARD is not given as argument
set(FILE_BOARD ${BOARD})
if(DEFINED BOARD_REVISION)
set(FILE_BOARD_REVISION ${BOARD_REVISION})
endif()
if(DEFINED BOARD_IDENTIFIER)
set(FILE_BOARD_IDENTIFIER ${BOARD_IDENTIFIER})
endif()
endif()
if(FILE_NAMES)
set(dts_filename_list ${FILE_NAMES})
set(kconf_filename_list ${FILE_NAMES})
else()
zephyr_build_string(filename_list
BOARD ${FILE_BOARD}
BOARD_REVISION ${FILE_BOARD_REVISION}
BOARD_IDENTIFIER ${FILE_BOARD_IDENTIFIER}
BUILD ${FILE_BUILD}
MERGE REVERSE
)
list(REMOVE_DUPLICATES filename_list)
set(dts_filename_list ${filename_list})
list(TRANSFORM dts_filename_list APPEND ".overlay")
set(kconf_filename_list ${filename_list})
list(TRANSFORM kconf_filename_list APPEND ".conf")
endif()
if(FILE_DTS)
foreach(path ${FILE_CONF_FILES})
foreach(filename ${dts_filename_list})
if(NOT IS_ABSOLUTE ${filename})
set(test_file ${path}/${filename})
else()
set(test_file ${filename})
endif()
zephyr_file_suffix(test_file SUFFIX ${FILE_SUFFIX})
if(EXISTS ${test_file})
list(APPEND ${FILE_DTS} ${test_file})
if(DEFINED FILE_BUILD)
set(deprecated_file_found y)
endif()
if(FILE_NAMES)
break()
endif()
endif()
endforeach()
endforeach()
# This updates the provided list in parent scope (callers scope)
set(${FILE_DTS} ${${FILE_DTS}} PARENT_SCOPE)
if(NOT ${FILE_DTS})
set(not_found ${dts_filename_list})
endif()
endif()
if(FILE_KCONF)
foreach(path ${FILE_CONF_FILES})
foreach(filename ${kconf_filename_list})
if(NOT IS_ABSOLUTE ${filename})
set(test_file ${path}/${filename})
else()
set(test_file ${filename})
endif()
zephyr_file_suffix(test_file SUFFIX ${FILE_SUFFIX})
if(EXISTS ${test_file})
list(APPEND ${FILE_KCONF} ${test_file})
if(DEFINED FILE_BUILD)
set(deprecated_file_found y)
endif()
if(FILE_NAMES)
break()
endif()
endif()
endforeach()
endforeach()
# This updates the provided list in parent scope (callers scope)
set(${FILE_KCONF} ${${FILE_KCONF}} PARENT_SCOPE)
if(NOT ${FILE_KCONF})
set(not_found ${kconf_filename_list})
endif()
endif()
if(FILE_REQUIRED AND DEFINED not_found)
message(FATAL_ERROR
"No ${not_found} file(s) was found in the ${FILE_CONF_FILES} folder(s), "
"please read the Zephyr documentation on application development."
)
endif()
if(deprecated_file_found)
message(DEPRECATION "prj_<build>.conf was deprecated after Zephyr 3.5,"
" you should switch to using -DFILE_SUFFIX instead")
endif()
if(FILE_DEFCONFIG)
foreach(path ${FILE_CONF_FILES})
foreach(filename ${filename_list})
if(EXISTS ${path}/${filename}_defconfig)
list(APPEND ${FILE_DEFCONFIG} ${path}/${filename}_defconfig)
endif()
endforeach()
endforeach()
# This updates the provided list in parent scope (callers scope)
set(${FILE_DEFCONFIG} ${${FILE_DEFCONFIG}} PARENT_SCOPE)
endif()
endif()
endfunction()
# Usage:
# zephyr_file_copy(<oldname> <newname> [ONLY_IF_DIFFERENT])
#
# Zephyr file copy extension.
# This function is similar to CMake function
# 'file(COPY_FILE <oldname> <newname> [ONLY_IF_DIFFERENT])'
# introduced with CMake 3.21.
#
# Because the minimal required CMake version with Zephyr is 3.20, this function
# is not guaranteed to be available.
#
# When using CMake version 3.21 or newer 'zephyr_file_copy()' simply calls
# 'file(COPY_FILE...)' directly.
# When using CMake version 3.20, the implementation will execute using CMake
# for running command line tool in a subprocess for identical functionality.
function(zephyr_file_copy oldname newname)
set(options ONLY_IF_DIFFERENT)
cmake_parse_arguments(ZEPHYR_FILE_COPY "${options}" "" "" ${ARGN})
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0)
if(ZEPHYR_FILE_COPY_ONLY_IF_DIFFERENT)
set(copy_file_options ONLY_IF_DIFFERENT)
endif()
file(COPY_FILE ${oldname} ${newname} ${copy_file_options})
else()
if(ZEPHYR_FILE_COPY_ONLY_IF_DIFFERENT)
set(copy_file_command copy_if_different)
else()
set(copy_file_command copy)
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} -E ${copy_file_command} ${oldname} ${newname}
)
endif()
endfunction()
# Usage:
# zephyr_file_suffix(<filename> SUFFIX <suffix>)
#
# Zephyr file add suffix extension.
# This function will check the provied filename or list of filenames to see if they have a
# `_<suffix>` extension to them and if so, updates the supplied variable/list with the new
# path/paths.
#
# <filename>: Variable (singlular or list) of absolute path filename(s) which should be checked
# and updated if there is a filename which has the <suffix> present.
# <suffix>: The suffix to test for and append to the end of the provided filename.
#
# Returns an updated variable of absolute path(s)
#
function(zephyr_file_suffix filename)
set(single_args SUFFIX)
cmake_parse_arguments(FILE "" "${single_args}" "" ${ARGN})
if(NOT DEFINED FILE_SUFFIX OR NOT DEFINED ${filename})
# If the file suffix variable is not known then there is nothing to do, return early
return()
endif()
set(tmp_new_list)
foreach(file ${${filename}})
if("${file}" STREQUAL "")
# Skip checking empty variables
continue()
endif()
# Search for the full stop so we know where to add the file suffix before the file extension
cmake_path(GET file EXTENSION file_ext)
cmake_path(REMOVE_EXTENSION file OUTPUT_VARIABLE new_filename)
cmake_path(APPEND_STRING new_filename "_${FILE_SUFFIX}${file_ext}")
# Use the filename with the suffix if it exists, if not then fall back to the default
if(EXISTS "${new_filename}")
list(APPEND tmp_new_list ${new_filename})
else()
list(APPEND tmp_new_list ${file})
endif()
endforeach()
# Update supplied variable if it differs
if(NOT "${${filename}}" STREQUAL "${tmp_new_list}")
set(${filename} "${tmp_new_list}" PARENT_SCOPE)
endif()
endfunction()
# Usage:
# zephyr_string(<mode> <out-var> <input> ...)
#
# Zephyr string function extension.
# This function extends the CMake string function by providing additional
# manipulation arguments to CMake string.
#
# SANITIZE: Ensure that the output string does not contain any special
# characters. Special characters, such as -, +, =, $, etc. are
# converted to underscores '_'.
#
# SANITIZE TOUPPER: Ensure that the output string does not contain any special
# characters. Special characters, such as -, +, =, $, etc. are
# converted to underscores '_'.
# The sanitized string will be returned in UPPER case.
#
# returns the updated string
function(zephyr_string)
set(options SANITIZE TOUPPER)
cmake_parse_arguments(ZEPHYR_STRING "${options}" "" "" ${ARGN})
if (NOT ZEPHYR_STRING_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Function zephyr_string() called without a return variable")
endif()
list(GET ZEPHYR_STRING_UNPARSED_ARGUMENTS 0 return_arg)
list(REMOVE_AT ZEPHYR_STRING_UNPARSED_ARGUMENTS 0)
list(JOIN ZEPHYR_STRING_UNPARSED_ARGUMENTS "" work_string)
if(ZEPHYR_STRING_SANITIZE)
string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" work_string ${work_string})
endif()
if(ZEPHYR_STRING_TOUPPER)
string(TOUPPER ${work_string} work_string)
endif()
set(${return_arg} ${work_string} PARENT_SCOPE)
endfunction()
# Usage:
# zephyr_list(TRANSFORM <list> <ACTION>
# [OUTPUT_VARIABLE <output variable])
#
# Example:
#
# zephyr_list(TRANSFORM my_input_var NORMALIZE_PATHS
# OUTPUT_VARIABLE my_input_as_list)
#
# Like CMake's list(TRANSFORM ...). This is intended as a placeholder
# for storing current and future Zephyr-related extensions for list
# processing.
#
# <ACTION>: This currently must be NORMALIZE_PATHS. This action
# converts the argument list <list> to a ;-list with
# CMake path names, after passing its contents through
# a configure_file() transformation. The input list
# may be whitespace- or semicolon-separated.
#
# OUTPUT_VARIABLE: the result is normally stored in place, but
# an alternative variable to store the result
# can be provided with this.
function(zephyr_list transform list_var action)
# Parse arguments.
if(NOT "${transform}" STREQUAL "TRANSFORM")
message(FATAL_ERROR "the first argument must be TRANSFORM")
endif()
if(NOT "${action}" STREQUAL "NORMALIZE_PATHS")
message(FATAL_ERROR "the third argument must be NORMALIZE_PATHS")
endif()
set(single_args OUTPUT_VARIABLE)
cmake_parse_arguments(ZEPHYR_LIST "" "${single_args}" "" ${ARGN})
if(DEFINED ZEPHYR_LIST_OUTPUT_VARIABLE)
set(out_var ${ZEPHYR_LIST_OUTPUT_VARIABLE})
else()
set(out_var ${list_var})
endif()
set(input ${${list_var}})
# Perform the transformation.
set(ret)
string(CONFIGURE "${input}" input_expanded)
string(REPLACE " " ";" input_raw_list "${input_expanded}")
foreach(file ${input_raw_list})
file(TO_CMAKE_PATH "${file}" cmake_path_file)
list(APPEND ret ${cmake_path_file})
endforeach()
set(${out_var} ${ret} PARENT_SCOPE)
endfunction()
# Usage:
# zephyr_var_name(<variable> <scope> <out>)
#
# Internal function for construction of scoped variable name expansion string.
# Examples:
# reading a current scope FOO variable is identical to expand ${FOO}.
# reading a cache scope FOO variable is identical to expand $CACHE{FOO}.
#
# this functions will return the var name in out var for the scope if it is
# defined, else it will set the outvar to undefined.
function(zephyr_var_name variable scope out)
if(scope STREQUAL "ENV" OR scope STREQUAL "CACHE")
if(DEFINED ${scope}{${variable}})
set(${out} "$${scope}{${variable}}" PARENT_SCOPE)
else()
set(${out} PARENT_SCOPE)
endif()
else()
if(DEFINED ${scope}_${variable})
set(${out} "${${scope}_${variable}}" PARENT_SCOPE)
else()
set(${out} PARENT_SCOPE)
endif()
endif()
endfunction()
# Usage:
# zephyr_get(<variable> [MERGE [REVERSE]] [SYSBUILD [LOCAL|GLOBAL]] [VAR <var1> ...])
#
# Return the value of <variable> as local scoped variable of same name. If MERGE
# is supplied, will return a list of found items. If REVERSE is supplied
# together with MERGE, the order of the list will be reversed before being
# returned. Reverse will happen before the list is returned and hence it will
# not change the order of precedence in which the list itself is constructed.
#
# VAR can be used either to store the result in a variable with a different
# name, or to look for values from multiple variables.
# zephyr_get(FOO VAR FOO_A FOO_B)
# zephyr_get(FOO MERGE VAR FOO_A FOO_B)
#
# zephyr_get() is a common function to provide a uniform way of supporting
# build settings that can be set from sysbuild, CMakeLists.txt, CMake cache, or
# in environment.
#
# The order of precedence for variables defined in multiple scopes:
# - Sysbuild defined when sysbuild is used.
# Sysbuild variables can be defined as global or local to specific image.
# Examples:
# - BOARD is considered a global sysbuild cache variable
# - blinky_BOARD is considered a local sysbuild cache variable only for the
# blinky image.
# If no sysbuild scope is specified, GLOBAL is assumed.
# If using MERGE then SYSBUILD GLOBAL will get both the local and global
# sysbuild scope variables (in that order, if both exist).
# - CMake cache, set by `-D<var>=<value>` or `set(<var> <val> CACHE ...)
# - Environment
# - Locally in CMakeLists.txt before 'find_package(Zephyr)'
#
# For example, if ZEPHYR_TOOLCHAIN_VARIANT is set in environment but locally
# overridden by setting ZEPHYR_TOOLCHAIN_VARIANT directly in the CMake cache
# using `-DZEPHYR_TOOLCHAIN_VARIANT=<val>`, then the value from the cache is
# returned.
function(zephyr_get variable)
cmake_parse_arguments(GET_VAR "MERGE;REVERSE" "SYSBUILD" "VAR" ${ARGN})
if(DEFINED GET_VAR_SYSBUILD)
if(NOT ("${GET_VAR_SYSBUILD}" STREQUAL "GLOBAL" OR
"${GET_VAR_SYSBUILD}" STREQUAL "LOCAL")
)
message(FATAL_ERROR "zephyr_get(... SYSBUILD) requires GLOBAL or LOCAL.")
endif()
else()
set(GET_VAR_SYSBUILD "GLOBAL")
endif()
if(GET_VAR_REVERSE AND NOT GET_VAR_MERGE)
message(FATAL_ERROR "zephyr_get(... REVERSE) missing a required argument: MERGE")
endif()
if(NOT DEFINED GET_VAR_VAR)
set(GET_VAR_VAR ${variable})
endif()
# Keep current scope variables in internal variables.
# This is needed to properly handle cases where we want to check value against
# environment value or when appending with the MERGE operation.
foreach(var ${GET_VAR_VAR})
set(current_${var} ${${var}})
set(${var})
if(SYSBUILD)
get_property(sysbuild_name TARGET sysbuild_cache PROPERTY SYSBUILD_NAME)
get_property(sysbuild_main_app TARGET sysbuild_cache PROPERTY SYSBUILD_MAIN_APP)
get_property(sysbuild_local_${var} TARGET sysbuild_cache PROPERTY ${sysbuild_name}_${var})
get_property(sysbuild_global_${var} TARGET sysbuild_cache PROPERTY ${var})
if(NOT DEFINED sysbuild_local_${var} AND sysbuild_main_app)
set(sysbuild_local_${var} ${sysbuild_global_${var}})
endif()
if(NOT "${GET_VAR_SYSBUILD}" STREQUAL "GLOBAL")
set(sysbuild_global_${var})
endif()
else()
set(sysbuild_local_${var})
set(sysbuild_global_${var})
endif()
if(TARGET snippets_scope)
get_property(snippets_${var} TARGET snippets_scope PROPERTY ${var})
endif()
endforeach()
set(${variable} "")
set(scopes "sysbuild_local;sysbuild_global;CACHE;snippets;ENV;current")
if(GET_VAR_REVERSE)
list(REVERSE scopes)
endif()
foreach(scope IN LISTS scopes)
foreach(var ${GET_VAR_VAR})
zephyr_var_name("${var}" "${scope}" expansion_var)
if(DEFINED expansion_var)
string(CONFIGURE "${expansion_var}" scope_value)
if(GET_VAR_MERGE)
list(APPEND ${variable} ${scope_value})
else()
set(${variable} ${scope_value} PARENT_SCOPE)
if("${scope}" STREQUAL "ENV")
# Set the environment variable in CMake cache, so that a build
# invocation triggering a CMake rerun doesn't rely on the
# environment variable still being available / have identical value.
set(${var} $ENV{${var}} CACHE INTERNAL "Cached environment variable ${var}")
endif()
if("${scope}" STREQUAL "ENV" AND DEFINED current_${var}
AND NOT "${current_${var}}" STREQUAL "$ENV{${var}}"
)
# Variable exists as current scoped variable, defined in a CMakeLists.txt
# file, however it is also set in environment.
# This might be a surprise to the user, so warn about it.
message(WARNING "environment variable '${var}' is hiding local "
"variable of same name.\n"
"Environment value (in use): $ENV{${var}}\n"
"Current scope value (hidden): ${current_${var}}\n"
)
endif()
return()
endif()
endif()
endforeach()
endforeach()
if(GET_VAR_MERGE)
if(GET_VAR_REVERSE)
list(REVERSE ${variable})
list(REMOVE_DUPLICATES ${variable})
list(REVERSE ${variable})
else()
list(REMOVE_DUPLICATES ${variable})
endif()
set(${variable} ${${variable}} PARENT_SCOPE)
endif()
endfunction(zephyr_get variable)
# Usage:
# zephyr_create_scope(<scope>)
#
# Create a new scope for creation of scoped variables.
#
# <scope>: Name of new scope.
#
function(zephyr_create_scope scope)
if(TARGET ${scope}_scope)
message(FATAL_ERROR "zephyr_create_scope(${scope}) already exists.")
endif()
add_custom_target(${scope}_scope)
endfunction()
# Usage:
# zephyr_set(<variable> <value> SCOPE <scope> [APPEND])
#
# Zephyr extension of CMake set which allows a variable to be set in a specific
# scope. The scope is used on later zephyr_get() invocation for precedence
# handling when a variable it set in multiple scopes.
#
# <variable> : Name of variable
# <value> : Value of variable, multiple values will create a list.
# The SCOPE argument identifies the end of value list.
# SCOPE <scope>: Name of scope for the variable
# APPEND : Append values to the already existing variable in <scope>
#
function(zephyr_set variable)
cmake_parse_arguments(SET_VAR "APPEND" "SCOPE" "" ${ARGN})
zephyr_check_arguments_required_all(zephyr_set SET_VAR SCOPE)
if(NOT TARGET ${SET_VAR_SCOPE}_scope)
message(FATAL_ERROR "zephyr_set(... SCOPE ${SET_VAR_SCOPE}) doesn't exists.")
endif()
if(SET_VAR_APPEND)
set(property_args APPEND)
endif()
set_property(TARGET ${SET_VAR_SCOPE}_scope ${property_args}
PROPERTY ${variable} ${SET_VAR_UNPARSED_ARGUMENTS}
)
endfunction()
# Usage:
# zephyr_check_cache(<variable> [REQUIRED])
#
# Check the current CMake cache for <variable> and warn the user if the value
# is being modified.
#
# This can be used to ensure the user does not accidentally try to change
# Zephyr build variables, such as:
# - BOARD
# - SHIELD
#
# variable: Name of <variable> to check and set, for example BOARD.
# REQUIRED: Optional flag. If specified, then an unset <variable> will be
# treated as an error.
# WATCH: Optional flag. If specified, watch the variable and print a warning if
# the variable is later being changed.
#
# Details:
# <variable> can be set by 3 sources.
# - Using CMake argument, -D<variable>
# - Using an environment variable
# - In the project CMakeLists.txt before `find_package(Zephyr)`.
#
# CLI has the highest precedence, then comes environment variables,
# and then finally CMakeLists.txt.
#
# The value defined on the first CMake invocation will be stored in the CMake
# cache as CACHED_<variable>. This allows the Zephyr build system to detect
# when a user reconfigures a sticky variable.
#
# A user can ignore all the precedence rules if the same source is always used
# E.g. always specifies -D<variable>= on the command line,
# always has an environment <variable> set, or always has a set(<variable> foo)
# line in his CMakeLists.txt and avoids mixing sources.
#
# The selected <variable> can be accessed through the variable '<variable>' in
# following Zephyr CMake code.
#
# If the user tries to change <variable> to a new value, then a warning will
# be printed, and the previously cached value (CACHED_<variable>) will be
# used, as it has precedence.
#
# Together with the warning, user is informed that in order to change
# <variable> the build directory must be cleaned.
#
function(zephyr_check_cache variable)
cmake_parse_arguments(CACHE_VAR "REQUIRED;WATCH" "" "" ${ARGN})
string(TOLOWER ${variable} variable_text)
string(REPLACE "_" " " variable_text ${variable_text})
get_property(cached_value CACHE ${variable} PROPERTY VALUE)
# If the build has already been configured in an earlier CMake invocation,
# then CACHED_${variable} is set. The CACHED_${variable} setting takes
# precedence over any user or CMakeLists.txt input.
# If we detect that user tries to change the setting, then print a warning
# that a pristine build is needed.
# If user uses -D<variable>=<new_value>, then cli_argument will hold the new
# value, otherwise cli_argument will hold the existing (old) value.
set(cli_argument ${cached_value})
if(cli_argument STREQUAL CACHED_${variable})
# The is no changes to the <variable> value.
unset(cli_argument)
endif()
set(app_cmake_lists ${${variable}})
if(cached_value STREQUAL ${variable})
# The app build scripts did not set a default, The variable we are
# reading is the cached value from the CLI
unset(app_cmake_lists)
endif()
if(DEFINED CACHED_${variable})
# Warn the user if it looks like he is trying to change the variable
# without cleaning first
if(cli_argument)
if(NOT ((CACHED_${variable} STREQUAL cli_argument) OR (${variable}_DEPRECATED STREQUAL cli_argument)))
message(WARNING "The build directory must be cleaned pristinely when "
"changing ${variable_text},\n"
"Current value=\"${CACHED_${variable}}\", "
"Ignored value=\"${cli_argument}\"")
endif()
endif()
if(CACHED_${variable})
set(${variable} ${CACHED_${variable}} PARENT_SCOPE)
set(${variable} ${CACHED_${variable}})
# This resets the user provided value with previous (working) value.
set(${variable} ${CACHED_${variable}} CACHE STRING "Selected ${variable_text}" FORCE)
else()
unset(${variable} PARENT_SCOPE)
unset(${variable} CACHE)
endif()
else()
zephyr_get(${variable})
endif()
if(${CACHE_VAR_REQUIRED} AND NOT DEFINED ${variable})
message(FATAL_ERROR "${variable} is not being defined on the CMake command-line,"
" in the environment or by the app."
)
endif()
if(DEFINED ${variable})
# Store the specified variable in parent scope and the cache
set(${variable} ${${variable}} PARENT_SCOPE)
set(${variable} ${${variable}} CACHE STRING "Selected ${variable_text}")
endif()
set(CACHED_${variable} ${${variable}} CACHE STRING "Selected ${variable_text}")
if(CACHE_VAR_WATCH)
# The variable is now set to its final value.
zephyr_boilerplate_watch(${variable})
endif()
endfunction(zephyr_check_cache variable)
# Usage:
# zephyr_boilerplate_watch(SOME_BOILERPLATE_VAR)
#
# Inform the build system that SOME_BOILERPLATE_VAR, a variable
# handled in the Zephyr package's boilerplate code, is now fixed and
# should no longer be changed.
#
# This function uses variable_watch() to print a noisy warning
# if the variable is set after it returns.
function(zephyr_boilerplate_watch variable)
variable_watch(${variable} zephyr_variable_set_too_late)
endfunction()
function(zephyr_variable_set_too_late variable access value current_list_file)
if (access STREQUAL "MODIFIED_ACCESS")
message(WARNING
"
**********************************************************************
*
* WARNING
*
* CMake variable ${variable} set to \"${value}\" in:
* ${current_list_file}
*
* This is too late to make changes! The change was ignored.
*
* Hint: ${variable} must be set before calling find_package(Zephyr ...).
*
**********************************************************************
")
endif()
endfunction()
# Usage:
# zephyr_get_targets(<directory> <types> <targets>)
#
# Get build targets for a given directory and sub-directories.
#
# This functions will traverse the build tree, starting from <directory>.
# It will read the `BUILDSYSTEM_TARGETS` for each directory in the build tree
# and return the build types matching the <types> list.
# Example of types: OBJECT_LIBRARY, STATIC_LIBRARY, INTERFACE_LIBRARY, UTILITY.
#
# returns a list of targets in <targets> matching the required <types>.
function(zephyr_get_targets directory types targets)
get_property(sub_directories DIRECTORY ${directory} PROPERTY SUBDIRECTORIES)
get_property(dir_targets DIRECTORY ${directory} PROPERTY BUILDSYSTEM_TARGETS)
foreach(dir_target ${dir_targets})
get_property(target_type TARGET ${dir_target} PROPERTY TYPE)
if(${target_type} IN_LIST types)
list(APPEND ${targets} ${dir_target})
endif()
endforeach()
foreach(directory ${sub_directories})
zephyr_get_targets(${directory} "${types}" ${targets})
endforeach()
set(${targets} ${${targets}} PARENT_SCOPE)
endfunction()
# Usage:
# test_sysbuild([REQUIRED])
#
# Test that current sample is invoked through sysbuild.
#
# This function tests that current CMake configure was invoked through sysbuild.
# If CMake configure was not invoked through sysbuild, then a warning is printed
# to the user. The warning can be upgraded to an error by setting `REQUIRED` as
# argument the `test_sysbuild()`.
#
# This function allows samples that are multi-image samples by nature to ensure
# all samples are correctly built together.
function(test_sysbuild)
cmake_parse_arguments(TEST_SYSBUILD "REQUIRED" "" "" ${ARGN})
if(TEST_SYSBUILD_REQUIRED)
set(message_mode FATAL_ERROR)
else()
set(message_mode WARNING)
endif()
if(NOT SYSBUILD)
message(${message_mode}
"Project '${PROJECT_NAME}' is designed for sysbuild.\n"
"For correct user-experiences, please build '${PROJECT_NAME}' "
"using sysbuild."
)
endif()
endfunction()
# Usage:
# target_byproducts(TARGET <target> BYPRODUCTS <file> [<file>...])
#
# Specify additional BYPRODUCTS that this target produces.
#
# This function allows the build system to specify additional byproducts to
# target created with `add_executable()`. When linking an executable the linker
# may produce additional files, like map files. Those files are not known to the
# build system. This function makes it possible to describe such additional
# byproducts in an easy manner.
function(target_byproducts)
cmake_parse_arguments(TB "" "TARGET" "BYPRODUCTS" ${ARGN})
if(NOT DEFINED TB_TARGET)
message(FATAL_ERROR "target_byproducts() missing parameter: TARGET <target>")
endif()
add_custom_command(TARGET ${TB_TARGET}
POST_BUILD COMMAND ${CMAKE_COMMAND} -E true
BYPRODUCTS ${TB_BYPRODUCTS}
COMMENT "Logical command for additional byproducts on target: ${TB_TARGET}"
)
endfunction()
# Usage:
# topological_sort(TARGETS <target> [<target> ...]
# PROPERTY_NAME <property>
# RESULT <out-variable>)
#
# This function performs topological sorting of CMake targets using a specific
# <property>, which dictates target dependencies. A fatal error occurs if the
# provided dependencies cannot be met, e.g., if they contain cycles.
#
# TARGETS: List of target names.
# PROPERTY_NAME: Name of the target property to be used when sorting. For every
# target listed in TARGETS, this property must contain a list
# (possibly empty) of other targets, which this target depends on
# for a particular purpose. The property must not contain any
# target which is not also found in TARGETS.
# RESULT: Output variable, where the topologically sorted list of target
# names will be returned.
#
function(topological_sort)
cmake_parse_arguments(TS "" "RESULT;PROPERTY_NAME" "TARGETS" ${ARGN})
set(dep_targets)
set(start_targets)
set(sorted_targets)
foreach(target ${TS_TARGETS})
get_target_property(${target}_dependencies ${target} ${TS_PROPERTY_NAME})
if(${target}_dependencies)
list(APPEND dep_targets ${target})
else()
list(APPEND start_targets ${target})
endif()
endforeach()
while(TRUE)
list(POP_FRONT start_targets node)
list(APPEND sorted_targets ${node})
set(to_remove)
foreach(target ${dep_targets})
if("${node}" IN_LIST ${target}_dependencies)
list(REMOVE_ITEM ${target}_dependencies ${node})
if(NOT ${target}_dependencies)
list(APPEND start_targets ${target})
list(APPEND to_remove ${target})
endif()
endif()
endforeach()
foreach(target ${to_remove})
list(REMOVE_ITEM dep_targets ${target})
endforeach()
if(NOT start_targets)
break()
endif()
endwhile()
if(dep_targets)
foreach(target ${dep_targets})
get_target_property(deps ${target} ${TS_PROPERTY_NAME})
list(JOIN deps " " deps)
list(APPEND dep_string "${target} depends on: ${deps}")
endforeach()
list(JOIN dep_string "\n" dep_string)
message(FATAL_ERROR "Unmet or cyclic dependencies:\n${dep_string}")
endif()
set(${TS_RESULT} "${sorted_targets}" PARENT_SCOPE)
endfunction()
########################################################
# 4. Devicetree extensions
########################################################
# 4.1. dt_*
#
# The following methods are for retrieving devicetree information in CMake.
#
# Notes:
#
# - In CMake, we refer to the nodes using the node's path, therefore
# there is no dt_path(...) function for obtaining a node identifier
# like there is in the C devicetree.h API.
#
# - As another difference from the C API, you can generally use an
# alias at the beginning of a path interchangeably with the full
# path to the aliased node in these functions. The usage comments
# will make this clear in each case.
# Usage:
# dt_nodelabel(<var> NODELABEL <label>)
#
# Function for retrieving the node path for the node having nodelabel
# <label>.
#
# Example devicetree fragment:
#
# / {
# soc {
# nvic: interrupt-controller@e000e100 { ... };
# };
# };
#
# Example usage:
#
# # Sets 'nvic_path' to "/soc/interrupt-controller@e000e100"
# dt_nodelabel(nvic_path NODELABEL "nvic")
#
# The node's path will be returned in the <var> parameter.
# <var> will be undefined if node does not exist.
#
# <var> : Return variable where the node path will be stored
# NODELABEL <label> : Node label
function(dt_nodelabel var)
set(req_single_args "NODELABEL")
cmake_parse_arguments(DT_LABEL "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_LABEL_${arg})
message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
get_target_property(${var} devicetree_target "DT_NODELABEL|${DT_LABEL_NODELABEL}")
if(${${var}} STREQUAL ${var}-NOTFOUND)
set(${var})
endif()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
# Usage:
# dt_alias(<var> PROPERTY <prop>)
#
# Get a node path for an /aliases node property.
#
# Example usage:
#
# # The full path to the 'led0' alias is returned in 'path'.
# dt_alias(path PROPERTY "led0")
#
# # The variable 'path' will be left undefined for a nonexistent
# # alias "does-not-exist".
# dt_alias(path PROPERTY "does-not-exist")
#
# The node's path will be returned in the <var> parameter. The
# variable will be left undefined if the alias does not exist.
#
# <var> : Return variable where the node path will be stored
# PROPERTY <prop> : The alias to check
function(dt_alias var)
set(req_single_args "PROPERTY")
cmake_parse_arguments(DT_ALIAS "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_alias(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_ALIAS_${arg})
message(FATAL_ERROR "dt_alias(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
get_target_property(${var} devicetree_target "DT_ALIAS|${DT_ALIAS_PROPERTY}")
if(${${var}} STREQUAL ${var}-NOTFOUND)
set(${var})
endif()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
# Usage:
# dt_node_exists(<var> PATH <path>)
#
# Tests whether a node with path <path> exists in the devicetree.
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# The result of the check, either TRUE or FALSE, will be returned in
# the <var> parameter.
#
# <var> : Return variable where the check result will be returned
# PATH <path> : Node path
function(dt_node_exists var)
set(req_single_args "PATH")
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_node_exists(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_NODE_${arg})
message(FATAL_ERROR "dt_node_exists(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
dt_path_internal(canonical "${DT_NODE_PATH}")
if (DEFINED canonical)
set(${var} TRUE PARENT_SCOPE)
else()
set(${var} FALSE PARENT_SCOPE)
endif()
endfunction()
# Usage:
# dt_node_has_status(<var> PATH <path> STATUS <status>)
#
# Tests whether <path> refers to a node which:
# - exists in the devicetree, and
# - has a status property matching the <status> argument
# (a missing status or an “ok” status is treated as if it
# were “okay” instead)
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# The result of the check, either TRUE or FALSE, will be returned in
# the <var> parameter.
#
# <var> : Return variable where the check result will be returned
# PATH <path> : Node path
# STATUS <status> : Status to check
function(dt_node_has_status var)
set(req_single_args "PATH;STATUS")
cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_NODE_${arg})
message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
dt_path_internal(canonical ${DT_NODE_PATH})
if(NOT DEFINED canonical)
set(${var} FALSE PARENT_SCOPE)
return()
endif()
dt_prop(status PATH ${canonical} PROPERTY status)
if(NOT DEFINED status OR status STREQUAL "ok")
set(status "okay")
endif()
if(status STREQUAL "${DT_NODE_STATUS}")
set(${var} TRUE PARENT_SCOPE)
else()
set(${var} FALSE PARENT_SCOPE)
endif()
endfunction()
# Usage:
#
# dt_prop(<var> PATH <path> PROPERTY <prop> [INDEX <idx>])
#
# Get a devicetree property value. The value will be returned in the
# <var> parameter.
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# This function currently only supports properties with the following
# devicetree binding types: string, int, boolean, array, uint8-array,
# string-array, path.
#
# For array valued properties (including uint8-array and
# string-array), the entire array is returned as a CMake list unless
# INDEX is given. If INDEX is given, just the array element at index
# <idx> is returned.
#
# The property value will be returned in the <var> parameter if the
# node exists and has a property <prop> with one of the above types.
# <var> will be undefined otherwise.
#
# To test if the property is defined before using it, use DEFINED on
# the return <var>, like this:
#
# dt_prop(reserved_ranges PATH "/soc/gpio@deadbeef" PROPERTY "gpio-reserved-ranges")
# if(DEFINED reserved_ranges)
# # Node exists and has the "gpio-reserved-ranges" property.
# endif()
#
# To distinguish a missing node from a missing property, combine
# dt_prop() and dt_node_exists(), like this:
#
# dt_node_exists(node_exists PATH "/soc/gpio@deadbeef")
# dt_prop(reserved_ranges PATH "/soc/gpio@deadbeef" PROPERTY "gpio-reserved-ranges")
# if(DEFINED reserved_ranges)
# # Node "/soc/gpio@deadbeef" exists and has the "gpio-reserved-ranges" property
# elseif(node_exists)
# # Node exists, but doesn't have the property, or the property has an unsupported type.
# endif()
#
# <var> : Return variable where the property value will be stored
# PATH <path> : Node path
# PROPERTY <prop>: Property for which a value should be returned, as it
# appears in the DTS source
# INDEX <idx> : Optional index when retrieving a value in an array property
function(dt_prop var)
set(req_single_args "PATH;PROPERTY")
set(single_args "INDEX")
cmake_parse_arguments(DT_PROP "" "${req_single_args};${single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_prop(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_PROP_${arg})
message(FATAL_ERROR "dt_prop(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
dt_path_internal(canonical "${DT_PROP_PATH}")
get_property(exists TARGET devicetree_target
PROPERTY "DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
SET
)
if(NOT exists)
set(${var} PARENT_SCOPE)
return()
endif()
get_target_property(val devicetree_target
"DT_PROP|${canonical}|${DT_PROP_PROPERTY}"
)
if(DEFINED DT_PROP_INDEX)
list(GET val ${DT_PROP_INDEX} element)
set(${var} "${element}" PARENT_SCOPE)
else()
set(${var} "${val}" PARENT_SCOPE)
endif()
endfunction()
# Usage:
#
# dt_comp_path(<var> COMPATIBLE <compatible> [INDEX <idx>])
#
# Get a list of paths for the nodes with the given compatible. The value will
# be returned in the <var> parameter.
# <var> will be undefined if no such compatible exists.
#
# For details and considerations about the format of <path> and the returned
# parameter refer to dt_prop().
#
# <var> : Return variable where the property value will be stored
# COMPATIBLE <compatible>: Compatible for which the list of paths should be
# returned, as it appears in the DTS source
# INDEX <idx> : Optional index when retrieving a value in an array property
function(dt_comp_path var)
set(req_single_args "COMPATIBLE")
set(single_args "INDEX")
cmake_parse_arguments(DT_COMP "" "${req_single_args};${single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_comp_path(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_COMP_${arg})
message(FATAL_ERROR "dt_comp_path(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
get_property(exists TARGET devicetree_target
PROPERTY "DT_COMP|${DT_COMP_COMPATIBLE}"
SET
)
if(NOT exists)
set(${var} PARENT_SCOPE)
return()
endif()
get_target_property(val devicetree_target
"DT_COMP|${DT_COMP_COMPATIBLE}"
)
if(DEFINED DT_COMP_INDEX)
list(GET val ${DT_COMP_INDEX} element)
set(${var} "${element}" PARENT_SCOPE)
else()
set(${var} "${val}" PARENT_SCOPE)
endif()
endfunction()
# Usage:
# dt_num_regs(<var> PATH <path>)
#
# Get the number of register blocks in the node's reg property;
# this may be zero.
#
# The value will be returned in the <var> parameter.
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# <var> : Return variable where the property value will be stored
# PATH <path> : Node path
function(dt_num_regs var)
set(req_single_args "PATH")
cmake_parse_arguments(DT_REG "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_REG_${arg})
message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
dt_path_internal(canonical "${DT_REG_PATH}")
get_target_property(${var} devicetree_target "DT_REG|${canonical}|NUM")
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
# Usage:
# dt_reg_addr(<var> PATH <path> [INDEX <idx>] [NAME <name>])
#
# Get the base address of the register block at index <idx>, or with
# name <name>. If <idx> and <name> are both omitted, the value at
# index 0 will be returned. Do not give both <idx> and <name>.
#
# The value will be returned in the <var> parameter.
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# Results can be:
# - The base address of the register block
# - <var> will be undefined if node does not exists or does not have a register
# block at the requested index or with the requested name
#
# <var> : Return variable where the address value will be stored
# PATH <path> : Node path
# INDEX <idx> : Register block index number
# NAME <name> : Register block name
function(dt_reg_addr var)
set(req_single_args "PATH")
set(single_args "INDEX;NAME")
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_REG_${arg})
message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
if(DEFINED DT_REG_INDEX AND DEFINED DT_REG_NAME)
message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) given both INDEX and NAME")
elseif(NOT DEFINED DT_REG_INDEX AND NOT DEFINED DT_REG_NAME)
set(DT_REG_INDEX 0)
elseif(DEFINED DT_REG_NAME)
dt_reg_index_private(DT_REG_INDEX "${DT_REG_PATH}" "${DT_REG_NAME}")
if(DT_REG_INDEX EQUAL "-1")
set(${var} PARENT_SCOPE)
return()
endif()
endif()
dt_path_internal(canonical "${DT_REG_PATH}")
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|ADDR")
list(GET ${var}_list ${DT_REG_INDEX} ${var})
if("${var}" STREQUAL NONE)
set(${var})
endif()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
# Usage:
# dt_reg_size(<var> PATH <path> [INDEX <idx>] [NAME <name>])
#
# Get the size of the register block at index <idx>, or with
# name <name>. If <idx> and <name> are both omitted, the value at
# index 0 will be returned. Do not give both <idx> and <name>.
#
# The value will be returned in the <value> parameter.
#
# The <path> value may be any of these:
#
# - absolute path to a node, like '/foo/bar'
# - a node alias, like 'my-alias'
# - a node alias followed by a path to a child node, like 'my-alias/child-node'
#
# <var> : Return variable where the size value will be stored
# PATH <path> : Node path
# INDEX <idx> : Register block index number
# NAME <name> : Register block name
function(dt_reg_size var)
set(req_single_args "PATH")
set(single_args "INDEX;NAME")
cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_REG_${arg})
message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
if(DEFINED DT_REG_INDEX AND DEFINED DT_REG_NAME)
message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) given both INDEX and NAME")
elseif(NOT DEFINED DT_REG_INDEX AND NOT DEFINED DT_REG_NAME)
set(DT_REG_INDEX 0)
elseif(DEFINED DT_REG_NAME)
dt_reg_index_private(DT_REG_INDEX "${DT_REG_PATH}" "${DT_REG_NAME}")
if(DT_REG_INDEX EQUAL "-1")
set(${var} PARENT_SCOPE)
return()
endif()
endif()
dt_path_internal(canonical "${DT_REG_PATH}")
get_target_property(${var}_list devicetree_target "DT_REG|${canonical}|SIZE")
list(GET ${var}_list ${DT_REG_INDEX} ${var})
if("${var}" STREQUAL NONE)
set(${var})
endif()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
# Internal helper for dt_reg_addr/dt_reg_size; not meant to be used directly
function(dt_reg_index_private var path name)
dt_prop(reg_names PATH "${path}" PROPERTY "reg-names")
if(NOT DEFINED reg_names)
set(index "-1")
else()
list(FIND reg_names "${name}" index)
endif()
set(${var} "${index}" PARENT_SCOPE)
endfunction()
# Usage:
# dt_has_chosen(<var> PROPERTY <prop>)
#
# Test if the devicetree's /chosen node has a given property
# <prop> which contains the path to a node.
#
# Example devicetree fragment:
#
# chosen {
# foo = &bar;
# };
#
# Example usage:
#
# # Sets 'result' to TRUE
# dt_has_chosen(result PROPERTY "foo")
#
# # Sets 'result' to FALSE
# dt_has_chosen(result PROPERTY "baz")
#
# The result of the check, either TRUE or FALSE, will be stored in the
# <var> parameter.
#
# <var> : Return variable
# PROPERTY <prop> : Chosen property
function(dt_has_chosen var)
set(req_single_args "PROPERTY")
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_CHOSEN_${arg})
message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
get_target_property(exists devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
if(${exists} STREQUAL exists-NOTFOUND)
set(${var} FALSE PARENT_SCOPE)
else()
set(${var} TRUE PARENT_SCOPE)
endif()
endfunction()
# Usage:
# dt_chosen(<var> PROPERTY <prop>)
#
# Get a node path for a /chosen node property.
#
# The node's path will be returned in the <var> parameter. The
# variable will be left undefined if the chosen node does not exist.
#
# <var> : Return variable where the node path will be stored
# PROPERTY <prop> : Chosen property
function(dt_chosen var)
set(req_single_args "PROPERTY")
cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
if(${ARGV0} IN_LIST req_single_args)
message(FATAL_ERROR "dt_chosen(${ARGV0} ...) missing return parameter.")
endif()
foreach(arg ${req_single_args})
if(NOT DEFINED DT_CHOSEN_${arg})
message(FATAL_ERROR "dt_chosen(${ARGV0} ...) "
"missing required argument: ${arg}"
)
endif()
endforeach()
get_target_property(${var} devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
if(${${var}} STREQUAL ${var}-NOTFOUND)
set(${var} PARENT_SCOPE)
else()
set(${var} ${${var}} PARENT_SCOPE)
endif()
endfunction()
# Internal helper. Canonicalizes a path 'path' into the output
# variable 'var'. This resolves aliases, if any. Child nodes may be
# accessed via alias as well. 'var' is left undefined if the path does
# not refer to an existing node.
#
# Example devicetree:
#
# / {
# foo {
# my-label: bar {
# baz {};
# };
# };
# aliases {
# my-alias = &my-label;
# };
# };
#
# Example usage:
#
# dt_path_internal(ret "/foo/bar") # sets ret to "/foo/bar"
# dt_path_internal(ret "my-alias") # sets ret to "/foo/bar"
# dt_path_internal(ret "my-alias/baz") # sets ret to "/foo/bar/baz"
# dt_path_internal(ret "/blub") # ret is undefined
function(dt_path_internal var path)
string(FIND "${path}" "/" slash_index)
if("${slash_index}" EQUAL 0)
# If the string starts with a slash, it should be an existing
# canonical path.
dt_path_internal_exists(check "${path}")
if (check)
set(${var} "${path}" PARENT_SCOPE)
return()
endif()
else()
# Otherwise, try to expand a leading alias.
string(SUBSTRING "${path}" 0 "${slash_index}" alias_name)
dt_alias(alias_path PROPERTY "${alias_name}")
# If there is a leading alias, append the rest of the string
# onto it and see if that's an existing node.
if (DEFINED alias_path)
set(rest)
if (NOT "${slash_index}" EQUAL -1)
string(SUBSTRING "${path}" "${slash_index}" -1 rest)
endif()
dt_path_internal_exists(expanded_path_exists "${alias_path}${rest}")
if (expanded_path_exists)
set(${var} "${alias_path}${rest}" PARENT_SCOPE)
return()
endif()
endif()
endif()
# Failed search; ensure return variable is undefined.
set(${var} PARENT_SCOPE)
endfunction()
# Internal helper. Set 'var' to TRUE if a canonical path 'path' refers
# to an existing node. Set it to FALSE otherwise. See
# dt_path_internal for a definition and examples of 'canonical' paths.
function(dt_path_internal_exists var path)
get_target_property(path_prop devicetree_target "DT_NODE|${path}")
if (path_prop)
set(${var} TRUE PARENT_SCOPE)
else()
set(${var} FALSE PARENT_SCOPE)
endif()
endfunction()
# 4.2. *_if_dt_node
#
# This section is similar to the extensions named *_ifdef, except
# actions are performed if the devicetree contains some node.
# *_if_dt_node functions may be added as needed, or if they are likely
# to be useful for user applications.
# Add item(s) to a target's SOURCES list if a devicetree node exists.
#
# Example usage:
#
# # If the devicetree alias "led0" refers to a node, this
# # adds "blink_led.c" to the sources list for the "app" target.
# target_sources_if_dt_node("led0" app PRIVATE blink_led.c)
#
# # If the devicetree path "/soc/serial@4000" is a node, this
# # adds "uart.c" to the sources list for the "lib" target,
# target_sources_if_dt_node("/soc/serial@4000" lib PRIVATE uart.c)
#
# <path> : Path to devicetree node to check
# <target> : Build system target whose sources to add to
# <scope> : Scope to add items to
# <item> : Item (or items) to add to the target
function(target_sources_if_dt_node path target scope item)
dt_node_exists(check PATH "${path}")
if(${check})
target_sources(${target} ${scope} ${item} ${ARGN})
endif()
endfunction()
########################################################
# 4.3 zephyr_dt_*
#
# The following methods are common code for dealing
# with devicetree related files in CMake.
#
# Note that functions related to accessing the
# *contents* of the devicetree belong in section 4.1.
# This section is just for DT file processing at
# configuration time.
########################################################
# Usage:
# zephyr_dt_preprocess(CPP <path> [<argument...>]
# SOURCE_FILES <file...>
# OUT_FILE <file>
# [DEPS_FILE <file>]
# [EXTRA_CPPFLAGS <flag...>]
# [INCLUDE_DIRECTORIES <dir...>]
# [WORKING_DIRECTORY <dir>]
#
# Preprocess one or more devicetree source files. The preprocessor
# symbol __DTS__ will be defined. If the preprocessor command fails, a
# fatal error occurs.
#
# Mandatory arguments:
#
# CPP <path> [<argument...>]: path to C preprocessor, followed by any
# additional arguments
#
# SOURCE_FILES <file...>: The source files to run the preprocessor on.
# These will, in effect, be concatenated in order
# and used as the preprocessor input.
#
# OUT_FILE <file>: Where to store the preprocessor output.
#
# Optional arguments:
#
# DEPS_FILE <file>: If set, generate a dependency file here.
#
# EXTRA_CPPFLAGS <flag...>: Additional flags to pass the preprocessor.
#
# INCLUDE_DIRECTORIES <dir...>: Additional #include file directories.
#
# WORKING_DIRECTORY <dir>: where to run the preprocessor.
function(zephyr_dt_preprocess)
set(req_single_args "OUT_FILE")
set(single_args "DEPS_FILE;WORKING_DIRECTORY")
set(req_multi_args "CPP;SOURCE_FILES")
set(multi_args "EXTRA_CPPFLAGS;INCLUDE_DIRECTORIES")
cmake_parse_arguments(DT_PREPROCESS "" "${req_single_args};${single_args}" "${req_multi_args};${multi_args}" ${ARGN})
foreach(arg ${req_single_args} ${req_multi_args})
if(NOT DEFINED DT_PREPROCESS_${arg})
message(FATAL_ERROR "dt_preprocess() missing required argument: ${arg}")
endif()
endforeach()
set(include_opts)
foreach(dir ${DT_PREPROCESS_INCLUDE_DIRECTORIES})
list(APPEND include_opts -isystem ${dir})
endforeach()
set(source_opts)
foreach(file ${DT_PREPROCESS_SOURCE_FILES})
list(APPEND source_opts -include ${file})
endforeach()
set(deps_opts)
if(DEFINED DT_PREPROCESS_DEPS_FILE)
list(APPEND deps_opts -MD -MF ${DT_PREPROCESS_DEPS_FILE})
endif()
set(workdir_opts)
if(DEFINED DT_PREPROCESS_WORKING_DIRECTORY)
list(APPEND workdir_opts WORKING_DIRECTORY ${DT_PREPROCESS_WORKING_DIRECTORY})
endif()
# We are leaving linemarker directives enabled on purpose. This tells
# dtlib where each line actually came from, which improves error
# reporting.
set(preprocess_cmd ${DT_PREPROCESS_CPP}
-x assembler-with-cpp
-nostdinc
${include_opts}
${source_opts}
${NOSYSDEF_CFLAG}
-D__DTS__
${DT_PREPROCESS_EXTRA_CPPFLAGS}
-E # Stop after preprocessing
${deps_opts}
-o ${DT_PREPROCESS_OUT_FILE}
${ZEPHYR_BASE}/misc/empty_file.c
${workdir_opts})
execute_process(COMMAND ${preprocess_cmd} RESULT_VARIABLE ret)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "failed to preprocess devicetree files (error code ${ret}): ${DT_PREPROCESS_SOURCE_FILES}")
endif()
endfunction()
########################################################
# 5. Zephyr linker functions
########################################################
# 5.1. zephyr_linker*
#
# The following methods are for defining linker structure using CMake functions.
#
# This allows Zephyr developers to define linker sections and their content and
# have this configuration rendered into an appropriate linker script based on
# the toolchain in use.
# For example:
# ld linker scripts with GNU ld
# ARM scatter files with ARM linker.
#
# Example usage:
# zephyr_linker_section(
# NAME my_data
# VMA RAM
# LMA FLASH
# )
#
# and to configure special input sections for the section
# zephyr_linker_section_configure(
# SECTION my_data
# INPUT "my_custom_data"
# KEEP
# )
# Usage:
# zephyr_linker([FORMAT <format>]
# [ENTRY <entry symbol>]
# )
#
# Zephyr linker general settings.
# This function specifies general settings for the linker script to be generated.
#
# FORMAT <format>: The output format of the linked executable.
# ENTRY <entry symbolformat>: The code entry symbol.
#
function(zephyr_linker)
set(single_args "ENTRY;FORMAT")
cmake_parse_arguments(LINKER "" "${single_args}" "" ${ARGN})
if(LINKER_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker(${ARGV0} ...) given unknown "
"arguments: ${LINKER_UNPARSED_ARGUMENTS}"
)
endif()
if(DEFINED LINKER_FORMAT)
get_property(format_defined TARGET linker PROPERTY FORMAT SET)
if(format_defined)
message(FATAL_ERROR "zephyr_linker(FORMAT ...) already configured.")
else()
set_property(TARGET linker PROPERTY FORMAT ${LINKER_FORMAT})
endif()
endif()
if(DEFINED LINKER_ENTRY)
get_property(entry_defined TARGET linker PROPERTY ENTRY SET)
if(entry_defined)
message(FATAL_ERROR "zephyr_linker(ENTRY ...) already configured.")
else()
set_property(TARGET linker PROPERTY ENTRY ${LINKER_ENTRY})
endif()
endif()
endfunction()
# Usage:
# zephyr_linker_memory(NAME <name> START <address> SIZE <size> FLAGS <flags>)
#
# Zephyr linker memory.
# This function specifies a memory region for the platform in use.
#
# Note:
# This function should generally be called with values obtained from
# devicetree or Kconfig.
#
# NAME <name> : Name of the memory region, for example FLASH.
# START <address>: Start address of the memory region.
# Start address can be given as decimal or hex value.
# SIZE <size> : Size of the memory region.
# Size can be given as decimal value, hex value, or decimal with postfix k or m.
# All the following are valid values:
# 1048576, 0x10000, 1024k, 1024K, 1m, and 1M.
# FLAGS <flags> : Flags describing properties of the memory region.
# Currently supported:
# r: Read-only region
# w: Read-write region
# x: Executable region
# The flags r and x, or w and x may be combined like: rx, wx.
function(zephyr_linker_memory)
set(single_args "FLAGS;NAME;SIZE;START")
cmake_parse_arguments(MEMORY "" "${single_args}" "" ${ARGN})
if(MEMORY_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker_memory(${ARGV0} ...) given unknown "
"arguments: ${MEMORY_UNPARSED_ARGUMENTS}"
)
endif()
foreach(arg ${single_args})
if(NOT DEFINED MEMORY_${arg})
message(FATAL_ERROR "zephyr_linker_memory(${ARGV0} ...) missing required "
"argument: ${arg}"
)
endif()
endforeach()
set(MEMORY)
zephyr_linker_arg_val_list(MEMORY "${single_args}")
string(REPLACE ";" "\;" MEMORY "${MEMORY}")
set_property(TARGET linker
APPEND PROPERTY MEMORY_REGIONS "{${MEMORY}}"
)
endfunction()
# Usage:
# zephyr_linker_memory_ifdef(<setting> NAME <name> START <address> SIZE <size> FLAGS <flags>)
#
# Will create memory region if <setting> is enabled.
#
# <setting>: Setting to check for True value before invoking
# zephyr_linker_memory()
#
# See zephyr_linker_memory() description for other supported arguments.
#
macro(zephyr_linker_memory_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_linker_memory(${ARGN})
endif()
endmacro()
# Usage:
# zephyr_linker_dts_section(PATH <path>)
#
# Zephyr linker devicetree memory section from path.
#
# This function specifies an output section for the platform in use based on its
# devicetree configuration.
#
# The section will only be defined if the devicetree exists and has status okay.
#
# PATH <path> : Devicetree node path.
#
function(zephyr_linker_dts_section)
set(single_args "PATH")
cmake_parse_arguments(DTS_SECTION "" "${single_args}" "" ${ARGN})
if(DTS_SECTION_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) given unknown "
"arguments: ${DTS_SECTION_UNPARSED_ARGUMENTS}"
)
endif()
if(NOT DEFINED DTS_SECTION_PATH)
message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) missing "
"required argument: PATH"
)
endif()
dt_node_has_status(okay PATH ${DTS_SECTION_PATH} STATUS okay)
if(NOT ${okay})
return()
endif()
dt_prop(name PATH ${DTS_SECTION_PATH} PROPERTY "zephyr,memory-region")
if(NOT DEFINED name)
message(FATAL_ERROR "zephyr_linker_dts_section(${ARGV0} ...) missing "
"\"zephyr,memory-region\" property"
)
endif()
zephyr_string(SANITIZE name ${name})
dt_reg_addr(addr PATH ${DTS_SECTION_PATH})
zephyr_linker_section(NAME ${name} ADDRESS ${addr} VMA ${name} TYPE NOLOAD)
endfunction()
# Usage:
# zephyr_linker_dts_memory(PATH <path> FLAGS <flags>)
# zephyr_linker_dts_memory(NODELABEL <nodelabel> FLAGS <flags>)
# zephyr_linker_dts_memory(CHOSEN <prop> FLAGS <flags>)
#
# Zephyr linker devicetree memory.
# This function specifies a memory region for the platform in use based on its
# devicetree configuration.
#
# The memory will only be defined if the devicetree node or a devicetree node
# matching the nodelabel exists and has status okay.
#
# Only one of PATH, NODELABEL, and CHOSEN parameters may be given.
#
# PATH <path> : Devicetree node identifier.
# NODELABEL <label>: Node label
# CHOSEN <prop> : Chosen property, add memory section described by the
# /chosen property if it exists.
# FLAGS <flags> : Flags describing properties of the memory region.
# Currently supported:
# r: Read-only region
# w: Read-write region
# x: Executable region
# The flags r and x, or w and x may be combined like: rx, wx.
#
function(zephyr_linker_dts_memory)
set(single_args "CHOSEN;FLAGS;PATH;NODELABEL")
cmake_parse_arguments(DTS_MEMORY "" "${single_args}" "" ${ARGN})
if(DTS_MEMORY_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...) given unknown "
"arguments: ${DTS_MEMORY_UNPARSED_ARGUMENTS}"
)
endif()
if((DEFINED DTS_MEMORY_PATH AND (DEFINED DTS_MEMORY_NODELABEL OR DEFINED DTS_MEMORY_CHOSEN))
OR (DEFINED DTS_MEMORY_NODELABEL AND DEFINED DTS_MEMORY_CHOSEN))
message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...), only one of "
"PATH, NODELABEL, and CHOSEN is allowed."
)
endif()
if(DEFINED DTS_MEMORY_NODELABEL)
dt_nodelabel(DTS_MEMORY_PATH NODELABEL ${DTS_MEMORY_NODELABEL})
endif()
if(DEFINED DTS_MEMORY_CHOSEN)
dt_chosen(DTS_MEMORY_PATH PROPERTY ${DTS_MEMORY_CHOSEN})
endif()
if(NOT DEFINED DTS_MEMORY_PATH)
return()
endif()
dt_node_has_status(okay PATH ${DTS_MEMORY_PATH} STATUS okay)
if(NOT ${okay})
return()
endif()
dt_reg_addr(addr PATH ${DTS_MEMORY_PATH})
dt_reg_size(size PATH ${DTS_MEMORY_PATH})
dt_prop(name PATH ${DTS_MEMORY_PATH} PROPERTY "zephyr,memory-region")
if(NOT DEFINED name)
message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...) missing "
"\"zephyr,memory-region\" property"
)
endif()
zephyr_string(SANITIZE name ${name})
zephyr_linker_memory(
NAME ${name}
START ${addr}
SIZE ${size}
FLAGS ${DTS_MEMORY_FLAGS}
)
endfunction()
# Usage:
# zephyr_linker_group(NAME <name> [VMA <region|group>] [LMA <region|group>] [SYMBOL <SECTION>])
# zephyr_linker_group(NAME <name> GROUP <group> [SYMBOL <SECTION>])
#
# Zephyr linker group.
# This function specifies a group inside a memory region or another group.
#
# The group ensures that all section inside the group are located together inside
# the specified group.
#
# This also allows for section placement inside a given group without the section
# itself needing the precise knowledge regarding the exact memory region this
# section will be placed in, as that will be determined by the group setup.
#
# Each group will define the following linker symbols:
# __<name>_start : Start address of the group
# __<name>_end : End address of the group
# __<name>_size : Size of the group
#
# Note: <name> will be converted to lower casing for linker symbols definitions.
#
# NAME <name> : Name of the group.
# VMA <region|group> : VMA Memory region or group to be used for this group.
# If a group is used then the VMA region of that group will be used.
# LMA <region|group> : Memory region or group to be used for this group.
# GROUP <group> : Place the new group inside the existing group <group>
# SYMBOL <SECTION> : Specify that start symbol of the region should be identical
# to the start address of the first section in the group.
#
# Note: VMA and LMA are mutual exclusive with GROUP
#
# Example:
# zephyr_linker_memory(NAME memA START ... SIZE ... FLAGS ...)
# zephyr_linker_group(NAME groupA LMA memA)
# zephyr_linker_group(NAME groupB LMA groupA)
#
# will create two groups in same memory region as groupB will inherit the LMA
# from groupA:
#
# +-----------------+
# | memory region A |
# | |
# | +-------------+ |
# | | groupA | |
# | +-------------+ |
# | |
# | +-------------+ |
# | | groupB | |
# | +-------------+ |
# | |
# +-----------------+
#
# whereas
# zephyr_linker_memory(NAME memA START ... SIZE ... FLAGS ...)
# zephyr_linker_group(NAME groupA LMA memA)
# zephyr_linker_group(NAME groupB GROUP groupA)
#
# will create groupB inside groupA:
#
# +---------------------+
# | memory region A |
# | |
# | +-----------------+ |
# | | groupA | |
# | | | |
# | | +-------------+ | |
# | | | groupB | | |
# | | +-------------+ | |
# | | | |
# | +-----------------+ |
# | |
# +---------------------+
function(zephyr_linker_group)
set(single_args "NAME;GROUP;LMA;SYMBOL;VMA")
set(symbol_values SECTION)
cmake_parse_arguments(GROUP "" "${single_args}" "" ${ARGN})
if(GROUP_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker_group(${ARGV0} ...) given unknown "
"arguments: ${GROUP_UNPARSED_ARGUMENTS}"
)
endif()
if(DEFINED GROUP_GROUP AND (DEFINED GROUP_VMA OR DEFINED GROUP_LMA))
message(FATAL_ERROR "zephyr_linker_group(GROUP ...) cannot be used with "
"VMA or LMA"
)
endif()
if(DEFINED GROUP_SYMBOL)
if(NOT ${GROUP_SYMBOL} IN_LIST symbol_values)
message(FATAL_ERROR "zephyr_linker_group(SYMBOL ...) given unknown value")
endif()
endif()
set(GROUP)
zephyr_linker_arg_val_list(GROUP "${single_args}")
string(REPLACE ";" "\;" GROUP "${GROUP}")
set_property(TARGET linker
APPEND PROPERTY GROUPS "{${GROUP}}"
)
endfunction()
# Usage:
# zephyr_linker_section(NAME <name> [GROUP <group>]
# [VMA <region|group>] [LMA <region|group>]
# [ADDRESS <address>] [ALIGN <alignment>]
# [SUBALIGN <alignment>] [FLAGS <flags>]
# [HIDDEN] [NOINPUT] [NOINIT]
# [PASS [NOT] <name>]
# )
#
# Zephyr linker output section.
# This function specifies an output section for the linker.
#
# When using zephyr_linker_section(NAME <name>) an output section with <name>
# will be configured. This section will default include input sections of the
# same name, unless NOINPUT is specified.
# This means the section named `foo` will default include the sections matching
# `foo` and `foo.*`
# Each output section will define the following linker symbols:
# __<name>_start : Start address of the section
# __<name>_end : End address of the section
# __<name>_size : Size of the section
# __<name>_load_start : Load address of the section, if VMA = LMA then this
# value will be identical to `__<name>_start`
#
# The location of the output section can be controlled using LMA, VMA, and
# address parameters
#
# NAME <name> : Name of the output section.
# VMA <region|group> : VMA Memory region or group where code / data is located runtime (VMA)
# If <group> is used here it means the section will use the
# same VMA memory region as <group> but will not be placed
# inside the group itself, see also GROUP argument.
# KVMA <region|group> : Kernel VMA Memory region or group where code / data is located runtime (VMA)
# When MMU is active and Kernel VM base and offset is different
# from SRAM base and offset, then the region defined by KVMA will
# be used as VMA.
# If <group> is used here it means the section will use the
# same VMA memory region as <group> but will not be placed
# inside the group itself, see also GROUP argument.
# LMA <region|group> : Memory region or group where code / data is loaded (LMA)
# If VMA is different from LMA, the code / data will be loaded
# from LMA into VMA at bootup, this is usually the case for
# global or static variables that are loaded in rom and copied
# to ram at boot time.
# If <group> is used here it means the section will use the
# same LMA memory region as <group> but will not be placed
# inside the group itself, see also GROUP argument.
# GROUP <group> : Place this section inside the group <group>
# ADDRESS <address> : Specific address to use for this section.
# ALIGN_WITH_INPUT : The alignment difference between VMA and LMA is kept
# intact for this section.
# ALIGN <alignment> : Align the execution address with alignment.
# SUBALIGN <alignment>: Align input sections with alignment value.
# ENDALIGN <alignment>: Align the end so that next output section will start aligned.
# This only has effect on Scatter scripts.
# Note: Regarding all alignment attributes. Not all linkers may handle alignment
# in identical way. For example the Scatter file will align both load and
# execution address (LMA and VMA) to be aligned when given the ALIGN attribute.
# NOINPUT : No default input sections will be defined, to setup input
# sections for section <name>, the corresponding
# `zephyr_linker_section_configure()` must be used.
# PASS [NOT] <name> : Linker pass iteration where this section should be active.
# Default a section will be present during all linker passes
# but in cases a section shall only be present at a specific
# pass, this argument can be used. For example to only have
# this section present on the `TEST` linker pass, use `PASS TEST`.
# It is possible to negate <name>, such as `PASS NOT <name>`.
# For example, `PASS NOT TEST` means the call is effective
# on all but the `TEST` linker pass iteration.
#
# Note: VMA and LMA are mutual exclusive with GROUP
#
function(zephyr_linker_section)
set(options "ALIGN_WITH_INPUT;HIDDEN;NOINIT;NOINPUT")
set(single_args "ADDRESS;ALIGN;ENDALIGN;GROUP;KVMA;LMA;NAME;SUBALIGN;TYPE;VMA")
set(multi_args "PASS")
cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(SECTION_UNPARSED_ARGUMENTS)
message(WARNING "zephyr_linker_section(${ARGV0} ...) given unknown "
"arguments: ${SECTION_UNPARSED_ARGUMENTS}"
)
endif()
if(DEFINED SECTION_GROUP AND (DEFINED SECTION_VMA OR DEFINED SECTION_LMA))
message(FATAL_ERROR "zephyr_linker_section(GROUP ...) cannot be used with "
"VMA or LMA"
)
endif()
if(DEFINED SECTION_KVMA)
# If KVMA is set and the Kernel virtual memory settings reqs are met, we
# substitute the VMA setting with the specified KVMA value.
if(CONFIG_MMU)
math(EXPR KERNEL_MEM_VM_OFFSET
"(${CONFIG_KERNEL_VM_BASE} + ${CONFIG_KERNEL_VM_OFFSET})\
- (${CONFIG_SRAM_BASE_ADDRESS} + ${CONFIG_SRAM_OFFSET})"
)
if(NOT (${KERNEL_MEM_VM_OFFSET} EQUAL 0))
set(SECTION_VMA ${SECTION_KVMA})
set(SECTION_KVMA)
endif()
endif()
endif()
if(DEFINED SECTION_PASS)
list(LENGTH SECTION_PASS pass_length)
if(${pass_length} GREATER 1)
list(GET SECTION_PASS 0 pass_elem_0)
if((NOT (${pass_elem_0} STREQUAL "NOT")) OR (${pass_length} GREATER 2))
message(FATAL_ERROR "zephyr_linker_section(PASS takes maximum "
"a single argument of the form: '<pass name>' or 'NOT <pass_name>'.")
endif()
endif()
endif()
set(SECTION)
zephyr_linker_arg_val_list(SECTION "${single_args}")
zephyr_linker_arg_val_list(SECTION "${options}")
zephyr_linker_arg_val_list(SECTION "${multi_args}")
string(REPLACE ";" "\;" SECTION "${SECTION}")
set_property(TARGET linker
APPEND PROPERTY SECTIONS "{${SECTION}}"
)
endfunction()
# Usage:
# zephyr_linker_section_ifdef(<setting>
# NAME <name> [VMA <region>] [LMA <region>]
# [ADDRESS <address>] [ALIGN <alignment>]
# [SUBALIGN <alignment>] [FLAGS <flags>]
# [HIDDEN] [NOINPUT] [NOINIT]
# [PASS <no> [<no>...]
# )
#
# Will create an output section if <setting> is enabled.
#
# <setting>: Setting to check for True value before invoking
# zephyr_linker_section()
#
# See zephyr_linker_section() description for other supported arguments.
#
macro(zephyr_linker_section_ifdef feature_toggle)
if(${${feature_toggle}})
zephyr_linker_section(${ARGN})
endif()
endmacro()
# Usage:
# zephyr_iterable_section(NAME <name> [GROUP <group>]
# [VMA <region|group>] [LMA <region|group>]
# [ALIGN_WITH_INPUT] [SUBALIGN <alignment>]
# )
#
#
# Define an output section which will set up an iterable area
# of equally-sized data structures. For use with STRUCT_SECTION_ITERABLE.
# Input sections will be sorted by name in lexicographical order.
#
# Each list for an input section will define the following linker symbols:
# _<name>_list_start: Start of the iterable list
# _<name>_list_end : End of the iterable list
#
# The output section will be named `<name>_area` and define the following linker
# symbols:
# __<name>_area_start : Start address of the section
# __<name>_area_end : End address of the section
# __<name>_area_size : Size of the section
# __<name>_area_load_start : Load address of the section, if VMA = LMA then this
# value will be identical to `__<name>_area_start`
#
# NAME <name> : Name of the struct type, the output section be named
# accordingly as: <name>_area.
# VMA <region|group> : VMA Memory region where code / data is located runtime (VMA)
# LMA <region|group> : Memory region where code / data is loaded (LMA)
# If VMA is different from LMA, the code / data will be loaded
# from LMA into VMA at bootup, this is usually the case for
# global or static variables that are loaded in rom and copied
# to ram at boot time.
# GROUP <group> : Place this section inside the group <group>
# ADDRESS <address> : Specific address to use for this section.
# ALIGN_WITH_INPUT : The alignment difference between VMA and LMA is kept
# intact for this section.
# NUMERIC : Use numeric sorting.
# SUBALIGN <alignment>: Force input alignment with size <alignment>
# Note: Regarding all alignment attributes. Not all linkers may handle alignment
# in identical way. For example the Scatter file will align both load and
# execution address (LMA and VMA) to be aligned when given the ALIGN attribute.
#/
function(zephyr_iterable_section)
# ToDo - Should we use ROM, RAM, etc as arguments ?
set(options "ALIGN_WITH_INPUT;NUMERIC")
set(single_args "GROUP;LMA;NAME;SUBALIGN;VMA")
set(multi_args "")
set(align_input)
cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(NOT DEFINED SECTION_NAME)
message(FATAL_ERROR "zephyr_iterable_section(${ARGV0} ...) missing "
"required argument: NAME"
)
endif()
if(NOT DEFINED SECTION_SUBALIGN)
message(FATAL_ERROR "zephyr_iterable_section(${ARGV0} ...) missing "
"required argument: SUBALIGN"
)
endif()
if(SECTION_ALIGN_WITH_INPUT)
set(align_input ALIGN_WITH_INPUT)
endif()
if(SECTION_NUMERIC)
set(INPUT "._${SECTION_NAME}.static.*_?_*;._${SECTION_NAME}.static.*_??_*")
else()
set(INPUT "._${SECTION_NAME}.static.*")
endif()
zephyr_linker_section(
NAME ${SECTION_NAME}_area
GROUP "${SECTION_GROUP}"
VMA "${SECTION_VMA}" LMA "${SECTION_LMA}"
NOINPUT ${align_input} SUBALIGN ${SECTION_SUBALIGN}
)
zephyr_linker_section_configure(
SECTION ${SECTION_NAME}_area
INPUT "${INPUT}"
SYMBOLS _${SECTION_NAME}_list_start _${SECTION_NAME}_list_end
KEEP SORT NAME
)
endfunction()
# Usage:
# zephyr_linker_section_obj_level(SECTION <section> LEVEL <level>)
#
# generate a symbol to mark the start of the objects array for
# the specified object and level, then link all of those objects
# (sorted by priority). Ensure the objects aren't discarded if there is
# no direct reference to them.
#
# This is useful content such as struct devices.
#
# For example: zephyr_linker_section_obj_level(SECTION init LEVEL PRE_KERNEL_1)
# will create an input section matching `.z_init_PRE_KERNEL_1?_` and
# `.z_init_PRE_KERNEL_1??_`.
#
# SECTION <section>: Section in which the objects shall be placed
# LEVEL <level> : Priority level, all input sections matching the level
# will be sorted.
#
function(zephyr_linker_section_obj_level)
set(single_args "SECTION;LEVEL")
cmake_parse_arguments(OBJ "" "${single_args}" "" ${ARGN})
if(NOT DEFINED OBJ_SECTION)
message(FATAL_ERROR "zephyr_linker_section_obj_level(${ARGV0} ...) "
"missing required argument: SECTION"
)
endif()
if(NOT DEFINED OBJ_LEVEL)
message(FATAL_ERROR "zephyr_linker_section_obj_level(${ARGV0} ...) "
"missing required argument: LEVEL"
)
endif()
zephyr_linker_section_configure(
SECTION ${OBJ_SECTION}
INPUT ".z_${OBJ_SECTION}_${OBJ_LEVEL}?_*"
SYMBOLS __${OBJ_SECTION}_${OBJ_LEVEL}_start
KEEP SORT NAME
)
zephyr_linker_section_configure(
SECTION ${OBJ_SECTION}
INPUT ".z_${OBJ_SECTION}_${OBJ_LEVEL}??_*"
KEEP SORT NAME
)
endfunction()
# Usage:
# zephyr_linker_section_configure(SECTION <section> [ALIGN <alignment>]
# [PASS [NOT] <name>] [PRIO <no>] [SORT <sort>]
# [ANY] [FIRST] [KEEP]
# )
#
# Configure an output section with additional input sections.
# An output section can be configured with additional input sections besides its
# default section.
# For example, to add the input section `foo` to the output section bar, with KEEP
# attribute, call:
# zephyr_linker_section_configure(SECTION bar INPUT foo KEEP)
#
# ALIGN <alignment> : Will align the input section placement inside the load
# region with <alignment>
# FIRST : The first input section in the list should be marked as
# first section in output.
# SORT <NAME> : Sort the input sections according to <type>.
# Currently only `NAME` is supported.
# KEEP : Do not eliminate input section during linking
# PRIO : The priority of the input section. Per default, input
# sections order is not guaranteed by all linkers, but
# using priority Zephyr CMake linker will create sections
# such that order can be guaranteed. All unprioritized
# sections will internally be given a CMake process order
# priority counting from 100, so first unprioritized section
# is handled internal prio 100, next 101, and so on.
# To ensure a specific input section come before those,
# you may use `PRIO 50`, `PRIO 20` and so on.
# To ensure an input section is at the end, it is advised
# to use `PRIO 200` and above.
# PASS [NOT] <name> : The call should only be considered for linker pass where
# <name> is defined. It is possible to negate <name>, such
# as `PASS NOT <name>.
# For example, `PASS TEST` means the call is only effective
# on the `TEST` linker pass iteration. `PASS NOT TEST` on
# all iterations the are not `TEST`.
# FLAGS <flags> : Special section flags such as "+RO", +XO, "+ZI".
# ANY : ANY section flag in scatter file.
# The FLAGS and ANY arguments only has effect for scatter files.
#
function(zephyr_linker_section_configure)
set(options "ANY;FIRST;KEEP")
set(single_args "ALIGN;OFFSET;PRIO;SECTION;SORT")
set(multi_args "FLAGS;INPUT;PASS;SYMBOLS")
cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
if(SECTION_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_linker_section_configure(${ARGV0} ...) given unknown arguments: ${SECTION_UNPARSED_ARGUMENTS}")
endif()
if(DEFINED SECTION_SYMBOLS)
list(LENGTH SECTION_SYMBOLS symbols_count)
if(${symbols_count} GREATER 2)
message(FATAL_ERROR "zephyr_linker_section_configure(SYMBOLS [start_sym [end_sym]]) takes maximum two symbol names (start and end).")
endif()
endif()
if(DEFINED SECTION_PASS)
list(LENGTH SECTION_PASS pass_length)
if(${pass_length} GREATER 1)
list(GET SECTION_PASS 0 pass_elem_0)
if((NOT (${pass_elem_0} STREQUAL "NOT")) OR (${pass_length} GREATER 2))
message(FATAL_ERROR "zephyr_linker_section_configure(PASS takes maximum "
"a single argument of the form: '<pass name>' or 'NOT <pass_name>'.")
endif()
endif()
endif()
set(SECTION)
zephyr_linker_arg_val_list(SECTION "${single_args}")
zephyr_linker_arg_val_list(SECTION "${options}")
zephyr_linker_arg_val_list(SECTION "${multi_args}")
string(REPLACE ";" "\;" SECTION "${SECTION}")
set_property(TARGET linker
APPEND PROPERTY SECTION_SETTINGS "{${SECTION}}"
)
endfunction()
# Usage:
# zephyr_linker_symbol(SYMBOL <name> EXPR <expr>)
#
# Add additional user defined symbol to the generated linker script.
#
# SYMBOL <name>: Symbol name to be available.
# EXPR <expr> : Expression that defines the symbol. Due to linker limitations
# all expressions should only contain simple math, such as
# `+, -, *` and similar. The expression will go directly into the
# linker, and all `@<symbol>@` will be replaced with the referred
# symbol.
#
# Example:
# To create a new symbol `bar` pointing to the start VMA address of section
# `foo` + 1024, one can write:
# zephyr_linker_symbol(SYMBOL bar EXPR "(@foo@ + 1024)")
#
function(zephyr_linker_symbol)
set(single_args "EXPR;SYMBOL")
cmake_parse_arguments(SYMBOL "" "${single_args}" "" ${ARGN})
if(SECTION_UNPARSED_ARGUMENTS)
message(WARNING "zephyr_linker_symbol(${ARGV0} ...) given unknown "
"arguments: ${SECTION_UNPARSED_ARGUMENTS}"
)
endif()
set(SYMBOL)
zephyr_linker_arg_val_list(SYMBOL "${single_args}")
string(REPLACE ";" "\;" SYMBOL "${SYMBOL}")
set_property(TARGET linker
APPEND PROPERTY SYMBOLS "{${SYMBOL}}"
)
endfunction()
# Internal helper macro for zephyr_linker*() functions.
# The macro will create a list of argument-value pairs for defined arguments
# that can be passed on to linker script generators and processed as a CMake
# function call using cmake_parse_arguments.
#
# For example, having the following argument and value:
# FOO: bar
# BAZ: <undefined>
# QUX: option set
#
# will create a list as: "FOO;bar;QUX;TRUE" which can then be parsed as argument
# list later.
macro(zephyr_linker_arg_val_list list arguments)
foreach(arg ${arguments})
if(DEFINED ${list}_${arg})
list(APPEND ${list} ${arg} "${${list}_${arg}}")
endif()
endforeach()
endmacro()
########################################################
# 6. Function helper macros
########################################################
#
# Set of CMake macros to facilitate argument processing when defining functions.
#
#
# Helper macro for verifying that at least one of the required arguments has
# been provided by the caller.
#
# A FATAL_ERROR will be raised if not one of the required arguments has been
# passed by the caller.
#
# Usage:
# zephyr_check_arguments_required(<function_name> <prefix> <arg1> [<arg2> ...])
#
macro(zephyr_check_arguments_required function prefix)
set(check_defined DEFINED)
zephyr_check_flags_required(${function} ${prefix} ${ARGN})
set(check_defined)
endmacro()
#
# Helper macro for verifying that at least one of the required flags has
# been provided by the caller.
#
# A FATAL_ERROR will be raised if not one of the required arguments has been
# passed by the caller.
#
# Usage:
# zephyr_check_flags_required(<function_name> <prefix> <flag1> [<flag2> ...])
#
macro(zephyr_check_flags_required function prefix)
set(required_found FALSE)
foreach(required ${ARGN})
if(${check_defined} ${prefix}_${required})
set(required_found TRUE)
endif()
endforeach()
if(NOT required_found)
message(FATAL_ERROR "${function}(...) missing a required argument: ${ARGN}")
endif()
endmacro()
#
# Helper macro for verifying that all the required arguments have been
# provided by the caller.
#
# A FATAL_ERROR will be raised if one of the required arguments is missing.
#
# Usage:
# zephyr_check_arguments_required_all(<function_name> <prefix> <arg1> [<arg2> ...])
#
macro(zephyr_check_arguments_required_all function prefix)
foreach(required ${ARGN})
if(NOT DEFINED ${prefix}_${required})
message(FATAL_ERROR "${function}(...) missing a required argument: ${required}")
endif()
endforeach()
endmacro()
#
# Helper macro for verifying that none of the mutual exclusive arguments are
# provided together.
#
# A FATAL_ERROR will be raised if any of the arguments are given together.
#
# Usage:
# zephyr_check_arguments_exclusive(<function_name> <prefix> <arg1> <arg2> [<arg3> ...])
#
macro(zephyr_check_arguments_exclusive function prefix)
set(check_defined DEFINED)
zephyr_check_flags_exclusive(${function} ${prefix} ${ARGN})
set(check_defined)
endmacro()
#
# Helper macro for verifying that none of the mutual exclusive flags are
# provided together.
#
# A FATAL_ERROR will be raised if any of the flags are given together.
#
# Usage:
# zephyr_check_flags_exclusive(<function_name> <prefix> <flag1> <flag2> [<flag3> ...])
#
macro(zephyr_check_flags_exclusive function prefix)
set(args_defined)
foreach(arg ${ARGN})
if(${check_defined} ${prefix}_${arg})
list(APPEND args_defined ${arg})
endif()
endforeach()
list(LENGTH args_defined exclusive_length)
if(exclusive_length GREATER 1)
list(POP_FRONT args_defined argument)
message(FATAL_ERROR "${function}(${argument} ...) cannot be used with "
"argument: ${args_defined}"
)
endif()
endmacro()
########################################################
# 7. Linkable loadable extensions (llext)
########################################################
#
# These functions simplify the creation and management of linkable
# loadable extensions (llexts).
#
# Add a custom target that compiles a single source file to a .llext file.
#
# Output and source files must be specified using the OUTPUT and SOURCES
# arguments. Only one source file is currently supported.
#
# The llext code will be compiled with mostly the same C compiler flags used
# in the Zephyr build, but with some important modifications. The list of
# flags to remove and flags to append is controlled respectively by the
# LLEXT_REMOVE_FLAGS and LLEXT_APPEND_FLAGS global variables.
# The C_FLAGS argument can be used to pass additional compiler flags to the
# compilation of this particular llext.
#
# Example usage:
# add_llext_target(hello_world
# OUTPUT ${PROJECT_BINARY_DIR}/hello_world.llext
# SOURCES ${PROJECT_SOURCE_DIR}/src/llext/hello_world.c
# C_FLAGS -Werror
# )
# will compile the source file src/llext/hello_world.c to a file
# ${PROJECT_BINARY_DIR}/hello_world.llext, adding -Werror to the compilation.
#
function(add_llext_target target_name)
set(single_args OUTPUT)
set(multi_args SOURCES;C_FLAGS)
cmake_parse_arguments(PARSE_ARGV 1 LLEXT "${options}" "${single_args}" "${multi_args}")
# Check that the llext subsystem is enabled for this build
if (NOT CONFIG_LLEXT)
message(FATAL_ERROR "add_llext_target: CONFIG_LLEXT must be enabled")
endif()
# Output file must be provided
if(NOT LLEXT_OUTPUT)
message(FATAL_ERROR "add_llext_target: OUTPUT argument must be provided")
endif()
# Source list length must currently be 1
list(LENGTH LLEXT_SOURCES source_count)
if(NOT source_count EQUAL 1)
message(FATAL_ERROR "add_llext_target: only one source file is supported")
endif()
set(output_file ${LLEXT_OUTPUT})
set(source_file ${LLEXT_SOURCES})
get_filename_component(output_name ${output_file} NAME)
# Add user-visible target and dependency
add_custom_target(${target_name}
COMMENT "Compiling ${output_name}"
DEPENDS ${output_file}
)
# Convert the LLEXT_REMOVE_FLAGS list to a regular expression, and use it to
# filter out these flags from the Zephyr target settings
list(TRANSFORM LLEXT_REMOVE_FLAGS
REPLACE "(.+)" "^\\1$"
OUTPUT_VARIABLE llext_remove_flags_regexp
)
string(REPLACE ";" "|" llext_remove_flags_regexp "${llext_remove_flags_regexp}")
set(zephyr_flags
"$<TARGET_PROPERTY:zephyr_interface,INTERFACE_COMPILE_OPTIONS>"
)
set(zephyr_filtered_flags
"$<FILTER:${zephyr_flags},EXCLUDE,${llext_remove_flags_regexp}>"
)
# Compile the source file to an object file using current Zephyr settings
# but a different set of flags
add_library(${target_name}_lib OBJECT ${source_file})
target_compile_definitions(${target_name}_lib PRIVATE
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_COMPILE_DEFINITIONS>
)
target_compile_options(${target_name}_lib PRIVATE
${zephyr_filtered_flags}
${LLEXT_APPEND_FLAGS}
${LLEXT_C_FLAGS}
)
target_include_directories(${target_name}_lib PRIVATE
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>
)
target_include_directories(${target_name}_lib SYSTEM PUBLIC
$<TARGET_PROPERTY:zephyr_interface,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
)
add_dependencies(${target_name}_lib
zephyr_interface
zephyr_generated_headers
)
# Arch-specific conversion of the object file to an llext
if(CONFIG_ARM)
# No conversion required, simply copy the object file
add_custom_command(
OUTPUT ${output_file}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:${target_name}_lib> ${output_file}
DEPENDS ${target_name}_lib $<TARGET_OBJECTS:${target_name}_lib>
)
elseif(CONFIG_XTENSA)
# Generate an intermediate file name
get_filename_component(output_dir ${output_file} DIRECTORY)
get_filename_component(output_name_we ${output_file} NAME_WE)
set(pre_output_file ${output_dir}/${output_name_we}.pre.llext)
# Need to convert the object file to a shared library, then strip some sections
add_custom_command(
OUTPUT ${output_file}
BYPRODUCTS ${pre_output_file}
COMMAND ${CMAKE_C_COMPILER} ${LLEXT_APPEND_FLAGS}
-o ${pre_output_file}
$<TARGET_OBJECTS:${target_name}_lib>
COMMAND $<TARGET_PROPERTY:bintools,strip_command>
$<TARGET_PROPERTY:bintools,strip_flag>
$<TARGET_PROPERTY:bintools,strip_flag_remove_section>.xt.*
$<TARGET_PROPERTY:bintools,strip_flag_infile>${pre_output_file}
$<TARGET_PROPERTY:bintools,strip_flag_outfile>${output_file}
$<TARGET_PROPERTY:bintools,strip_flag_final>
DEPENDS ${target_name}_lib $<TARGET_OBJECTS:${target_name}_lib>
)
else()
message(FATAL_ERROR "add_llext_target: unsupported architecture")
endif()
endfunction()