Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ jobs:
matrix:
compiler: [gcc, clang]
architecture: [arm, riscv]
link_mode: [static]
include:
- compiler: gcc
architecture: arm
link_mode: dynamic
- compiler: clang
architecture: arm
link_mode: dynamic
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -18,25 +26,29 @@ jobs:
sudo apt-get install -q -y graphviz jq
sudo apt-get install -q -y qemu-user
sudo apt-get install -q -y build-essential
sudo apt-get install -q -y gcc-arm-linux-gnueabihf
- name: Build artifacts
env:
CC: ${{ matrix.compiler }}
run: |
make distclean config ARCH=${{ matrix.architecture }}
make ARCH=${{ matrix.architecture }} LINK_MODE=${{ matrix.link_mode }}
- name: IR regression tests
run: |
make check-snapshot || exit 1
make check-snapshot LINK_MODE=${{ matrix.link_mode }} || exit 1
- name: Sanitizer-enabled stage 0 tests
env:
CC: ${{ matrix.compiler }}
run: |
make check-sanitizer || exit 1
make check-sanitizer LINK_MODE=${{ matrix.link_mode }} || exit 1
- name: Unit tests
run: |
make check || exit 1
make check LINK_MODE=${{ matrix.link_mode }} || exit 1

host-arm:
runs-on: ubuntu-24.04
strategy:
matrix:
link_mode: [static, dynamic]
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -52,9 +64,9 @@ jobs:
apt-get update -qq -y
apt-get install -yqq build-essential
run: |
make config ARCH=arm
make check-sanitizer || exit 1
make check || exit 1
make ARCH=arm LINK_MODE=${{ matrix.link_mode }}
make check-sanitizer LINK_MODE=${{ matrix.link_mode }} || exit 1
make check LINK_MODE=${{ matrix.link_mode }} || exit 1

coding-style:
runs-on: ubuntu-24.04
Expand Down
55 changes: 36 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,28 @@ ARCH ?= $(firstword $(ARCHS))
HOST_ARCH = $(shell arch 2>/dev/null)
SRCDIR := $(shell find src -type d)
LIBDIR := $(shell find lib -type d)
LINK_MODES = static dynamic

BUILTIN_LIBC ?= c.c
STAGE0_FLAGS ?= --dump-ir
STAGE1_FLAGS ?=
ifeq ($(LINK_MODE),dynamic)
ifeq ($(ARCH),riscv)
# TODO: implement dynamic linking for RISC-V.
$(error "Dynamic linking mode is not implemented for RISC-V")
endif
BUILTIN_LIBC := c.h
STAGE0_FLAGS += --dynlink
STAGE1_FLAGS += --dynlink
endif

SRCS := $(wildcard $(patsubst %,%/main.c, $(SRCDIR)))
OBJS := $(SRCS:%.c=$(OUT)/%.o)
deps := $(OBJS:%.o=%.o.d)
TESTS := $(wildcard tests/*.c)
TESTBINS := $(TESTS:%.c=$(OUT)/%.elf)
SNAPSHOTS := $(foreach SNAPSHOT_ARCH,$(ARCHS), $(patsubst tests/%.c, tests/snapshots/%-$(SNAPSHOT_ARCH).json, $(TESTS)))
SNAPSHOTS = $(foreach SNAPSHOT_ARCH,$(ARCHS), $(patsubst tests/%.c, tests/snapshots/%-$(SNAPSHOT_ARCH)-static.json, $(TESTS)))
SNAPSHOTS += $(patsubst tests/%.c, tests/snapshots/%-arm-dynamic.json, $(TESTS))

all: config bootstrap

Expand All @@ -72,44 +87,46 @@ config:

$(OUT)/tests/%.elf: tests/%.c $(OUT)/$(STAGE0)
$(VECHO) " SHECC\t$@\n"
$(Q)$(OUT)/$(STAGE0) --dump-ir -o $@ $< > $(basename $@).log ; \
$(Q)$(OUT)/$(STAGE0) $(STAGE0_FLAGS) -o $@ $< > $(basename $@).log ; \
chmod +x $@ ; $(PRINTF) "Running $@ ...\n"
$(Q)$(TARGET_EXEC) $@ && $(call pass)

check: check-stage0 check-stage2

check-stage0: $(OUT)/$(STAGE0) $(TESTBINS) tests/driver.sh
$(VECHO) " TEST STAGE 0\n"
tests/driver.sh 0
tests/driver.sh 0 $(LINK_MODE)

check-stage2: $(OUT)/$(STAGE2) $(TESTBINS) tests/driver.sh
$(VECHO) " TEST STAGE 2\n"
tests/driver.sh 2
tests/driver.sh 2 $(LINK_MODE)

check-sanitizer: $(OUT)/$(STAGE0)-sanitizer tests/driver.sh
$(VECHO) " TEST STAGE 0 (with sanitizers)\n"
$(Q)cp $(OUT)/$(STAGE0)-sanitizer $(OUT)/shecc
tests/driver.sh 0
tests/driver.sh 0 $(LINK_MODE)
$(Q)rm $(OUT)/shecc

check-snapshots: $(OUT)/$(STAGE0) $(SNAPSHOTS) tests/check-snapshots.sh
$(Q)$(foreach SNAPSHOT_ARCH, $(ARCHS), $(MAKE) distclean config check-snapshot ARCH=$(SNAPSHOT_ARCH) --silent;)
$(VECHO) "Switching backend back to %s\n" $(ARCH)
$(Q)$(MAKE) distclean config ARCH=$(ARCH) --silent
$(Q)$(foreach SNAPSHOT_ARCH, $(ARCHS), $(MAKE) distclean config check-snapshot ARCH=$(SNAPSHOT_ARCH) LINK_MODE=static --silent;)
$(Q)$(MAKE) distclean config check-snapshot ARCH=arm LINK_MODE=dynamic --silent
$(VECHO) "Switching backend back to %s (%s mode)\n" arm static
$(Q)$(MAKE) distclean config ARCH=arm --silent

check-snapshot: $(OUT)/$(STAGE0) tests/check-snapshots.sh
$(VECHO) "Checking snapshot for %s\n" $(ARCH)
tests/check-snapshots.sh $(ARCH)
$(VECHO) "Checking snapshot for %s (%s mode)\n" $(ARCH) $(LINK_MODE)
tests/check-snapshots.sh $(ARCH) $(LINK_MODE)
$(VECHO) " OK\n"

update-snapshots: tests/update-snapshots.sh
$(Q)$(foreach SNAPSHOT_ARCH, $(ARCHS), $(MAKE) distclean config update-snapshot ARCH=$(SNAPSHOT_ARCH) --silent;)
$(VECHO) "Switching backend back to %s\n" $(ARCH)
$(Q)$(MAKE) distclean config ARCH=$(ARCH) --silent
$(Q)$(foreach SNAPSHOT_ARCH, $(ARCHS), $(MAKE) distclean config update-snapshot ARCH=$(SNAPSHOT_ARCH) LINK_MODE=static --silent;)
$(Q)$(MAKE) distclean config update-snapshot ARCH=arm LINK_MODE=dynamic --silent
$(VECHO) "Switching backend back to %s (%s mode)\n" arm static
$(Q)$(MAKE) distclean config ARCH=arm --silent

update-snapshot: $(OUT)/$(STAGE0) tests/update-snapshots.sh
$(VECHO) "Updating snapshot for %s\n" $(ARCH)
tests/update-snapshots.sh $(ARCH)
$(VECHO) "Updating snapshot for %s (%s mode)\n" $(ARCH) $(LINK_MODE)
tests/update-snapshots.sh $(ARCH) $(LINK_MODE)
$(VECHO) " OK\n"

$(OUT)/%.o: %.c
Expand All @@ -122,9 +139,9 @@ $(OUT)/norm-lf: tools/norm-lf.c
$(VECHO) " CC+LD\t$@\n"
$(Q)$(CC) $(CFLAGS) -o $@ $^

$(OUT)/libc.inc: $(OUT)/inliner $(OUT)/norm-lf $(LIBDIR)/c.c
$(OUT)/libc.inc: $(OUT)/inliner $(OUT)/norm-lf $(LIBDIR)/$(BUILTIN_LIBC)
$(VECHO) " GEN\t$@\n"
$(Q)$(OUT)/norm-lf $(LIBDIR)/c.c $(OUT)/c.normalized.c
$(Q)$(OUT)/norm-lf $(LIBDIR)/$(BUILTIN_LIBC) $(OUT)/c.normalized.c
$(Q)$(OUT)/inliner $(OUT)/c.normalized.c $@
$(Q)$(RM) $(OUT)/c.normalized.c

Expand All @@ -143,12 +160,12 @@ $(OUT)/$(STAGE0)-sanitizer: $(OUT)/libc.inc $(OBJS)
$(OUT)/$(STAGE1): $(OUT)/$(STAGE0)
$(Q)$(STAGE1_CHECK_CMD)
$(VECHO) " SHECC\t$@\n"
$(Q)$(OUT)/$(STAGE0) --dump-ir -o $@ $(SRCDIR)/main.c > $(OUT)/shecc-stage1.log
$(Q)$(OUT)/$(STAGE0) $(STAGE0_FLAGS) -o $@ $(SRCDIR)/main.c > $(OUT)/shecc-stage1.log
$(Q)chmod a+x $@

$(OUT)/$(STAGE2): $(OUT)/$(STAGE1)
$(VECHO) " SHECC\t$@\n"
$(Q)$(TARGET_EXEC) $(OUT)/$(STAGE1) -o $@ $(SRCDIR)/main.c
$(Q)$(TARGET_EXEC) $(OUT)/$(STAGE1) $(STAGE1_FLAGS) -o $@ $(SRCDIR)/main.c

bootstrap: $(OUT)/$(STAGE2)
$(Q)chmod 775 $(OUT)/$(STAGE2)
Expand Down
42 changes: 39 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,19 @@ To execute the snapshot test, install the packages below:
$ sudo apt-get install graphviz jq
```

Additionally, because `shecc` supports the dynamic linking mode for the Arm architecture,
it needs to install the ARM GNU toolchain to obtain the ELF interpreter and other dependencies:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

```shell
$ sudo apt-get install gcc-arm-linux-gnueabihf
```
Another approach is to manually download and install the toolchain from [ARM Developer website](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads).

Select "x86_64 Linux hosted cross toolchains" - "AArch32 GNU/Linux target with hard float (arm-none-linux-gnueabihf)" to download the toolchain.

## Build and Verify

Configure which backend you want, `shecc` supports ARMv7-A and RV32IM backend:
```
```shell
$ make config ARCH=arm
# Target machine code switch to Arm

Expand All @@ -86,13 +95,29 @@ $ make config ARCH=riscv
```

Run `make` and you should see this:
```shell
$ make
CC+LD out/inliner
GEN out/libc.inc
CC out/src/main.o
LD out/shecc
SHECC out/shecc-stage1.elf
SHECC out/shecc-stage2.elf
```

Run `make LINK_MODE=dynamic` to use the dynamic linking mode and generate the dynamically linked compiler:
```shell
# If using the dynamic linking mode, you should add 'LINK_MODE=dynamic' for each 'make' command.
$ make LINK_MODE=dynamic
CC+LD out/inliner
GEN out/libc.inc
CC out/src/main.o
LD out/shecc
SHECC out/shecc-stage1.elf
SHECC out/shecc-stage2.elf

$ file out/shecc-stage2.elf
out/shecc-stage2.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, not stripped
```

For development builds with memory safety checks:
Expand All @@ -103,22 +128,32 @@ $ make check-sanitizer

File `out/shecc` is the first stage compiler. Its usage:
```shell
$ shecc [-o output] [+m] [--no-libc] [--dump-ir] <infile.c>
$ shecc [-o output] [+m] [--no-libc] [--dump-ir] [--dynlink] <infile.c>
```

Compiler options:
- `-o` : Specify output file name (default: `out.elf`)
- `+m` : Use hardware multiplication/division instructions (default: disabled)
- `--no-libc` : Exclude embedded C library (default: embedded)
- `--dump-ir` : Dump intermediate representation (IR)
- `--dynlink` : Use dynamic linking (default: disabled)

Example:
Example 1: static linking mode
```shell
$ out/shecc -o fib tests/fib.c
$ chmod +x fib
$ qemu-arm fib
```

Example 2: dynamic linking mode

Notice that `/usr/arm-linux-gnueabihf` is the ELF interpreter prefix. Since the path may be different if you manually install the ARM GNU toolchain instead of using `apt-get`, you should set the prefix to the actual path.
```shell
$ out/shecc --dynlink -o fib tests/fib.c
$ chmod +x fib
$ qemu-arm -L /usr/arm-linux-gnueabihf fib
```

### IR Regression Tests

To ensure the consistency of frontend (lexer, parser) behavior when working on it, the snapshot test is introduced.
Expand All @@ -142,6 +177,7 @@ use `update-snapshot` / `check-snapshot` instead.

`shecc` comes with a comprehensive test suite (200+ test cases). To run the tests:
```shell
# Add 'LINK_MODE=dynamic' if using the dynamic linking mode.
$ make check # Run all tests (stage 0 and stage 2)
$ make check-stage0 # Test stage 0 compiler only
$ make check-stage2 # Test stage 2 compiler only
Expand Down
50 changes: 50 additions & 0 deletions lib/c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* shecc - Self-Hosting and Educational C Compiler.
*
* shecc is freely redistributable under the BSD 2 clause license. See the
* file "LICENSE" for information on usage and redistribution of this file.
*/

#pragma once
/* Declarations of C standard library functions */

#define NULL 0

#define bool _Bool
#define true 1
#define false 0

/* va_list support for variadic functions */
typedef int *va_list;

/* File I/O */
typedef int FILE;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defines FILE as int, which is ABI-incompatible with libc's opaque FILE type and will break dynamic linking with real stdio functions.

(Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)

Prompt for AI agents
Address the following comment on lib/c.h at line 18:

<comment>Defines FILE as int, which is ABI-incompatible with libc&#39;s opaque FILE type and will break dynamic linking with real stdio functions.

(Based on your team&#39;s feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)</comment>

<file context>
@@ -0,0 +1,47 @@
+#define false 0
+
+/* File I/O */
+typedef int FILE;
+FILE *fopen(char *filename, char *mode);
+int fclose(FILE *stream);
</file context>

FILE *fopen(char *filename, char *mode);
int fclose(FILE *stream);
int fgetc(FILE *stream);
char *fgets(char *str, int n, FILE *stream);
int fputc(int c, FILE *stream);

/* string-related functions */
int strlen(char *str);
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strlen should return size_t and accept const char *; current signature risks overflow and misses const-correctness.

Prompt for AI agents
Address the following comment on lib/c.h at line 29:

<comment>strlen should return size_t and accept const char *; current signature risks overflow and misses const-correctness.</comment>

<file context>
@@ -0,0 +1,50 @@
+int fputc(int c, FILE *stream);
+
+/* string-related functions */
+int strlen(char *str);
+int strcmp(char *s1, char *s2);
+int strncmp(char *s1, char *s2, int len);
</file context>
Fix with Cubic

Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strlen signature is incorrect (missing const and wrong return type); this creates an incompatible prototype with libc and risks UB during dynamic linking.

Prompt for AI agents
Address the following comment on lib/c.h at line 29:

<comment>strlen signature is incorrect (missing const and wrong return type); this creates an incompatible prototype with libc and risks UB during dynamic linking.</comment>

<file context>
@@ -0,0 +1,50 @@
+int fputc(int c, FILE *stream);
+
+/* string-related functions */
+int strlen(char *str);
+int strcmp(char *s1, char *s2);
+int strncmp(char *s1, char *s2, int len);
</file context>
Fix with Cubic

int strcmp(char *s1, char *s2);
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add const to strcmp parameters for correctness and compatibility with libc.

Prompt for AI agents
Address the following comment on lib/c.h at line 27:

<comment>Add const to strcmp parameters for correctness and compatibility with libc.</comment>

<file context>
@@ -0,0 +1,47 @@
+
+/* string-related functions */
+int strlen(char *str);
+int strcmp(char *s1, char *s2);
+int strncmp(char *s1, char *s2, int len);
+char *strcpy(char *dest, char *src);
</file context>
Suggested change
int strcmp(char *s1, char *s2);
int strcmp(const char *s1, const char *s2);
Fix with Cubic

int strncmp(char *s1, char *s2, int len);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonstandard strncmp signature (missing const, len should be size_t) is incompatible with libc and may mis-handle large sizes.

(Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)

Prompt for AI agents
Address the following comment on lib/c.h at line 28:

<comment>Nonstandard strncmp signature (missing const, len should be size_t) is incompatible with libc and may mis-handle large sizes.

(Based on your team&#39;s feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)</comment>

<file context>
@@ -0,0 +1,47 @@
+/* string-related functions */
+int strlen(char *str);
+int strcmp(char *s1, char *s2);
+int strncmp(char *s1, char *s2, int len);
+char *strcpy(char *dest, char *src);
+char *strncpy(char *dest, char *src, int len);
</file context>

char *strcpy(char *dest, char *src);
char *strncpy(char *dest, char *src, int len);
char *memcpy(char *dest, char *src, int count);
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nonstandard memcpy signature (return type and parameter types incorrect) is incompatible with libc and risks ABI mismatch.

(Based on your team's feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)

Prompt for AI agents
Address the following comment on lib/c.h at line 31:

<comment>Nonstandard memcpy signature (return type and parameter types incorrect) is incompatible with libc and risks ABI mismatch.

(Based on your team&#39;s feedback about fixing potential issues and refining c.c/c.h for dynamic linking.)</comment>

<file context>
@@ -0,0 +1,47 @@
+int strncmp(char *s1, char *s2, int len);
+char *strcpy(char *dest, char *src);
+char *strncpy(char *dest, char *src, int len);
+char *memcpy(char *dest, char *src, int count);
+int memcmp(void *s1, void *s2, int n);
+void *memset(void *s, int c, int n);
</file context>

✅ Addressed in 3a6cd23

Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memcpy should use void* for pointers, const on src, and size_t for count to match libc and avoid size truncation.

Prompt for AI agents
Address the following comment on lib/c.h at line 31:

<comment>memcpy should use void* for pointers, const on src, and size_t for count to match libc and avoid size truncation.</comment>

<file context>
@@ -0,0 +1,47 @@
+int strncmp(char *s1, char *s2, int len);
+char *strcpy(char *dest, char *src);
+char *strncpy(char *dest, char *src, int len);
+char *memcpy(char *dest, char *src, int count);
+int memcmp(void *s1, void *s2, int n);
+void *memset(void *s, int c, int n);
</file context>
Fix with Cubic

int memcmp(void *s1, void *s2, int n);
void *memset(void *s, int c, int n);

/* formatted output string */
int printf(char *str, ...);
int sprintf(char *buffer, char *str, ...);
int snprintf(char *buffer, int n, char *str, ...);

/* Terminating program */
void exit(int exit_code);
void abort(void);

/* Dynamic memory allocation/deallocation functions */
void *malloc(int size);
void *calloc(int n, int size);
void free(void *ptr);
50 changes: 49 additions & 1 deletion mk/arm.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,53 @@ ARCH_DEFS = \
\#pragma once\n$\
\#define ARCH_PREDEFINED \"__arm__\" /* defined by GNU C and RealView */\n$\
\#define ELF_MACHINE 0x28 /* up to ARMv7/Aarch32 */\n$\
\#define ELF_FLAGS 0x5000200\n$\
\#define ELF_FLAGS 0x5000400\n$\
\#define DYN_LINKER \"/lib/ld-linux-armhf.so.3\"\n$\
\#define LIBC_SO \"libc.so.6\"\n$\
\#define PLT_FIXUP_SIZE 20\n$\
\#define PLT_ENT_SIZE 12\n$\
\#define R_ARCH_JUMP_SLOT 0x16\n$\
"

# Find the sysroot of the ARM GNU toolchain if using dynamic linking.
#
# Since developers may install the toolchain manually instead of
# using a package manager such as apt, we cannot assume that the
# path of ld-linux is always "/usr/arm-linux-gnueabihf".
#
# Therefore, the following process first locates find the correct
# sysroot of the toolchain, and then generate the ELF interpreter
# prefix for later use.
ifneq ($(HOST_ARCH),$(ARCH_NAME))
ifeq ($(LINK_MODE),dynamic)
CROSS_COMPILE = arm-none-linux-gnueabihf-
ARM_CC = $(CROSS_COMPILE)gcc
ARM_CC := $(shell which $(ARM_CC))
ifndef ARM_CC
CROSS_COMPILE = arm-linux-gnueabihf-
ARM_CC = $(CROSS_COMPILE)gcc
ARM_CC := $(shell which $(ARM_CC))
ifndef ARM_CC
$(error "Unable to find ARM GNU toolchain.")
endif
endif

LD_LINUX_PATH := $(shell cd $(shell $(ARM_CC) --print-sysroot) 2>/dev/null && pwd)
ifeq ("$(LD_LINUX_PATH)","/")
LD_LINUX_PATH := $(shell dirname "$(shell which $(ARM_CC))")/..
LD_LINUX_PATH := $(shell cd $(LD_LINUX_PATH) 2>/dev/null && pwd)
LD_LINUX_PATH := $(LD_LINUX_PATH)/$(shell echo $(CROSS_COMPILE) | sed s'/.$$//')/libc
LD_LINUX_PATH := $(shell cd $(LD_LINUX_PATH) 2>/dev/null && pwd)
ifndef LD_LINUX_PATH
LD_LINUX_PATH = /usr/$(shell echo $(CROSS_COMPILE) | sed s'/.$$//')
LD_LINUX_PATH := $(shell cd $(LD_LINUX_PATH) 2>/dev/null && pwd)
endif
endif

ifndef LD_LINUX_PATH
$(error "Dynamic linking mode requires ld-linux.so")
endif

RUNNER_LD_PREFIX = -L $(LD_LINUX_PATH)
endif
endif
3 changes: 3 additions & 0 deletions mk/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ ifneq ($(HOST_ARCH),$(ARCH_NAME))

# Generate the path to the architecture-specific qemu
TARGET_EXEC = $(shell which $(ARCH_RUNNER))
ifeq ($(LINK_MODE),dynamic)
TARGET_EXEC += $(RUNNER_LD_PREFIX)
endif
endif
export TARGET_EXEC

Expand Down
Loading