From 6f119d4ce90a1a4f3b491f21d50a286662f79480 Mon Sep 17 00:00:00 2001 From: GUI <39894654+GuEe-GUI@users.noreply.github.com> Date: Tue, 25 Jul 2023 21:31:44 +0800 Subject: [PATCH] AArch64: support public linker scripts (#7831) Signed-off-by: GuEe-GUI --- bsp/qemu-virt64-aarch64/.config | 8 ++ bsp/qemu-virt64-aarch64/SConstruct | 4 - bsp/qemu-virt64-aarch64/link.lds | 109 -------------- bsp/qemu-virt64-aarch64/link_smart.lds | 109 -------------- bsp/qemu-virt64-aarch64/rtconfig.h | 7 + bsp/qemu-virt64-aarch64/rtconfig.py | 4 +- libcpu/Kconfig | 6 + libcpu/aarch64/.gitignore | 1 + libcpu/aarch64/Kconfig | 19 +++ libcpu/aarch64/SConscript | 5 + libcpu/aarch64/common/mmu.c | 4 +- libcpu/aarch64/cortex-a/entry_point.S | 48 ++++++- libcpu/aarch64/link.lds.S | 191 +++++++++++++++++++++++++ tools/building.py | 17 +++ 14 files changed, 302 insertions(+), 230 deletions(-) delete mode 100644 bsp/qemu-virt64-aarch64/link.lds delete mode 100644 bsp/qemu-virt64-aarch64/link_smart.lds create mode 100755 libcpu/aarch64/.gitignore create mode 100644 libcpu/aarch64/Kconfig create mode 100644 libcpu/aarch64/link.lds.S diff --git a/bsp/qemu-virt64-aarch64/.config b/bsp/qemu-virt64-aarch64/.config index 44f181b385..1b1516ad60 100644 --- a/bsp/qemu-virt64-aarch64/.config +++ b/bsp/qemu-virt64-aarch64/.config @@ -94,6 +94,10 @@ CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" CONFIG_RT_VER_NUM=0x50001 CONFIG_RT_USING_STDC_ATOMIC=y + +# +# RT-Thread Architecture +# CONFIG_ARCH_CPU_64BIT=y CONFIG_RT_USING_CACHE=y # CONFIG_RT_USING_HW_ATOMIC is not set @@ -104,6 +108,10 @@ CONFIG_ARCH_MM_MMU=y CONFIG_ARCH_ARM=y CONFIG_ARCH_ARM_MMU=y CONFIG_ARCH_ARMV8=y +CONFIG_ARCH_TEXT_OFFSET=0x80000 +CONFIG_ARCH_RAM_OFFSET=0x40000000 +CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=4096 +CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y # # RT-Thread Components diff --git a/bsp/qemu-virt64-aarch64/SConstruct b/bsp/qemu-virt64-aarch64/SConstruct index 70cd98c4f4..3791a1bfac 100644 --- a/bsp/qemu-virt64-aarch64/SConstruct +++ b/bsp/qemu-virt64-aarch64/SConstruct @@ -40,9 +40,5 @@ Export('rtconfig') # prepare building environment objs = PrepareBuilding(env, RTT_ROOT) -if GetDepend('RT_USING_SMART'): - # use smart link.lds - env['LINKFLAGS'] = env['LINKFLAGS'].replace('link.lds', 'link_smart.lds') - # make a building DoBuilding(TARGET, objs) diff --git a/bsp/qemu-virt64-aarch64/link.lds b/bsp/qemu-virt64-aarch64/link.lds deleted file mode 100644 index 3adad6e44c..0000000000 --- a/bsp/qemu-virt64-aarch64/link.lds +++ /dev/null @@ -1,109 +0,0 @@ -OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") -OUTPUT_ARCH(aarch64) -SECTIONS -{ - . = 0x40080000; - /* . = 0xffff000000080000; */ - - __text_start = .; - .text : - { - KEEP(*(.text.entrypoint)) - KEEP(*(.vectors)) - *(.text) - *(.text.*) - - /* section information for utest */ - . = ALIGN(8); - __rt_utest_tc_tab_start = .; - KEEP(*(UtestTcTab)) - __rt_utest_tc_tab_end = .; - - /* section information for finsh shell */ - . = ALIGN(8); - __fsymtab_start = .; - KEEP(*(FSymTab)) - __fsymtab_end = .; - . = ALIGN(8); - __vsymtab_start = .; - KEEP(*(VSymTab)) - __vsymtab_end = .; - . = ALIGN(8); - - /* section information for modules */ - . = ALIGN(8); - __rtmsymtab_start = .; - KEEP(*(RTMSymTab)) - __rtmsymtab_end = .; - - /* section information for initialization */ - . = ALIGN(8); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - } =0 - __text_end = .; - - .ARM.exidx : - { - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - } - - __rodata_start = .; - .rodata : { *(.rodata) *(.rodata.*) } - __rodata_end = .; - - . = ALIGN(8); - .ctors : - { - PROVIDE(__ctors_start__ = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__ctors_end__ = .); - } - - .dtors : - { - PROVIDE(__dtors_start__ = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE(__dtors_end__ = .); - } - - . = ALIGN(8); - __data_start = .; - .data : - { - *(.data) - *(.data.*) - } - __data_end = .; - - . = ALIGN(8); - __bss_start = .; - .bss : - { - *(.bss) - *(.bss.*) - *(COMMON) - . = ALIGN(8); - } - . = ALIGN(8); - __bss_end = .; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - __data_size = SIZEOF(.data); - __bss_size = SIZEOF(.bss); - - _end = .; -} diff --git a/bsp/qemu-virt64-aarch64/link_smart.lds b/bsp/qemu-virt64-aarch64/link_smart.lds deleted file mode 100644 index 3df5a76afc..0000000000 --- a/bsp/qemu-virt64-aarch64/link_smart.lds +++ /dev/null @@ -1,109 +0,0 @@ -OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") -OUTPUT_ARCH(aarch64) -SECTIONS -{ - /* . = 0x40080000; */ - . = 0xffff000000080000; - - __text_start = .; - .text : - { - KEEP(*(.text.entrypoint)) - KEEP(*(.vectors)) - *(.text) - *(.text.*) - - /* section information for utest */ - . = ALIGN(8); - __rt_utest_tc_tab_start = .; - KEEP(*(UtestTcTab)) - __rt_utest_tc_tab_end = .; - - /* section information for finsh shell */ - . = ALIGN(8); - __fsymtab_start = .; - KEEP(*(FSymTab)) - __fsymtab_end = .; - . = ALIGN(8); - __vsymtab_start = .; - KEEP(*(VSymTab)) - __vsymtab_end = .; - . = ALIGN(8); - - /* section information for modules */ - . = ALIGN(8); - __rtmsymtab_start = .; - KEEP(*(RTMSymTab)) - __rtmsymtab_end = .; - - /* section information for initialization */ - . = ALIGN(8); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - } =0 - __text_end = .; - - .ARM.exidx : - { - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - } - - __rodata_start = .; - .rodata : { *(.rodata) *(.rodata.*) } - __rodata_end = .; - - . = ALIGN(8); - .ctors : - { - PROVIDE(__ctors_start__ = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__ctors_end__ = .); - } - - .dtors : - { - PROVIDE(__dtors_start__ = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE(__dtors_end__ = .); - } - - . = ALIGN(8); - __data_start = .; - .data : - { - *(.data) - *(.data.*) - } - __data_end = .; - - . = ALIGN(8); - __bss_start = .; - .bss : - { - *(.bss) - *(.bss.*) - *(COMMON) - . = ALIGN(8); - } - . = ALIGN(8); - __bss_end = .; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - __data_size = SIZEOF(.data); - __bss_size = SIZEOF(.bss); - - _end = .; -} diff --git a/bsp/qemu-virt64-aarch64/rtconfig.h b/bsp/qemu-virt64-aarch64/rtconfig.h index 5b71c996f6..205d642927 100644 --- a/bsp/qemu-virt64-aarch64/rtconfig.h +++ b/bsp/qemu-virt64-aarch64/rtconfig.h @@ -61,12 +61,19 @@ #define RT_CONSOLE_DEVICE_NAME "uart0" #define RT_VER_NUM 0x50001 #define RT_USING_STDC_ATOMIC + +/* RT-Thread Architecture */ + #define ARCH_CPU_64BIT #define RT_USING_CACHE #define ARCH_MM_MMU #define ARCH_ARM #define ARCH_ARM_MMU #define ARCH_ARMV8 +#define ARCH_TEXT_OFFSET 0x80000 +#define ARCH_RAM_OFFSET 0x40000000 +#define ARCH_SECONDARY_CPU_STACK_SIZE 4096 +#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS /* RT-Thread Components */ diff --git a/bsp/qemu-virt64-aarch64/rtconfig.py b/bsp/qemu-virt64-aarch64/rtconfig.py index dd6cbdc4a7..98d1a38cec 100644 --- a/bsp/qemu-virt64-aarch64/rtconfig.py +++ b/bsp/qemu-virt64-aarch64/rtconfig.py @@ -13,6 +13,7 @@ if PLATFORM == 'gcc': PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-' CC = PREFIX + 'gcc' CXX = PREFIX + 'g++' + CPP = PREFIX + 'cpp' AS = PREFIX + 'gcc' AR = PREFIX + 'ar' LINK = PREFIX + 'gcc' @@ -25,10 +26,11 @@ if PLATFORM == 'gcc': AFPFLAGS = ' ' DEVICE = ' -march=armv8-a -mtune=cortex-a53 -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing' + CPPFLAGS= ' -E -P -x assembler-with-cpp' CXXFLAGS= DEVICE + CFPFLAGS + ' -Wall -fdiagnostics-color=always' CFLAGS = DEVICE + CFPFLAGS + ' -Wall -Wno-cpp -std=gnu99 -fdiagnostics-color=always' AFLAGS = ' -c' + AFPFLAGS + ' -x assembler-with-cpp' - LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds' + ' -lsupc++ -lgcc -static' + LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds' + ' -lsupc++ -lgcc -static' CPATH = '' LPATH = '' diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 0a667f6281..897ce60555 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -1,3 +1,5 @@ +menu "RT-Thread Architecture" + config ARCH_CPU_64BIT bool @@ -231,3 +233,7 @@ config ARCH_HOST_SIMULATOR config ARCH_CPU_STACK_GROWS_UPWARD bool default n + +source "$RTT_DIR/libcpu/aarch64/Kconfig" + +endmenu diff --git a/libcpu/aarch64/.gitignore b/libcpu/aarch64/.gitignore new file mode 100755 index 0000000000..feb550d190 --- /dev/null +++ b/libcpu/aarch64/.gitignore @@ -0,0 +1 @@ +link.lds diff --git a/libcpu/aarch64/Kconfig b/libcpu/aarch64/Kconfig new file mode 100644 index 0000000000..4bb9f1ffe7 --- /dev/null +++ b/libcpu/aarch64/Kconfig @@ -0,0 +1,19 @@ +if ARCH_ARMV8 && ARCH_CPU_64BIT + +config ARCH_TEXT_OFFSET + hex "Text offset" + default 0x200000 + +config ARCH_RAM_OFFSET + hex "RAM offset" + default 0 + +config ARCH_SECONDARY_CPU_STACK_SIZE + int "Secondary CPU stack size" + default 4096 + +config ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS + bool + default y + +endif diff --git a/libcpu/aarch64/SConscript b/libcpu/aarch64/SConscript index 5fca2b473b..d726d2d1f2 100644 --- a/libcpu/aarch64/SConscript +++ b/libcpu/aarch64/SConscript @@ -8,6 +8,11 @@ Import('rtconfig') cwd = GetCurrentDir() group = [] list = os.listdir(cwd) +bsp_path = Dir('#').abspath + +if not os.path.exists(bsp_path + "/link.lds"): + Env['LINKFLAGS'] = Env['LINKFLAGS'].replace('link.lds', cwd + "/link.lds") + Preprocessing("link.lds.S", ".lds", CPPPATH=[bsp_path]) # add common code files group = group + SConscript(os.path.join('common', 'SConscript')) diff --git a/libcpu/aarch64/common/mmu.c b/libcpu/aarch64/common/mmu.c index cd55948729..88df1f89ff 100644 --- a/libcpu/aarch64/common/mmu.c +++ b/libcpu/aarch64/common/mmu.c @@ -777,8 +777,8 @@ void rt_hw_mem_setup_early(unsigned long *tbl0, unsigned long *tbl1, #ifdef RT_USING_SMART unsigned long va = KERNEL_VADDR_START; #else - extern unsigned char __start; - unsigned long va = (unsigned long) &__start; + extern unsigned char _start; + unsigned long va = (unsigned long) &_start; va = RT_ALIGN_DOWN(va, 0x200000); #endif diff --git a/libcpu/aarch64/cortex-a/entry_point.S b/libcpu/aarch64/cortex-a/entry_point.S index e7e5650ea2..3bdca7b81c 100644 --- a/libcpu/aarch64/cortex-a/entry_point.S +++ b/libcpu/aarch64/cortex-a/entry_point.S @@ -6,13 +6,51 @@ * Date Author Notes * 2020-01-15 bigmagic the first version * 2020-08-10 SummerGift support clang compiler + * 2023-04-29 GuEe-GUI support kernel's ARM64 boot header */ #include "rtconfig.h" -.section ".text.entrypoint","ax" -.global __start -__start: + .section ".text.entrypoint","ax" + +#ifdef RT_USING_OFW +/* + * Our goal is to boot the rt-thread as possible without modifying the + * bootloader's config, so we use the kernel's boot header for ARM64: + * https://www.kernel.org/doc/html/latest/arm64/booting.html#call-the-kernel-image + */ +_head: + b _start /* Executable code */ + .long 0 /* Executable code */ + .quad _text_offset /* Image load offset from start of RAM, little endian */ + .quad _end - _head /* Effective Image size, little endian (_end defined in link.lds) */ + .quad 0xa /* Kernel flags, little endian */ + .quad 0 /* Reserved */ + .quad 0 /* Reserved */ + .quad 0 /* Reserved */ + .ascii "ARM\x64" /* Magic number */ + .long 0 /* Reserved (used for PE COFF offset) */ +#endif +/* Variable registers: x21~x28 */ +dtb_paddr .req x21 +boot_arg0 .req x22 +boot_arg1 .req x23 +boot_arg2 .req x24 +stack_top .req x25 + + .global _start +_start: +/* + * Boot CPU general-purpose register settings: + * x0 = physical address of device tree blob (dtb) in system RAM. + * x1 = 0 (reserved for future use) + * x2 = 0 (reserved for future use) + * x3 = 0 (reserved for future use) + */ + mov dtb_paddr, x0 + mov boot_arg0, x1 + mov boot_arg1, x2 + mov boot_arg2, x3 #ifdef ARCH_ARM_BOOTWITH_FLUSH_CACHE bl __asm_flush_dcache_all #endif @@ -127,8 +165,8 @@ __start: dsb sy #ifdef RT_USING_SMART - ldr x2, =__start - GET_PHY x3, __start + ldr x2, =_start + GET_PHY x3, _start sub x3, x3, x2 #else mov x3,0 diff --git a/libcpu/aarch64/link.lds.S b/libcpu/aarch64/link.lds.S new file mode 100644 index 0000000000..f3528c6e3a --- /dev/null +++ b/libcpu/aarch64/link.lds.S @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2017-5-30 bernard first version + */ + +#include "rtconfig.h" + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +#ifndef ARCH_TEXT_OFFSET +#define ARCH_TEXT_OFFSET 0x200000 /* We always boot in address where is 2MB aligned */ +#endif + +#ifndef ARCH_RAM_OFFSET +#define ARCH_RAM_OFFSET 0 +#endif + +SECTIONS +{ + _text_offset = ARCH_TEXT_OFFSET; + +#ifdef RT_USING_SMART + . = KERNEL_VADDR_START + _text_offset; +#else + . = ARCH_RAM_OFFSET + _text_offset; +#endif + + .text : + { + PROVIDE(__text_start = .); + + KEEP(*(.text.entrypoint)) /* The entry point */ + *(.vectors) + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for utest */ + . = ALIGN(8); + PROVIDE(__rt_utest_tc_tab_start = .); + KEEP(*(UtestTcTab)) + PROVIDE(__rt_utest_tc_tab_end = .); + + /* section information for finsh shell */ + . = ALIGN(8); + PROVIDE(__fsymtab_start = .); + KEEP(*(FSymTab)) + PROVIDE(__fsymtab_end = .); + . = ALIGN(8); + PROVIDE(__vsymtab_start = .); + KEEP(*(VSymTab)) + PROVIDE(__vsymtab_end = .); + . = ALIGN(8); + + /* section information for modules */ + . = ALIGN(8); + PROVIDE(__rtmsymtab_start = .); + KEEP(*(RTMSymTab)) + PROVIDE(__rtmsymtab_end = .); + + /* section information for initialization */ + . = ALIGN(8); + PROVIDE(__rt_init_start = .); + KEEP(*(SORT(.rti_fn*))) + PROVIDE(__rt_init_end = .); + + /* section information for rt_ofw. */ + . = ALIGN(16); + PROVIDE(__rt_ofw_data_start = .); + KEEP(*(SORT(.rt_ofw_data.*))) + PROVIDE(__rt_ofw_data_end = .); + . = ALIGN(16); + + PROVIDE(__text_end = .); + } + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + + . = ALIGN(8); + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(16); + _gp = ABSOLUTE(.); /* Base of small data */ + + *(.sdata) + *(.sdata.*) + *(.rel.local) + } + + . = ALIGN(8); + .ctors : + { + PROVIDE(__ctors_start = .); + /* new GCC version uses .init_array */ + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE(__ctors_end = .); + } + + .dtors : + { + PROVIDE(__dtors_start = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end = .); + } + + . = ALIGN(16); + .bss : + { + /* + * We need some free space to page or cpu stack, move .bss.noclean.* + * to optimize size. + */ + PROVIDE(__bss_noclean_start = .); + *(.bss.noclean.*) + PROVIDE(__bss_noclean_end = .); + . = ALIGN(8); + PROVIDE(__bss_start = .); + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + . = ALIGN(8); + PROVIDE(__bss_end = .); + } + + /* + * We should make the bootloader know the size of memory we need, + * so we MUST calc the image's size with section '.bss'. + */ + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + __data_size = SIZEOF(.data); + __bss_size = SIZEOF(.bss); +} diff --git a/tools/building.py b/tools/building.py index 0f55d9bca2..13a7b48270 100644 --- a/tools/building.py +++ b/tools/building.py @@ -513,6 +513,23 @@ def AddDepend(option): else: print('AddDepend arguements are illegal!') +def Preprocessing(input, suffix, output = None, CPPPATH = None): + if hasattr(rtconfig, "CPP") and hasattr(rtconfig, "CPPFLAGS"): + if output == None: + import re + output = re.sub(r'[\.]+.*', suffix, input) + inc = ' ' + cpppath = CPPPATH + for cpppath_item in cpppath: + inc += ' -I' + cpppath_item + CPP = rtconfig.EXEC_PATH + '/' + rtconfig.CPP + if not os.path.exists(CPP): + CPP = rtconfig.CPP + CPP += rtconfig.CPPFLAGS + path = GetCurrentDir() + '/' + os.system(CPP + inc + ' ' + path + input + ' -o ' + path + output) + else: + print('CPP tool or CPPFLAGS is undefined in rtconfig!') def MergeGroup(src_group, group): src_group['src'] = src_group['src'] + group['src']