Skip to content

Commit 2cbe2cb

Browse files
authored
Add dev container, fix bugs in compiler setup (#20)
Features added: * Add clang include directory to cfg * Adding statiging release * Add dev container * Add runtime library interface * Adding first version of unistd.c * Adding print for exit code at debug exit Bug Fixes: * Fix bugs in compiler cfg template * Fix namecmp to recognize substrings as non equal * Fix abi thread local issue, add test program build to top level cmake project * Fix makro in cmake template * Fix debug to handle unlimited number of input items or input-/outputsets
1 parent 74d3d75 commit 2cbe2cb

26 files changed

+641
-207
lines changed

.github/workflows/build_check.yml renamed to .github/workflows/release_experimental.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
name: make sure it still builds before merging into main
1+
name: release latest with all library versions
22

33
on:
44
pull_request:
5-
branches: [ "main" ]
5+
branches: [ "dev/staging" ]
66

77
jobs:
88
build:
@@ -57,4 +57,15 @@ jobs:
5757
run: cmake --build ${{ steps.build.outputs.dir }}
5858

5959
- name: Install
60-
run: cmake --install ${{ steps.build.outputs.dir }}
60+
run: cmake --install ${{ steps.build.outputs.dir }}
61+
62+
- name: Compress
63+
shell: bash
64+
working-directory: ${{ steps.build.outputs.dir }}
65+
run: tar -czf "dandelion_sdk_${{matrix.build}}_${{matrix.platform}}_${{matrix.cpu}}.tar.gz" dandelion_sdk
66+
67+
- name: Add to release
68+
shell: bash
69+
run: gh release upload experimental "${{ steps.build.outputs.dir }}/dandelion_sdk_${{matrix.build}}_${{matrix.platform}}_${{matrix.cpu}}.tar.gz" --clobber
70+
env:
71+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CMakeLists.txt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ option(NEWLIB "toggles builing of newlib on top of dandelion interface" OFF)
1515
# string options
1616
set(ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR} CACHE STRING "the architecture to build for")
1717
set(DANDELION_PLATFORM "debug" CACHE STRING "backend to build for")
18+
set(PAGE_SIZE "4096" CACHE STRING "Page size for the runtime to assume.")
1819
message(STATUS "Building for ${DANDELION_PLATFORM} on ${ARCHITECTURE}")
1920

2021
# Constants
@@ -119,6 +120,33 @@ if(NEWLIB)
119120
<INSTALL_DIR>/${ARCHITECTURE}-dandelion/lib
120121
${CMAKE_INSTALL_PREFIX}/lib
121122
)
123+
# Create folder at configuration time to avoid issues with includes
124+
file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include)
125+
file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/sys)
126+
127+
add_library(dlibc INTERFACE IMPORTED)
128+
target_compile_options(dlibc INTERFACE
129+
-D_GNU_SOURCE=1
130+
-D__GNU__
131+
-D__rtems__
132+
)
133+
target_include_directories(dlibc INTERFACE
134+
${CMAKE_INSTALL_PREFIX}/include
135+
${CMAKE_INSTALL_PREFIX}/include/sys
136+
)
137+
target_link_directories(dlibc INTERFACE ${CMAKE_INSTALL_PREFIX}/lib)
138+
target_link_libraries(dlibc INTERFACE
139+
${CMAKE_INSTALL_PREFIX}/lib/libc.a
140+
${CMAKE_INSTALL_PREFIX}/lib/libg.a
141+
${CMAKE_INSTALL_PREFIX}/lib/libm.a
142+
)
143+
target_link_options(dlibc INTERFACE
144+
-T${CMAKE_CURRENT_SOURCE_DIR}/sdk_install/linker.ld
145+
-fuse-ld=lld
146+
-static
147+
-nostdlib
148+
)
149+
add_dependencies(dlibc newlib)
122150

123151
set(LLVM_C_FLAGS "-D_GNU_SOURCE=1")
124152
string(APPEND LLVM_C_FLAGS " -D_POSIX_TIMERS")
@@ -191,13 +219,37 @@ if(NEWLIB)
191219
-DLIBCXXABI_BAREMETAL=ON
192220
-DLIBCXXABI_ENABLE_SHARED=OFF
193221
-DLIBCXXABI_USE_LLVM_UNWINDER=ON
222+
-DLIBCXXABI_ENABLE_THREADS=OFF
194223
-DLIBCXX_ENABLE_SHARED=OFF
195224
-DLIBCXX_ENABLE_STATIC=ON
196225
-DLIBCXX_INCLUDE_BENCHMARKS=OFF
197226
-DLIBCXX_CXX_ABI=libcxxabi
198227
-DLIBCXX_ENABLE_FILESYSTEM=ON
199228
-DLIBCXX_ENABLE_RANDOM_DEVICE=OFF
229+
-DLIBCXX_HAS_PTHREAD_API=ON
200230
)
201231
add_dependencies(llvmproject newlib)
202232

233+
# Create folder at configuration time to avoid issues with includes
234+
file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/c++/v1)
235+
236+
add_library(dlibcxx INTERFACE IMPORTED)
237+
target_include_directories(dlibcxx INTERFACE
238+
"${CMAKE_INSTALL_PREFIX}/include/c++/v1"
239+
)
240+
target_link_libraries(dlibcxx INTERFACE
241+
"${CMAKE_INSTALL_PREFIX}/lib/libc++.a"
242+
"${CMAKE_INSTALL_PREFIX}/lib/libc++abi.a"
243+
"${CMAKE_INSTALL_PREFIX}/lib/libunwind.a"
244+
)
245+
add_dependencies(dlibcxx llvmproject)
246+
247+
add_library(runtime INTERFACE IMPORTED)
248+
target_link_libraries(runtime INTERFACE
249+
"${CMAKE_INSTALL_PREFIX}/lib/generic/libclang_rt.builtins-${ARCHITECTURE}.a"
250+
)
251+
add_dependencies(runtime llvmproject)
252+
253+
add_subdirectory(test_programs)
254+
203255
endif()

Dockerfile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# syntax=docker/dockerfile:1
2+
FROM ubuntu:24.04
3+
4+
# arguments
5+
ARG BUILD="Release"
6+
ARG PLATFORM="debug"
7+
ARG TARGET_ARCH="x86_64"
8+
ARG VERSION="experimental"
9+
10+
# install packages required packages to get things running
11+
RUN apt update
12+
RUN apt-get install -y wget gpg
13+
RUN apt-get install -y lsb-release
14+
RUN apt-get install -y software-properties-common
15+
RUN apt-get install -y gcc g++ # clang uses gcc to interface with the linker
16+
17+
# download initial clang
18+
RUN wget https://apt.llvm.org/llvm.sh -O ~/llvm.sh
19+
RUN chmod +x ~/llvm.sh
20+
RUN ~/llvm.sh
21+
RUN ln -s /usr/bin/ld.lld-19 /usr/bin/ld.lld
22+
RUN rm -r /usr/include/*
23+
24+
# download and set up dandelionSDK
25+
RUN wget https://github.com/eth-easl/dandelionSDK/releases/download/${VERSION}/dandelion_sdk_${BUILD}_${PLATFORM}_${TARGET_ARCH}.tar.gz -O ~/dandelionSDK.tar.gz
26+
RUN tar -xzf ~/dandelionSDK.tar.gz -C ~/
27+
RUN ~/dandelion_sdk/create-compiler.sh -d -c clang-19
28+
29+
ENV CC="clang"
30+
ENV CXX="clang++"
31+
32+
# additional useful tooling
33+
RUN apt-get install -y cmake
34+
RUN apt-get install -y git

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ dumping outputs to the terminal when terminating.
3030
Fixing it is on our agenda, but not of highest priority.
3131
If you want to use Dandelion and need C++ support for aarch64, please get in touch and we may be able to provide experimental builds or bump the priority to get it fixed.
3232

33+
### Other parameters
34+
35+
Additionally, the following parameters can be used to influence system behaviour.
36+
37+
- `PAGE_SIZE` sets the page size the runtime will assume to optimize allocation etc. and makes available to others to depend on. Should be a multiple of sizeof(size_t) for the platform compiled for.
38+
3339
## Interface expectations
3440
### libc
3541
When using libc or any system on top of it values can be fed into stdin, argv and environ by specifying a input set called "stdio".
@@ -97,6 +103,28 @@ For newlib to be built correctly the autoconf version 2.69.
97103
This also enables the build of the in memory file system,
98104
which can also be built without the other newlib builds by setting `-DDANDELION_FS=ON`
99105

106+
## Build Container
107+
We also provide a docker file to construct a build container with the correct tools set up in them.
108+
To create the container with docker use the following command:
109+
```
110+
docker build -t dandelion_dev_docker . [--no-cache]
111+
```
112+
Use the `--no-cache` if you want to rebuild the container from scratch.
113+
114+
To use the container use the following command:
115+
```
116+
docker run --rm -it --mount type=bind,src=<path to your source folder>,dst=/workspace --workdir=/workspace dandelion_dev_docker:latest bash
117+
```
118+
You will enter the container and your source folder will be mounted at `/workspace`.
119+
The default clang and clang++ are set up to compile for dandelion debug on the machine you are running.
120+
If you want a different target, you can set build, platform and architecture in the docker file.
121+
Files you build in the container will be visible outside, as long as they are in the workspace directory.
122+
123+
To add more tools to the build environment, they can be added to the docker file, or you can base your container build on our docker file by importing it with:
124+
```
125+
FROM dandelion_dev_docker:latest
126+
```
127+
100128
## Freestanding
101129
The GCC/Clang standard expects 4 functions to allways be provided in any environment (even freestanding), which allow the compiler to always just insert them.
102130
(https://gcc.gnu.org/onlinedocs/gcc/Standards.html)

file_system/file_system.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ D_File *create_file(Path *name, char *content, size_t length, uint32_t mode) {
1616
if (new_file == NULL) {
1717
return NULL;
1818
}
19-
if (name->length > FS_NAME_LENGHT) {
19+
if (name->length > FS_NAME_LENGTH) {
2020
return NULL;
2121
}
2222
memcpy(new_file->name, name->path, name->length);
@@ -43,7 +43,7 @@ D_File *create_file(Path *name, char *content, size_t length, uint32_t mode) {
4343

4444
D_File *create_directory(Path *name, uint32_t mode) {
4545
D_File *new_file = dandelion_alloc(sizeof(D_File), _Alignof(D_File));
46-
if (name->length > FS_NAME_LENGHT) {
46+
if (name->length > FS_NAME_LENGTH) {
4747
return NULL;
4848
}
4949
memcpy(new_file->name, name->path, name->length);
@@ -69,12 +69,12 @@ int link_file_to_folder(D_File *folder, D_File *file) {
6969
file->next = NULL;
7070
} else {
7171
D_File *current = folder->child;
72-
if (namecmp(file->name, current->name, FS_NAME_LENGHT) < 0) {
72+
if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < 0) {
7373
file->next = current;
7474
folder->child = file;
7575
} else {
7676
while (current->next != NULL) {
77-
if (namecmp(file->name, current->next->name, FS_NAME_LENGHT) < 0) {
77+
if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, FS_NAME_LENGTH) < 0) {
7878
break;
7979
} else {
8080
current = current->next;
@@ -98,7 +98,7 @@ D_File *find_file_in_dir(D_File *directory, Path file) {
9898
for (D_File *current = directory->child; current != NULL;
9999
current = current->next) {
100100
int cmp_result =
101-
namecmp(current->name, file.path, MIN(file.length, FS_NAME_LENGHT));
101+
namecmp(current->name, FS_NAME_LENGTH, file.path, file.length);
102102
if (cmp_result == 0) {
103103
return current;
104104
} else if (cmp_result > 0) {
@@ -138,7 +138,7 @@ D_File *create_directories(D_File *directory, Path path, char prevent_up) {
138138
}
139139
for (Path current_path = get_component_advance(&path);
140140
current_path.length > 0; current_path = get_component_advance(&path)) {
141-
if (current_path.length > FS_NAME_LENGHT) {
141+
if (current_path.length > FS_NAME_LENGTH) {
142142
return NULL;
143143
} else if (current_path.length == 1 && current_path.path[0] == '.') {
144144
// handle special case of single dot for current directory
@@ -483,7 +483,7 @@ int fs_initialize(int *argc, char ***argv, char ***environ) {
483483
return -1;
484484
}
485485
int is_stdio_folder =
486-
namecmp(set_path.path, "stdio", MIN(set_path.length, 5));
486+
namecmp(set_path.path, set_path.length, "stdio", 5);
487487
size_t input_items = dandelion_input_buffer_count(set_index);
488488
for (size_t item_index = 0; item_index < input_items; item_index++) {
489489
IoBuffer *item_buffer = dandelion_get_input(set_index, item_index);
@@ -510,19 +510,19 @@ int fs_initialize(int *argc, char ***argv, char ***environ) {
510510
}
511511
if (is_stdio_folder == 0) {
512512
int is_stdin =
513-
namecmp(file_path.path, "stdin", MIN(file_path.length, 5));
513+
namecmp(file_path.path, file_path.length, "stdin", 5);
514514
if (is_stdin == 0) {
515515
error = open_existing_file(STDIN_FILENO, item_file, O_RDONLY, 0, 0);
516516
if (error != 0)
517517
return error;
518518
}
519-
int is_argv = namecmp(file_path.path, "argv", MIN(file_path.length, 4));
519+
int is_argv = namecmp(file_path.path, file_path.length, "argv", 4);
520520
if (is_argv == 0) {
521521
setup_charpparray(item_buffer->data, item_buffer->data_len, argc,
522522
argv);
523523
}
524524
int is_environ =
525-
namecmp(file_path.path, "environ", MIN(file_path.length, 7));
525+
namecmp(file_path.path, file_path.length, "environ", 7);
526526
if (is_environ == 0) {
527527
int envc;
528528
setup_charpparray(item_buffer->data, item_buffer->data_len, &envc,
@@ -588,7 +588,7 @@ int add_output_from_file(D_File *file, Path previous_path, size_t set_index) {
588588
switch (file->type) {
589589
case FILE:
590590
// check name length an create string with complete file name
591-
name_length = namelen(file->name, FS_NAME_LENGHT);
591+
name_length = namelen(file->name, FS_NAME_LENGTH);
592592
new_buffer = dandelion_alloc(previous_path.length + name_length, 1);
593593
if (new_buffer == NULL) {
594594
return -1;
@@ -631,7 +631,7 @@ int add_output_from_file(D_File *file, Path previous_path, size_t set_index) {
631631
return 0;
632632
case DIRECTORY:
633633
// check name length and create a new string / path to recurse further
634-
name_length = namelen(file->name, FS_NAME_LENGHT);
634+
name_length = namelen(file->name, FS_NAME_LENGTH);
635635
new_buffer = dandelion_alloc(previous_path.length + name_length + 1, 1);
636636
if (new_buffer == NULL) {
637637
dandelion_exit(ENOMEM);
@@ -677,10 +677,10 @@ int fs_terminate() {
677677
for (D_File *out_file = set_directory->child; out_file != NULL;
678678
out_file = out_file->next) {
679679
// ignore argv, environ and stdin in the stdio folder
680-
if (namecmp(set_ident.path, "stdio", MIN(set_ident.length, 5)) == 0) {
681-
if (namecmp(out_file->name, "environ", 7) == 0 ||
682-
namecmp(out_file->name, "argv", 4) == 0 ||
683-
namecmp(out_file->name, "stdin", 5) == 0)
680+
if (namecmp(set_ident.path, set_ident.length, "stdio", 5) == 0) {
681+
if (namecmp(out_file->name, FS_NAME_LENGTH, "environ", 7) == 0 ||
682+
namecmp(out_file->name, FS_NAME_LENGTH, "argv", 4) == 0 ||
683+
namecmp(out_file->name, FS_NAME_LENGTH, "stdin", 5) == 0)
684684
continue;
685685
}
686686
add_output_from_file(out_file, empty_path, set_index);

file_system/file_system.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <stdint.h>
77

88
#ifndef FS_NAME_LENGTH
9-
#define FS_NAME_LENGHT 64
9+
#define FS_NAME_LENGTH 64
1010
#endif
1111

1212
#ifndef FS_CHUNK_SIZE
@@ -40,7 +40,7 @@ typedef struct FileChunk {
4040

4141
// Use D_File instead of File, to avoid potential naming overlap
4242
typedef struct D_File {
43-
char name[FS_NAME_LENGHT];
43+
char name[FS_NAME_LENGTH];
4444
struct D_File *next;
4545
struct D_File *parent;
4646
FileType type;

file_system/fs_implementation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int dandelion_open(const char *name, int flags, uint32_t mode) {
125125
Path total_path = path_from_string(name);
126126
Path dir_path = get_directories(total_path);
127127
Path file_name = get_file(total_path);
128-
if (file_name.length >= FS_NAME_LENGHT) {
128+
if (file_name.length >= FS_NAME_LENGTH) {
129129
return -EINVAL;
130130
}
131131
D_File *parent = create_directories(fs_root, dir_path, 0);
@@ -643,7 +643,7 @@ int dandelion_readdir(DIR *directory, struct dirent *dirent) {
643643
return -1;
644644
}
645645
directory->child++;
646-
size_t max_name_length = MIN(256, FS_NAME_LENGHT);
646+
size_t max_name_length = MIN(256, FS_NAME_LENGTH);
647647
memcpy(dirent->d_name, current_child->name, max_name_length - 1);
648648
dirent->d_name[max_name_length] = 0;
649649
dirent->d_ino = 0;

file_system/paths.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,24 @@ static inline size_t namelen(const char *const name, size_t max_len) {
2323
return length;
2424
}
2525

26-
static inline int namecmp(const char *const name1, const char *const name2,
27-
size_t max_length) {
26+
static inline int namecmp(const char *const name1, size_t name1_length, const char *const name2,
27+
size_t name2_length) {
28+
size_t max_length = name1_length < name2_length ? name1_length : name2_length;
2829
for (size_t index = 0; index < max_length; index++) {
30+
// this also automatically returns -1 if one of them is null terminated earlier than their length
2931
if (name1[index] != name2[index])
3032
return name1[index] < name2[index] ? -1 : 1;
3133
// are the same if we got here
3234
if (name1[index] == '\0')
3335
return 0;
3436
}
35-
return 0;
37+
// they are the same until the end of the shorter one or there has not been null termination
38+
if(name1_length < name2_length)
39+
return -1;
40+
else if(name2_length < name1_length)
41+
return 1;
42+
else
43+
return 0;
3644
}
3745

3846
Path path_from_string(const char *const str);

newlib_shim/Makefile.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ libc_a_SOURCES += \
22
%D%/dirent.c \
33
%D%/pthread.c \
44
%D%/shim.c \
5-
%D%/time.c
5+
%D%/time.c \
6+
%D%/unistd.c

newlib_shim/patch_script

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ cp $THIS_DIR/shim.c $1/newlib/libc/sys/dandelion/shim.c
2222
cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c
2323
cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c
2424
cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c
25+
cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c
2526
cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h
2627
if ! test -d $1/newlib/libc/sys/dandelion/sys
2728
then

0 commit comments

Comments
 (0)