diff --git a/.cirrus.yml b/.cirrus.yml index c306ac97..1ccd6173 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,11 +7,12 @@ freebsd_task: env: matrix: - OCAML_VERSION: 5.3.0 + - OCAML_VERSION: 5.4.0 pkg_install_script: pkg install -y ocaml-opam gmp gmake pkgconf bash setup_script: - opam init -a --comp=$OCAML_VERSION - opam update - - opam install dune + - opam install dune fmt - opam pin add -n -t . - opam depext -yt ocaml-solo5 - opam install -t ocaml-solo5 --deps-only diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af6f6606..bf893dd7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,9 @@ jobs: test: strategy: matrix: - ocaml-compiler: [5.3.0] + ocaml-compiler: + - 5.3.0 + - 5.4.0 name: OCaml ${{ matrix.ocaml-compiler }} runs-on: ubuntu-latest steps: @@ -16,7 +18,7 @@ jobs: *.opam !ocaml-solo5-cross-aarch64.opam - name: Install ocaml-solo5 and dune - run: opam install ocaml-solo5 conf-libseccomp dune + run: opam install ocaml-solo5 conf-libseccomp dune fmt - name: Show the toolchain configuration run: | set -x @@ -25,6 +27,13 @@ jobs: opam exec -- ocamlfind -toolchain solo5 list - name: Compile examples with hvt run: MODE=hvt opam exec -- dune build --root example + - name: Run the hello example with hvt + run: | + set -x + MODE=hvt opam exec -- dune describe location --root example \ + --context solo5 --no-print-directory ./hello.exe |& tee hello.path + sudo setfacl -m u:${USER}:rw /dev/kvm + opam exec -- solo5-hvt -- "example/$(cat hello.path)" - name: Compile examples with spt run: MODE=spt opam exec -- dune build --root example - name: Run examples with spt diff --git a/example/dune.inc b/example/dune.inc index b885dfbd..5cfc9a76 100644 --- a/example/dune.inc +++ b/example/dune.inc @@ -10,7 +10,7 @@ ; Force linking the manifest in -cclib "-u __solo5_mft1_note") - (libraries solo5os) + (libraries solo5os fmt) (modes native)) (rule diff --git a/example/dune_gen.ml b/example/dune_gen.ml index 508ad818..b5581cf2 100644 --- a/example/dune_gen.ml +++ b/example/dune_gen.ml @@ -52,7 +52,7 @@ let print_rule test exitcode extraifs extralibs = exitcode let _ = - print_rule "hello" None [] []; + print_rule "hello" None [] ["fmt"]; print_rule "sysfail" (Some 2) [] []; print_rule "config" None [] []; print_rule "compilerlibsx86" None diff --git a/example/hello.ml b/example/hello.ml index ef16b82d..92c8f033 100644 --- a/example/hello.ml +++ b/example/hello.ml @@ -1 +1 @@ -let () = Printf.printf "Hello from OCaml on Solo5!\n%!";; +let () = Fmt.pr "Hello from OCaml on Solo5!\n%!";; diff --git a/nolibc/include/pthread.h b/nolibc/include/pthread.h index ea7b5651..dce1f329 100644 --- a/nolibc/include/pthread.h +++ b/nolibc/include/pthread.h @@ -54,4 +54,7 @@ int pthread_cond_broadcast(pthread_cond_t *); int pthread_cond_signal(pthread_cond_t *); int pthread_cond_destroy(pthread_cond_t *); +int pthread_cancel(pthread_t thread); +void pthread_exit(void *retval); + #endif diff --git a/nolibc/include/sys/time.h b/nolibc/include/sys/time.h index f39c30fa..0f71b30c 100644 --- a/nolibc/include/sys/time.h +++ b/nolibc/include/sys/time.h @@ -12,5 +12,9 @@ struct timezone { int tz_dsttime; }; int gettimeofday(struct timeval *tv, struct timezone *tz); +struct timespec { + time_t tv_sec; + long tv_nsec; +}; #endif diff --git a/nolibc/stubs.c b/nolibc/stubs.c index 54942217..774110bb 100644 --- a/nolibc/stubs.c +++ b/nolibc/stubs.c @@ -147,6 +147,8 @@ STUB_ABORT(pthread_cond_signal); STUB_IGNORE(int, pthread_cond_broadcast, 0); STUB_ABORT(pthread_self); STUB_ABORT(pthread_detach); +STUB_IGNORE(int, pthread_cancel, 0); +STUB_ABORT(pthread_exit); STUB_IGNORE(int, sigfillset, 0); STUB_ABORT(sigwait); diff --git a/ocaml-solo5-cross-aarch64.opam b/ocaml-solo5-cross-aarch64.opam index bb8975c5..6cbc4656 100644 --- a/ocaml-solo5-cross-aarch64.opam +++ b/ocaml-solo5-cross-aarch64.opam @@ -31,7 +31,7 @@ depends: [ "opatch" {build} # to patch the compiler sources "ocamlfind" {build} "ocaml-src" {build} - "ocaml" {= "5.3.0"} + "ocaml" {= "5.3.0" | = "5.4.0"} "solo5" {>= "0.9.1"} "solo5-cross-aarch64" {>= "0.9.1" } ] diff --git a/ocaml-solo5.opam b/ocaml-solo5.opam index 684c2766..95a688bf 100644 --- a/ocaml-solo5.opam +++ b/ocaml-solo5.opam @@ -31,7 +31,7 @@ depends: [ "opatch" {build} # to patch the compiler sources "ocamlfind" {build} "ocaml-src" {build} - "ocaml" {= "5.3.0"} + "ocaml" {= "5.3.0" | = "5.4.0"} "solo5" {>= "0.9.1"} ] conflicts: [ diff --git a/patches/5.4.0/0001-Accept-native-freestanding-targets-at-configure-time.patch b/patches/5.4.0/0001-Accept-native-freestanding-targets-at-configure-time.patch new file mode 100644 index 00000000..47432f34 --- /dev/null +++ b/patches/5.4.0/0001-Accept-native-freestanding-targets-at-configure-time.patch @@ -0,0 +1,68 @@ +From fb64bf56cd52896765a53007aa723a4346ef12c4 Mon Sep 17 00:00:00 2001 +From: Samuel Hym +Date: Mon, 26 Feb 2024 19:35:26 +0100 +Subject: [PATCH 1/3] Accept native freestanding targets at configure time + +Accept `*-none` and `*-elf*` triplets for all the architectures with a +native backend to describe the corresponding freestanding target; `none` +and `elf*` are the most commonly-used last components in triplets for +freestanding targets +Set `system` to `none` in such cases +--- + configure | Bin 737974 -> 738624 bytes + configure.ac | 14 +++++++++++++- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index 8bb7306cb1..1f0c06d943 100755 +--- a/configure ++++ b/configure +@@ -18612,7 +18612,19 @@ fi ;; #( + riscv64-*-linux*) : + has_native_backend=yes; arch=riscv; model=riscv64; system=linux ;; #( + x86_64-*-gnu*) : +- has_native_backend=yes; arch=amd64; system=gnu ++ has_native_backend=yes; arch=amd64; system=gnu ;; #( ++ aarch64-*-none|arm64-*-none|aarch64-*-elf*|arm64-*-elf*) : ++ has_native_backend=yes; arch=arm64; system=none ;; #( ++ powerpc64le*-*-none|powerpc64le*-*-elf*) : ++ has_native_backend=yes; arch=power; model=ppc64le; system=none ;; #( ++ powerpc64*-*-none|powerpc64*-*-elf*) : ++ has_native_backend=yes; arch=power; model=ppc64; system=none ;; #( ++ riscv64-*-none|riscv64-*-elf*) : ++ has_native_backend=yes; arch=riscv; model=riscv64; system=none ;; #( ++ s390x*-*-none|s390x*-*-elf*) : ++ has_native_backend=yes; arch=s390x; model=z10; system=none ;; #( ++ x86_64-*-none|x86_64-*-elf*) : ++ has_native_backend=yes; arch=amd64; system=none + ;; #( + *) : + ;; +diff --git a/configure.ac b/configure.ac +index 0535f404b0..8e5e1e9300 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1609,7 +1609,19 @@ AS_CASE([$target], + [riscv64-*-linux*], + [has_native_backend=yes; arch=riscv; model=riscv64; system=linux], + [x86_64-*-gnu*], +- [has_native_backend=yes; arch=amd64; system=gnu] ++ [has_native_backend=yes; arch=amd64; system=gnu], ++ [aarch64-*-none|arm64-*-none|aarch64-*-elf*|arm64-*-elf*], ++ [has_native_backend=yes; arch=arm64; system=none], ++ [powerpc64le*-*-none|powerpc64le*-*-elf*], ++ [has_native_backend=yes; arch=power; model=ppc64le; system=none], ++ [powerpc64*-*-none|powerpc64*-*-elf*], ++ [has_native_backend=yes; arch=power; model=ppc64; system=none], ++ [riscv64-*-none|riscv64-*-elf*], ++ [has_native_backend=yes; arch=riscv; model=riscv64; system=none], ++ [s390x*-*-none|s390x*-*-elf*], ++ [has_native_backend=yes; arch=s390x; model=z10; system=none], ++ [x86_64-*-none|x86_64-*-elf*], ++ [has_native_backend=yes; arch=amd64; system=none] + ) + + AS_CASE([$arch], +-- +2.51.0 + diff --git a/patches/5.4.0/0002-Allow-ocaml-in-a-triplet-target-to-build-freestandin.patch b/patches/5.4.0/0002-Allow-ocaml-in-a-triplet-target-to-build-freestandin.patch new file mode 100644 index 00000000..9272c800 --- /dev/null +++ b/patches/5.4.0/0002-Allow-ocaml-in-a-triplet-target-to-build-freestandin.patch @@ -0,0 +1,81 @@ +From 126ef9d01e512a82c6cd79bf74d0b3e9e9d5cec0 Mon Sep 17 00:00:00 2001 +From: Samuel Hym +Date: Mon, 26 Feb 2024 11:51:11 +0100 +Subject: [PATCH 2/3] Allow `ocaml` in a triplet target to build freestanding + cross compilers + +Allow `ocaml` to be used as the last component of the target triplet in +case we are using a custom toolchain for a freestanding target. The +target triplet is then temporarily rewritten to "-none" to compute +the canonical target. + +This allows to use a `*-*-ocaml-` prefixes (ie `x86_64-solo5-ocaml-`) to +create cross-compiler toolchains dedicated to specific freestanding +targets +--- + configure | Bin 738624 -> 739110 bytes + configure.ac | 13 +++++++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/configure b/configure +index 1f0c06d943..04f729c00c 100755 +--- a/configure ++++ b/configure +@@ -3690,6 +3690,21 @@ IFS=$ac_save_IFS + case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + ++# Allow "ocaml" to be used as the last component of the target triplet in case ++# we are using a custom toolchain for a freestanding target. To do so, the ++# target triplet is temporarily rewritten to "-none" to compute the ++# canonical target ++save_target_alias="$target_alias" ++case $target_alias in #( ++ *-*-ocaml) : ++ ac_save_IFS=$IFS ++ IFS='-' ++ set x $target_alias ++ target_alias="$2-none" ++ IFS=$ac_save_IFS ;; #( ++ *) : ++ ;; ++esac + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 + printf %s "checking target system type... " >&6; } + if test ${ac_cv_target+y} +@@ -3730,6 +3745,7 @@ test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- ++target_alias="$save_target_alias" + + # Override cross_compiling and ac_tool_prefix variables since the C toolchain is + # used to generate target code when building a cross compiler +diff --git a/configure.ac b/configure.ac +index 8e5e1e9300..d634d70bf2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -302,7 +302,20 @@ AC_CONFIG_COMMANDS_PRE(OCAML_QUOTED_STRING_ID) + + AC_CANONICAL_BUILD + AC_CANONICAL_HOST ++# Allow "ocaml" to be used as the last component of the target triplet in case ++# we are using a custom toolchain for a freestanding target. To do so, the ++# target triplet is temporarily rewritten to "-none" to compute the ++# canonical target ++save_target_alias="$target_alias" ++AS_CASE([$target_alias], ++ [*-*-ocaml], ++ [ac_save_IFS=$IFS ++ IFS='-' ++ set x $target_alias ++ target_alias="$2-none" ++ IFS=$ac_save_IFS]) + AC_CANONICAL_TARGET ++target_alias="$save_target_alias" + + # Override cross_compiling and ac_tool_prefix variables since the C toolchain is + # used to generate target code when building a cross compiler +-- +2.51.0 + diff --git a/patches/5.4.0/0003-Set-Max_domains_-def-max-to-1.patch b/patches/5.4.0/0003-Set-Max_domains_-def-max-to-1.patch new file mode 100644 index 00000000..6f82569a --- /dev/null +++ b/patches/5.4.0/0003-Set-Max_domains_-def-max-to-1.patch @@ -0,0 +1,44 @@ +From 038db6e2efd54d13a6841b250f9efe338eea72e2 Mon Sep 17 00:00:00 2001 +From: Samuel Hym +Date: Fri, 12 Apr 2024 19:21:52 +0200 +Subject: [PATCH 3/3] Set `Max_domains_{def,max}` to 1 + +Solo5 is single-core with no scheduler, so avoid the useless memory +waste + +Note that since PR#13272 the maximum number of domains can set using a +parameter in `OCAMLRUNPARAM` so a patchless implementation could be to +add to `nolibc`: +- a `secure_getenv` returning `"d=1"` for the `OCAMLRUNPARAM` value, +- a `sscanf`; it could be hard-coded version just for that use case + (namely recover the `1`) +but this would still be rather brittle +--- + runtime/caml/domain.h | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/runtime/caml/domain.h b/runtime/caml/domain.h +index c7d6c1136f..ef3ff52ede 100644 +--- a/runtime/caml/domain.h ++++ b/runtime/caml/domain.h +@@ -26,15 +26,11 @@ + #include "mlvalues.h" + #include "domain_state.h" + +-#ifdef ARCH_SIXTYFOUR +-#define Max_domains_def 128 +-#else +-#define Max_domains_def 16 +-#endif ++#define Max_domains_def 1 + + /* Upper limit for the number of domains. Chosen to be arbitrarily large. Used + * for sanity checking [max_domains] value in OCAMLRUNPARAM. */ +-#define Max_domains_max 4096 ++#define Max_domains_max 1 + + /* is the minor heap full or an external interrupt has been triggered */ + Caml_inline int caml_check_gc_interrupt(caml_domain_state * dom_st) +-- +2.51.0 +