From 2287e31731420c915e880eabd06169331c276037 Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Tue, 23 Jun 2026 12:36:28 +0200 Subject: [PATCH 1/6] CI: Update the configuration of the non-cross compiler In the cross-compilers CI tests, update the configuration of the initial non-cross compiler to set the same options than in standard opam packages (`ocaml-variants.opam` or the released `ocaml-compiler` packages) --- .github/workflows/build-cross.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-cross.yml b/.github/workflows/build-cross.yml index 567f4a57d400..ffcdb70fdfce 100644 --- a/.github/workflows/build-cross.yml +++ b/.github/workflows/build-cross.yml @@ -50,7 +50,9 @@ jobs: set -x ./configure --disable-warn-error --disable-ocamldoc \ --disable-ocamltest --disable-stdlib-manpages \ - --prefix="$PREFIX" || failed=$? + --prefix="$PREFIX" --with-additional-stublibsdir \ + --with-relative-libdir --enable-runtime-search \ + --enable-runtime-search-target=fallback || failed=$? if ((failed)) ; then set +x echo ; echo "::group::config.log content ($(wc -l config.log) lines)" cat config.log ; echo '::endgroup::' ; exit $failed From 62051686ec128d86f7964d793235b4ec32b21faf Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Thu, 25 Jun 2026 16:41:37 +0200 Subject: [PATCH 2/6] Test in CI that the cross compilers are relocatable --- .github/workflows/build-cross.yml | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/build-cross.yml b/.github/workflows/build-cross.yml index ffcdb70fdfce..3504d7a15316 100644 --- a/.github/workflows/build-cross.yml +++ b/.github/workflows/build-cross.yml @@ -93,6 +93,8 @@ jobs: run: | set -x ./configure --prefix="$HOME/cross" --target=x86_64-w64-mingw32 \ + --with-additional-stublibsdir --with-relative-libdir \ + --enable-runtime-search --enable-runtime-search-target=fallback \ TARGET_LIBDIR="$TESTDIR" || failed=$? if ((failed)) ; then set +x echo ; echo "::group::config.log content ($(wc -l config.log) lines)" @@ -120,6 +122,21 @@ jobs: name: x86_64-w64-mingw32-executable path: example.exe retention-days: 1 + - name: Move the cross compiler + run: | + mv $HOME/cross $HOME/relocated + ln -srf "$HOME/relocated/bin/flexlink.opt.exe" "$HOME/.local/bin/flexlink" + - name: Show opt.opt configuration after relocation + run: | + set -x + $HOME/relocated/bin/ocamlopt.opt.exe -config + cat runtime/build_config.h + - name: Cross compile a small program after relocation + run: | + printf %s "$EXAMPLE_PROGRAM$COMPLIBS_PROG_X86_64" > example.ml + set -x + cat example.ml + $HOME/relocated/bin/ocamlopt.opt.exe -I $HOME/relocated/lib/ocaml/compiler-libs/ ocamlcommon.cmxa ocamloptcomp.cmxa example.ml -o example.exe -verbose - name: Test cross sak run: | printf %s "$STR_UTF16" > utf16.ref @@ -167,6 +184,8 @@ jobs: run: | set -x ./configure --prefix="$HOME/cross" --target=aarch64-linux-gnu \ + --with-additional-stublibsdir --with-relative-libdir \ + --enable-runtime-search --enable-runtime-search-target=fallback \ || failed=$? if ((failed)) ; then set +x echo ; echo "::group::config.log content ($(wc -l config.log) lines)" @@ -189,6 +208,24 @@ jobs: run: | set -x qemu-aarch64 -L /usr/aarch64-linux-gnu example + - name: Move the cross compiler + run: | + mv $HOME/cross $HOME/relocated + - name: Show opt.opt configuration + run: | + set -x + $HOME/relocated/bin/ocamlopt.opt -config + cat runtime/build_config.h + - name: Cross compile a small program + run: | + printf %s "$EXAMPLE_PROGRAM$COMPLIBS_PROG_AARCH64" > example.ml + set -x + cat example.ml + $HOME/relocated/bin/ocamlopt.opt -I $HOME/relocated/lib/ocaml/compiler-libs/ ocamlcommon.cmxa ocamloptcomp.cmxa example.ml -o example -verbose + - name: Run the small example program + run: | + set -x + qemu-aarch64 -L /usr/aarch64-linux-gnu example - name: Test cross sak run: | printf %s "$STR_UTF16" > utf16.ref @@ -255,6 +292,8 @@ jobs: # program should _not_ be run with cleanup on exit (so no # `c=1` in `OCAMLRUNPARAM`) ./configure --prefix="$HOME/cross" --target=$TARGET \ + --with-additional-stublibsdir --with-relative-libdir \ + --enable-runtime-search --enable-runtime-search-target=fallback \ TARGET_LIBDIR="/dummy/directory" \ CC="$DIR/clang --target=$TARGET" \ AR="$DIR/llvm-ar" \ From b4e9a6fbcca45891978a2a5347a0b11a3797dc3b Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Thu, 25 Jun 2026 16:11:08 +0200 Subject: [PATCH 3/6] Set `HOST_LIBDIR` during configuration The `HOST_LIBDIR` variable was used only internally in `Makefile.common` so that `Makefile.cross` could override it. But when a cross compiler is configured, even with `--with-relative-libdir`, the resulting value was absolute because `LIBDIR` is then the concatenation of the binary directory with the relative libdir path. This introduces a matching `host_libdir` variable in `configure` to store the relative path when it is set and so that `HOST_LIBDIR` contains the expected value in cross and non-cross cases. This also allows to set both `--with-relative-libdir` and `TARGET_LIBDIR` explicitly when building a cross compiler, where the relative libdir is meant for the host. --- Makefile.build_config.in | 5 +++++ Makefile.common | 4 ---- Makefile.cross | 3 +-- configure | 14 +++++++++++++- configure.ac | 12 +++++++++--- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Makefile.build_config.in b/Makefile.build_config.in index 093cca67bd0f..26f0444595d6 100644 --- a/Makefile.build_config.in +++ b/Makefile.build_config.in @@ -167,6 +167,11 @@ DOCDIR=@docdir@ TARGET_LIBDIR=@TARGET_LIBDIR@ TARGET_LIBDIR_IS_RELATIVE=@target_libdir_is_relative@ +### Where to look for the standard library on host +# The difference with LIBDIR (in Makefile.config) is that this is just the +# relative path when --with-relative-libdir is enabled +HOST_LIBDIR=@host_libdir@ + unix_directory = @unix_directory@ unix_library = @unix_library@ diff --git a/Makefile.common b/Makefile.common index 4787eb8d5d73..53ef3ce60ab3 100644 --- a/Makefile.common +++ b/Makefile.common @@ -531,10 +531,6 @@ ifeq "$(TARGET_LIBDIR_IS_RELATIVE)" "true" $(if $(SRCDIR_REAL_ENCODED),:.=$(SRCDIR_REAL_ENCODED)) endif # ifeq "$(TARGET_LIBDIR_IS_RELATIVE)" "true" -# Allow Makefile.cross to override the Standard Library default for the compiler -# itself. -HOST_LIBDIR ?= $(TARGET_LIBDIR) - OC_COMMON_LINKFLAGS += \ -set-runtime-default \ $(call QUOTE_SINGLE,standard_library_default=$(HOST_LIBDIR)) diff --git a/Makefile.cross b/Makefile.cross index c5a47d957853..ed65b011600b 100644 --- a/Makefile.cross +++ b/Makefile.cross @@ -53,8 +53,7 @@ CROSS_OVERRIDES=OCAMLRUN=ocamlrun NEW_OCAMLRUN=ocamlrun \ # be overridden with -set-runtime-default so that cross/bin/ocamlopt instead has # cross/lib/ocaml for Config.standard_library_default CROSS_COMPILER_OVERRIDES=$(CROSS_OVERRIDES) CAMLC=ocamlc CAMLOPT=ocamlopt \ - BEST_OCAMLC=ocamlc BEST_OCAMLOPT=ocamlopt BEST_OCAMLLEX=ocamllex \ - HOST_LIBDIR="$(LIBDIR)" + BEST_OCAMLC=ocamlc BEST_OCAMLOPT=ocamlopt BEST_OCAMLLEX=ocamllex CROSS_COMPILERLIBS_OVERRIDES=$(CROSS_OVERRIDES) CAMLC=ocamlc \ CAMLOPT="$(ROOTDIR)/ocamlopt.opt$(EXE) $(STDLIBFLAGS)" diff --git a/configure b/configure index 7ea4ec2a5499..954252f59b52 100755 --- a/configure +++ b/configure @@ -818,6 +818,7 @@ target_libdir_is_relative ar_supports_response_files QS TARGET_LIBDIR +host_libdir ocaml_libdir ocaml_bindir ocaml_prefix @@ -3671,6 +3672,7 @@ LINEAR_MAGIC_NUMBER=Caml1999L038 + ## Generated files @@ -24532,10 +24534,20 @@ then : fi fi -if test x"$bindir_to_libdir" != 'x' && test x"$TARGET_LIBDIR" != 'x' +host_libdir='${TARGET_LIBDIR}' + +if $cross_compiler +then : + if test x"$bindir_to_libdir" != 'x' +then : + host_libdir="$bindir_to_libdir" +fi +else $as_nop + if test x"$bindir_to_libdir" != 'x' && test x"$TARGET_LIBDIR" != 'x' then : as_fn_error $? "--with-relative-libdir and TARGET_LIBDIR cannot both be specified" "$LINENO" 5 fi +fi # Define a few macros that were defined in config/m-nt.h # but whose value is not guessed properly by configure diff --git a/configure.ac b/configure.ac index f7a7258f4acf..bed59f9738d9 100644 --- a/configure.ac +++ b/configure.ac @@ -297,6 +297,7 @@ AC_SUBST([compute_deps]) AC_SUBST([ocaml_prefix]) AC_SUBST([ocaml_bindir]) AC_SUBST([ocaml_libdir]) +AC_SUBST([host_libdir]) AC_SUBST([TARGET_LIBDIR]) AC_SUBST([QS]) AC_SUBST([ar_supports_response_files]) @@ -3136,9 +3137,14 @@ AS_IF([test x"$libdir_given" = 'xno'], [AC_MSG_ERROR(m4_normalize([--with-relative-libdir and --libdir cannot both be specified]))])]) -AS_IF([test x"$bindir_to_libdir" != 'x' && test x"$TARGET_LIBDIR" != 'x'], - [AC_MSG_ERROR(m4_normalize([--with-relative-libdir and TARGET_LIBDIR cannot - both be specified]))]) +host_libdir='${TARGET_LIBDIR}' + +AS_IF([$cross_compiler], + [AS_IF([test x"$bindir_to_libdir" != 'x'], + [host_libdir="$bindir_to_libdir"])], + [AS_IF([test x"$bindir_to_libdir" != 'x' && test x"$TARGET_LIBDIR" != 'x'], + [AC_MSG_ERROR(m4_normalize([--with-relative-libdir and TARGET_LIBDIR cannot + both be specified]))])]) # Define a few macros that were defined in config/m-nt.h # but whose value is not guessed properly by configure From cf91c9f4d4e374684a9e38f83967159a88d4d449 Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Thu, 25 Jun 2026 17:44:14 +0200 Subject: [PATCH 4/6] Change a `configure`-internal variable for cross compilers Set the `configure`-internal `default_separator` variable according to host instead of target and rename it `host_dir_sep` to make this more explicit This makes the `--with-relative-libdir` option choose the proper path and the test that the path is explicit relative consistent (but it doesn't fix the fact that some paths are currently shared between host and target) Note that the change is transparent when host = target --- configure | 14 +++++++------- configure.ac | 17 +++++++++-------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 954252f59b52..065e1a639f19 100755 --- a/configure +++ b/configure @@ -4081,11 +4081,11 @@ fi # Environment-specific set-up -case $target in #( +case $host in #( *-w64-mingw32*|*-pc-windows) : - default_separator='\' ;; #( + host_dir_sep='\' ;; #( *) : - default_separator='/' ;; + host_dir_sep='/' ;; esac # Environment variables that are taken into account @@ -4381,7 +4381,7 @@ then : no) : ocaml_additional_stublibs_dir='' ;; #( yes) : - ocaml_additional_stublibs_dir="..${default_separator}stublibs" ;; #( + ocaml_additional_stublibs_dir="..${host_dir_sep}stublibs" ;; #( *) : ocaml_additional_stublibs_dir="$withval" ;; esac @@ -4467,7 +4467,7 @@ then : no) : bindir_to_libdir='' ;; #( yes) : - bindir_to_libdir="..${default_separator}lib${default_separator}ocaml" ;; #( + bindir_to_libdir="..${host_dir_sep}lib${host_dir_sep}ocaml" ;; #( *) : bindir_to_libdir="$withval" ;; esac @@ -25815,7 +25815,7 @@ fi ocaml_additional_stublibs_dir=\ '$(echo "$ocaml_additional_stublibs_dir" | sed -e "s/'/'\"'\"'/g")' ocaml_libdir='$(echo "$ocaml_libdir" | sed -e "s/'/'\"'\"'/g")' - default_separator='$default_separator' + host_dir_sep='$host_dir_sep' supports_shared_libraries='$supports_shared_libraries' _ACEOF @@ -26996,7 +26996,7 @@ ltmain=$ac_aux_dir/ltmain.sh test x"$ocaml_additional_stublibs_dir" = 'x' || \ echo "$ocaml_additional_stublibs_dir" > runtime/ld.conf if $supports_shared_libraries; then - echo ".${default_separator}stublibs" >> runtime/ld.conf + echo ".${host_dir_sep}stublibs" >> runtime/ld.conf fi echo "." >> runtime/ld.conf ;; diff --git a/configure.ac b/configure.ac index bed59f9738d9..a9266504ecc7 100644 --- a/configure.ac +++ b/configure.ac @@ -479,11 +479,12 @@ AS_IF([test -n "$csc"], dnl The separator should be being treated differently for host/target for dnl cross-compilers, but the installation layout for cross-compilers is already dnl incorrect (for example, ld.conf is processed by _both_ the host and target -dnl runtimes), so this is left as target-specific for now. -AS_CASE([$target], +dnl runtimes), so this is left as host-specific for now as being more useful +dnl (ie things break at compile-time if paths are incorrect on the host) +AS_CASE([$host], [*-w64-mingw32*|*-pc-windows], - [default_separator='\'], - [default_separator='/']) + [host_dir_sep='\'], + [host_dir_sep='/']) # Environment variables that are taken into account @@ -684,7 +685,7 @@ AC_ARG_WITH([additional-stublibsdir], [no], [ocaml_additional_stublibs_dir=''], [yes], - [ocaml_additional_stublibs_dir="..${default_separator}stublibs"], + [ocaml_additional_stublibs_dir="..${host_dir_sep}stublibs"], [ocaml_additional_stublibs_dir="$withval"])], [ocaml_additional_stublibs_dir='']) @@ -741,7 +742,7 @@ AC_ARG_WITH([relative-libdir], [no], [bindir_to_libdir=''], [yes], - [bindir_to_libdir="..${default_separator}lib${default_separator}ocaml"], + [bindir_to_libdir="..${host_dir_sep}lib${host_dir_sep}ocaml"], [bindir_to_libdir="$withval"])], [bindir_to_libdir='']) @@ -3277,13 +3278,13 @@ AC_CONFIG_COMMANDS([runtime/ld.conf], test x"$ocaml_additional_stublibs_dir" = 'x' || \ echo "$ocaml_additional_stublibs_dir" > runtime/ld.conf if $supports_shared_libraries; then - echo ".${default_separator}stublibs" >> runtime/ld.conf + echo ".${host_dir_sep}stublibs" >> runtime/ld.conf fi echo "." >> runtime/ld.conf], [ocaml_additional_stublibs_dir=\ '$(echo "$ocaml_additional_stublibs_dir" | sed -e "s/'/'\"'\"'/g")' ocaml_libdir='$(echo "$ocaml_libdir" | sed -e "s/'/'\"'\"'/g")' - default_separator='$default_separator' + host_dir_sep='$host_dir_sep' supports_shared_libraries='$supports_shared_libraries']) # Just before config.status is generated, determine the final values for MKEXE, From 3e788bc22d052bf3405650cf451e4acd59d309d2 Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Thu, 25 Jun 2026 17:13:24 +0200 Subject: [PATCH 5/6] Use `TARGET_LIBDIR` when available to set `target_libdir_is_relative` When configuring a cross compiler with `./configure --with-relative-libdir TARGET_LIBDIR=...` use `TARGET_LIBDIR` instead of the host libdir to set `target_libdir_is_relative` --- configure | 18 +++++++++++++++++- configure.ac | 11 ++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 065e1a639f19..b74ef0425957 100755 --- a/configure +++ b/configure @@ -4087,6 +4087,12 @@ case $host in #( *) : host_dir_sep='/' ;; esac +case $target in #( + *-w64-mingw32*|*-pc-windows) : + target_dir_sep='\' ;; #( + *) : + target_dir_sep='/' ;; +esac # Environment variables that are taken into account @@ -24510,7 +24516,10 @@ then : if test x"$bindir_to_libdir" != 'x' then : ocaml_libdir="$bindir_to_libdir" - target_libdir_is_relative=true + if test x"$TARGET_LIBDIR" = x +then : + target_libdir_is_relative=true +fi case $cygwin_build_env,$host in #( true,*-w64-mingw32*|true,*-pc-windows) : build_bindir_to_libdir="$(LC_ALL=C.UTF-8 cygpath \ @@ -24534,6 +24543,13 @@ then : fi fi +case $TARGET_LIBDIR in #( + .|..|.${target_dir_sep}*|..${target_dir_sep}*) : + target_libdir_is_relative=true ;; #( + *) : + ;; +esac + host_libdir='${TARGET_LIBDIR}' if $cross_compiler diff --git a/configure.ac b/configure.ac index a9266504ecc7..940b0b4f6cf5 100644 --- a/configure.ac +++ b/configure.ac @@ -485,6 +485,10 @@ AS_CASE([$host], [*-w64-mingw32*|*-pc-windows], [host_dir_sep='\'], [host_dir_sep='/']) +AS_CASE([$target], + [*-w64-mingw32*|*-pc-windows], + [target_dir_sep='\'], + [target_dir_sep='/']) # Environment variables that are taken into account @@ -3123,7 +3127,8 @@ AS_CASE([$cygwin_build_env,$host], AS_IF([test x"$libdir_given" = 'xno'], [AS_IF([test x"$bindir_to_libdir" != 'x'], [ocaml_libdir="$bindir_to_libdir" - target_libdir_is_relative=true + AS_IF([test x"$TARGET_LIBDIR" = x], + [target_libdir_is_relative=true]) AS_CASE([$cygwin_build_env,$host], [true,*-w64-mingw32*|true,*-pc-windows], [build_bindir_to_libdir="$(LC_ALL=C.UTF-8 cygpath \ @@ -3138,6 +3143,10 @@ AS_IF([test x"$libdir_given" = 'xno'], [AC_MSG_ERROR(m4_normalize([--with-relative-libdir and --libdir cannot both be specified]))])]) +AS_CASE([$TARGET_LIBDIR], + [.|..|.${target_dir_sep}*|..${target_dir_sep}*], + [target_libdir_is_relative=true]) + host_libdir='${TARGET_LIBDIR}' AS_IF([$cross_compiler], From eff4326cb9c4c6ea52d923e847a75aac4271cfb7 Mon Sep 17 00:00:00 2001 From: Samuel Hym Date: Thu, 25 Jun 2026 16:13:40 +0200 Subject: [PATCH 6/6] Fix a typo in a CI step name --- .github/workflows/build-cross.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-cross.yml b/.github/workflows/build-cross.yml index 3504d7a15316..811836849bf3 100644 --- a/.github/workflows/build-cross.yml +++ b/.github/workflows/build-cross.yml @@ -180,7 +180,7 @@ jobs: with: submodules: true persist-credentials: false - - name: Configure, build and install Linux-to-Windows OCaml + - name: Configure, build and install Linux-to-ARM-Linux OCaml run: | set -x ./configure --prefix="$HOME/cross" --target=aarch64-linux-gnu \