diff --git a/.ci/Manifest.toml b/.ci/Manifest.toml index 1a916252483..0f540c5408a 100644 --- a/.ci/Manifest.toml +++ b/.ci/Manifest.toml @@ -37,16 +37,16 @@ uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[deps.BinaryBuilder]] deps = ["ArgParse", "BinaryBuilderBase", "Binutils_jll", "Dates", "Downloads", "GitHub", "HTTP", "JLD2", "JSON", "LibGit2", "Libdl", "Logging", "LoggingExtras", "ObjectFile", "OutputCollectors", "Patchelf_jll", "Pkg", "PkgLicenses", "REPL", "Random", "Registrator", "RegistryTools", "SHA", "Scratch", "Sockets", "TOML", "UUIDs", "ghr_jll"] -git-tree-sha1 = "32a89265ffd77083daf729618d4279242ee44020" -repo-rev = "master" -repo-url = "https://github.com/JuliaPackaging/BinaryBuilder.jl" +git-tree-sha1 = "c844af8893f1597a57e2d28d58082262313db77d" +repo-rev = "ct/ocaml-support" +repo-url = "https://github.com/JuliaPackaging/BinaryBuilder.jl.git" uuid = "12aac903-9f7c-5d81-afc2-d9565ea332ae" version = "0.6.4" [[deps.BinaryBuilderBase]] deps = ["Bzip2_jll", "CodecZlib", "Downloads", "Gzip_jll", "HistoricalStdlibVersions", "InteractiveUtils", "JLLWrappers", "JSON", "LibGit2", "LibGit2_jll", "Libdl", "Logging", "OrderedCollections", "OutputCollectors", "Pkg", "Printf", "ProgressMeter", "REPL", "Random", "SHA", "Scratch", "SimpleBufferStream", "TOML", "Tar", "Tar_jll", "UUIDs", "XZ_jll", "Zstd_jll", "p7zip_jll", "pigz_jll", "unzip_jll"] -git-tree-sha1 = "85259632e317f61245d8240d3ee9b08112f52903" -repo-rev = "master" +git-tree-sha1 = "91ed234470884b2dd655c0a9dd53f13d16ef3cae" +repo-rev = "ct/ocaml-runner" repo-url = "https://github.com/JuliaPackaging/BinaryBuilderBase.jl.git" uuid = "7f725544-6523-48cd-82d1-3fa08ff4056e" version = "1.37.0" diff --git a/0_RootFS/OCaml/build_tarballs.jl b/0_RootFS/OCaml/build_tarballs.jl new file mode 100644 index 00000000000..9209563be39 --- /dev/null +++ b/0_RootFS/OCaml/build_tarballs.jl @@ -0,0 +1,156 @@ +### Instructions for adding a new version of the OCaml toolchain +# +# * update the `version` variable and `sources` +# * To deploy the shard and automatically update your BinaryBuilderBase's +# `Artifacts.toml`, use the `--deploy` flag to the `build_tarballs.jl` script. +# You can build & deploy by running: +# +# julia build_tarballs.jl --debug --verbose --deploy TARGET +# + +using BinaryBuilderBase, BinaryBuilder, Pkg.Artifacts + +include("../common.jl") + +name = "OCamlBase" +version = v"5.4.0" + +sources = [ + GitSource("https://github.com/ocaml/ocaml.git", + "ff1ab416a5503c8bde9fa3fae5f2bb21c7ddc81e"), # 5.4.0~alpha1 + GitSource("https://github.com/ocaml/dune", + "76c0c3941798f81dcc13a305d7abb120c191f5fa"), # 3.19.1 + GitSource("https://github.com/ocaml/ocamlbuild", + "131ba63a1b96d00f3986c8187677c8af61d20a08"), # 0.16.1 + GitSource("https://github.com/ocaml/opam", + "e13109411952d4f723a165c2a24b8c03c4945041"), # 2.3.0 + DirectorySource("./bundled"), +] + +# Check if deploy flag is set +deploy = "--deploy" in ARGS + +# These are the targets we support right now: +# x86_64-w64-mingw32 +# x86_64-apple-darwin14 +# aarch64-apple-darwin20 +# x86_64-linux-gnu +# x86_64-linux-musl +# aarch64-linux-gnu +# aarch64-linux-musl +# riscv64-linux-gnu +# riscv64-linux-musl +# powerpc64le-linux-gnu +# +# Not supported: +# i686: OCaml 5.0 dropped support for 32-bit platforms +# freebsd: `POSIX threads are required but not supported on this platform` + +# The first thing we're going to do is to install Rust for all targets into a single prefix +script = raw""" +cd ${WORKSPACE}/srcdir/ocaml +git submodule update --init + +# Apply patches +for f in ${WORKSPACE}/srcdir/patches/*.patch; do + atomic_patch -p1 ${f} +done + +# unset compiler env vars so that configure can detect them properly +unset CC CXX LD STRIP AS + +if [[ "${target}" == "${MACHTYPE}" ]]; then + # Build a native compiler in $prefix + ./configure --prefix=${prefix} + make -j${nproc} + make install +else + # Build a native compiler in $host_prefix (which takes PATH preference over $prefix) + ./configure --prefix=${host_prefix} --build=${MACHTYPE} --host=${MACHTYPE} + make -j${nproc} + make install + git clean -fxd + + # Build a cross-compiler in $prefix + ./configure --prefix=${prefix} --build=${MACHTYPE} --host=${MACHTYPE} --target=${target} + make crossopt -j${nproc} + make installcross + if [[ "${target}" == *-mingw* ]]; then + # the OCaml configure script detects the executable extension by looking at the + # target compiler. for host utilities, we don't want this symlink, so remove it. + for bin in ${bindir}/*.exe; do + # (links to) target binaries should retain their extension + if file -L $bin | grep 'PE32' >/dev/null; then + continue + fi + + # if this is a symlink, update both the name of the link and the target + if [[ -L $bin ]]; then + target=$(readlink $bin) + rm $bin + ln -s $(basename ${target} .exe) ${bindir}/$(basename ${bin} .exe) + + # if this is a file, simply rename it + elif [[ -f $bin ]]; then + mv $bin ${bindir}/$(basename ${bin} .exe) + fi + done + fi +fi + +# Fix shebang of ocamlrun scripts to not hardcode a path of the build environment +for bin in $(file ${bindir}/* | grep "a \S*/ocamlrun script" | cut -d: -f1); do + abspath=$(file ${bin} | grep -oh "a \S*/ocamlrun script" | cut -d' ' -f2) + sed -i "s?${abspath}?/usr/bin/env ocamlrun?" "${bin}" +done + +# Dune +cd ${WORKSPACE}/srcdir/dune +./configure --prefix $prefix +make release +make install + +# OCamlbuild +cd ${WORKSPACE}/srcdir/ocamlbuild +make configure OCAMLBUILD_PREFIX=$prefix OCAMLBUILD_BINDIR=$bindir OCAMLBUILD_LIBDIR=$prefix/lib +# XXX: can't use $libdir because on Windows it aliases with $bindir +# while ocamlbuild wants to put files in $libdir/ocamlbuild +make -j${nproc} +make install + +# Opam +cd ${WORKSPACE}/srcdir/opam +./configure --prefix $prefix --host=${MACHTYPE} --with-vendored-deps +make -j${nproc} +make install +""" + +platforms = Platform[ host_platform ] +products = Product[ + # build with no products since all of our products are for the host, not the target + + # ExecutableProduct("ocamlopt.opt", :ocamlopt), + # ExecutableProduct("ocamlc.opt", :ocamlc), + # ExecutableProduct("ocamlrun", :ocamlrun), +] +dependencies = Dependency[] + +name = "OCaml" +compiler_target = try + parse(Platform, ARGS[end]) +catch + error("This is not a typical build_tarballs.jl! Must provide exactly one platform as the last argument!") +end +deleteat!(ARGS, length(ARGS)) + +# Build the tarballs +ndARGS, deploy_target = find_deploy_arg(ARGS) +build_info = build_tarballs(ndARGS, name, version, sources, script, Platform[compiler_target], products, dependencies; + skip_audit=true, julia_compat="1.6", preferred_gcc_version=v"6") + +build_info = Dict(host_platform => first(values(build_info))) + +# Upload the artifacts (if requested) +if deploy_target !== nothing + upload_and_insert_shards(deploy_target, name, version, build_info; target=compiler_target) +end diff --git a/0_RootFS/OCaml/bundled/patches/00001-ocaml-relative-libdir.patch b/0_RootFS/OCaml/bundled/patches/00001-ocaml-relative-libdir.patch new file mode 100644 index 00000000000..6212557be0a --- /dev/null +++ b/0_RootFS/OCaml/bundled/patches/00001-ocaml-relative-libdir.patch @@ -0,0 +1,395 @@ +commit 06fe917b0104b55dc80ac0abe8a1e0915446394f +Author: Cody Tapscott +Date: Thu May 8 19:08:26 2025 -0400 + + Add relative path fallback for libdir / bindir + + The existing `OCAMLLIB` environment variable already allows you to use + a standard library installed elsewhere, but it doesn't let you re-locate + an existing installation. As one might expect, the problem is that the + stdlib itself contains absolute references to its own paths. + + This patch tries to hook into both places where that happens and do an + on-the-fly replacement of the standard library path, if it turns out + this is the standard library that OCaml that was built with (just + moved). + + This kicks in if the default hard-coded `%%LIBDIR%%`/`%%BINDIR%%` cannot + be found. + +diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml +index c55224fab8..1b5b0aa99f 100644 +--- a/bytecomp/bytelink.ml ++++ b/bytecomp/bytelink.ml +@@ -344,7 +344,10 @@ let read_runtime_launch_info file = + try + let bindir_start = String.index buffer '\n' + 1 in + let bindir_end = String.index_from buffer bindir_start '\000' in +- let bindir = String.sub buffer bindir_start (bindir_end - bindir_start) in ++ let bindir = ++ let relocate_bindir = Misc.replace_substring ~before:Config.bindir_default ~after:Config.bindir ++ and raw_bindir = String.sub buffer bindir_start (bindir_end - bindir_start) in ++ relocate_bindir raw_bindir in + let executable_offset = bindir_end + 2 in + let launcher = + let kind = String.sub buffer 0 (bindir_start - 1) in +diff --git a/runtime/caml/misc.h b/runtime/caml/misc.h +index 1182b72808..1c16cf48f8 100644 +--- a/runtime/caml/misc.h ++++ b/runtime/caml/misc.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + /* Detection of available C attributes and compiler extensions */ + +@@ -491,6 +492,141 @@ extern double caml_log1p(double); + #define main_os wmain + #endif + ++static wchar_t * __cdecl _wdirname(wchar_t *path); ++ ++// Adapted to wchar_t from ++// https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/misc/dirname.c ++ ++#include ++#include ++#include ++ ++static wchar_t * __cdecl ++_wdirname(wchar_t *path) ++{ ++ static wchar_t *retfail = NULL; ++ size_t len = wcslen(path); ++ ++ if (path && *path) ++ { ++ wchar_t *refpath = path; ++ ++ /* SUSv3 identifies a special case, where path is exactly equal to "//"; ++ * (we will also accept "\\" in the Win32 context, but not "/\" or "\/", ++ * and neither will we consider paths with an initial drive designator). ++ * For this special case, SUSv3 allows the implementation to choose to ++ * return "/" or "//", (or "\" or "\\", since this is Win32); we will ++ * simply return the path unchanged, (i.e. "//" or "\\"). */ ++ if (len > 1 && (refpath[0] == L'/' || refpath[0] == L'\\')) ++ { ++ if (refpath[1] == refpath[0] && refpath[2] == L'\0') ++ { ++ return path; ++ } ++ } ++ /* For all other cases ... ++ * step over the drive designator, if present ... */ ++ else if (len > 1 && refpath[1] == L':') ++ { ++ /* FIXME: maybe should confirm *refpath is a valid drive designator. */ ++ refpath += 2; ++ } ++ /* check again, just to ensure we still have a non-empty path name ... */ ++ if (*refpath) ++ { ++# undef basename ++# define basename __the_basename /* avoid shadowing. */ ++ /* reproduce the scanning logic of the "basename" function ++ * to locate the basename component of the current path string, ++ * (but also remember where the dirname component starts). */ ++ wchar_t *refname, *basename; ++ for (refname = basename = refpath; *refpath; ++refpath) ++ { ++ if (*refpath == L'/' || *refpath == L'\\') ++ { ++ /* we found a dir separator ... ++ * step over it, and any others which immediately follow it. */ ++ while (*refpath == L'/' || *refpath == L'\\') ++ ++refpath; ++ /* if we didn't reach the end of the path string ... */ ++ if (*refpath) ++ /* then we have a new candidate for the base name. */ ++ basename = refpath; ++ else ++ /* we struck an early termination of the path string, ++ * with trailing dir separators following the base name, ++ * so break out of the for loop, to avoid overrun. */ ++ break; ++ } ++ } ++ /* now check, ++ * to confirm that we have distinct dirname and basename components. */ ++ if (basename > refname) ++ { ++ /* and, when we do ... ++ * backtrack over all trailing separators on the dirname component, ++ * (but preserve exactly two initial dirname separators, if identical), ++ * and add a NUL terminator in their place. */ ++ do --basename; ++ while (basename > refname && (*basename == L'/' || *basename == L'\\')); ++ if (basename == refname && (refname[0] == L'/' || refname[0] == L'\\') ++ && refname[1] == refname[0] && refname[2] != L'/' && refname[2] != L'\\') ++ ++basename; ++ *++basename = L'\0'; ++ /* if the resultant dirname begins with EXACTLY two dir separators, ++ * AND both are identical, then we preserve them. */ ++ refpath = path; ++ while ((*refpath == L'/' || *refpath == L'\\')) ++ ++refpath; ++ if ((refpath - path) > 2 || path[1] != path[0]) ++ refpath = path; ++ /* and finally ... ++ * we remove any residual, redundantly duplicated separators from the dirname, ++ * reterminate, and return it. */ ++ refname = refpath; ++ while (*refpath) ++ { ++ if ((*refname++ = *refpath) == L'/' || *refpath++ == L'\\') ++ { ++ while (*refpath == L'/' || *refpath == L'\\') ++ ++refpath; ++ } ++ } ++ *refname = L'\0'; ++ } ++ else ++ { ++ /* either there were no dirname separators in the path name, ++ * or there was nothing else ... */ ++ if (*refname == L'/' || *refname == L'\\') ++ { ++ /* it was all separators, so return one. */ ++ ++refname; ++ } ++ else ++ { ++ /* there were no separators, so return '.'. */ ++ *refname++ = L'.'; ++ } ++ /* add a NUL terminator, in either case, ++ * then transform to the multibyte char domain, ++ * using our own buffer. */ ++ *refname = L'\0'; ++ } ++ return path; ++ } ++# undef basename ++ } ++ /* path is NULL, or an empty string; default return value is "." ... ++ * return this in our own buffer, regenerated by wide char transform, ++ * in case the caller trashed it after a previous call. ++ */ ++ retfail = realloc(retfail, 2 * sizeof(wchar_t)); ++ retfail[0] = L'.'; ++ retfail[1] = L'\0'; ++ return retfail; ++} ++ + #define access_os _waccess + #define open_os _wopen + #define stat_os _wstati64 +@@ -508,11 +644,13 @@ extern double caml_log1p(double); + #define execvp_os _wexecvp + #define execvpe_os _wexecvpe + #define strcmp_os wcscmp ++#define strncmp_os wcsncmp + #define strlen_os wcslen + #define sscanf_os swscanf + #define strcpy_os wcscpy + #define mktemp_os _wmktemp + #define fopen_os _wfopen ++#define dirname_os _wdirname + + #define clock_os caml_win32_clock + +@@ -553,11 +691,13 @@ extern double caml_log1p(double); + #define execvp_os execvp + #define execvpe_os execvpe + #define strcmp_os strcmp ++#define strncmp_os strncmp + #define strlen_os strlen + #define sscanf_os sscanf + #define strcpy_os strcpy + #define mktemp_os mktemp + #define fopen_os fopen ++#define dirname_os dirname + + #define clock_os clock + +diff --git a/runtime/dynlink.c b/runtime/dynlink.c +index d3e6b1b534..105c699589 100644 +--- a/runtime/dynlink.c ++++ b/runtime/dynlink.c +@@ -83,19 +83,62 @@ static c_primitive lookup_primitive(const char * name) + + #define LD_CONF_NAME T("ld.conf") + ++static int is_directory(char_os * p) ++{ ++#ifdef _WIN32 ++ struct _stati64 st; ++#else ++ struct stat st; ++#endif ++ int ret; ++ ++ ret = stat_os(p, &st); ++ if (ret == -1) return -1; ++ if (st.st_mode == -1) return -1; ++ ++#ifdef S_ISDIR ++ return S_ISDIR(st.st_mode) ? 1 : 0; ++#else ++ return st.st_mode & S_IFDIR ? 1 : 0; ++#endif ++} ++ + CAMLexport const char_os * caml_get_stdlib_location(void) + { +- const char_os * stdlib; ++ const char_os * bindir; ++ char_os * exe; ++ ++ static const char_os * stdlib = NULL; ++ if (stdlib != NULL) ++ return stdlib; ++ + stdlib = caml_secure_getenv(T("OCAMLLIB")); + if (stdlib == NULL) stdlib = caml_secure_getenv(T("CAMLLIB")); +- if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR; ++ if (stdlib == NULL && is_directory(OCAML_STDLIB_DIR) == 1) ++ stdlib = OCAML_STDLIB_DIR; ++ ++ if (stdlib == NULL) { ++ exe = caml_executable_name(); ++ bindir = dirname_os(exe); ++ ++ stdlib = caml_stat_strconcat_os(7, ++ bindir, T("/"), "..", T("/"), "lib", T("/"), "ocaml"); ++ ++ caml_stat_free(exe); ++ } ++ + return stdlib; + } + ++int starts_with(const char_os *str, const char_os * pre) ++{ ++ return strncmp_os(pre, str, strlen_os(pre)) == 0; ++} ++ + CAMLexport char_os * caml_parse_ld_conf(void) + { + const char_os * stdlib; +- char_os * ldconfname, * wconfig, * p, * q; ++ char_os * ldconfname, * wconfig, * tail, * replaced, * p, * q; + char * config; + #ifdef _WIN32 + struct _stati64 st; +@@ -127,7 +170,14 @@ CAMLexport char_os * caml_parse_ld_conf(void) + for (p = wconfig; *p != 0; p++) { + if (*p == '\n') { + *p = 0; +- caml_ext_table_add(&caml_shared_libs_path, q); ++ if (starts_with(q, OCAML_STDLIB_DIR)) { ++ // replace 'OCAML_STDLIB_DIR' with 'stdlib' ++ tail = q + strlen_os(OCAML_STDLIB_DIR); ++ replaced = caml_stat_strconcat_os(2, stdlib, tail); ++ caml_ext_table_add(&caml_shared_libs_path, replaced); ++ } else { ++ caml_ext_table_add(&caml_shared_libs_path, q); ++ } + q = p + 1; + } + } +diff --git a/utils/config.common.ml.in b/utils/config.common.ml.in +index 0f956d2fbc..d21f9becc1 100644 +--- a/utils/config.common.ml.in ++++ b/utils/config.common.ml.in +@@ -20,6 +20,20 @@ + (* The main OCaml version string has moved to ../build-aux/ocaml_version.m4 *) + let version = Sys.ocaml_version + ++let bindir = ++ let relative_path = Filename.dirname Sys.executable_name in ++ try ++ if Sys.is_directory bindir_default then ++ bindir_default ++ else ++ relative_path ++ with Sys_error(_) -> ++ relative_path ++ ++let standard_library_relative = ++ let dir_sep = Filename.dir_sep in ++ ".." ^ dir_sep ^ "lib" ^ dir_sep ^ "ocaml" ++ + let standard_library = + try + Sys.getenv "OCAMLLIB" +@@ -27,7 +41,17 @@ let standard_library = + try + Sys.getenv "CAMLLIB" + with Not_found -> +- standard_library_default ++ let dirname = Filename.dirname ++ and dir_sep = Filename.dir_sep ++ and executable_name = Sys.executable_name in ++ let relative_path = (dirname executable_name) ^ dir_sep ^ standard_library_relative in ++ try ++ if Sys.is_directory standard_library_default then ++ standard_library_default ++ else ++ relative_path ++ with Sys_error(_) -> ++ relative_path + + let exec_magic_number = {magic|@EXEC_MAGIC_NUMBER@|magic} + (* exec_magic_number is duplicated in runtime/caml/exec.h *) +@@ -74,6 +98,7 @@ let configuration_variables () = + [ + p "version" version; + p "standard_library_default" standard_library_default; ++ p "standard_library_relative" standard_library_relative; + p "standard_library" standard_library; + p "ccomp_type" ccomp_type; + p "c_compiler" c_compiler; +diff --git a/utils/config.fixed.ml b/utils/config.fixed.ml +index a334b1d76f..5e42ce990d 100644 +--- a/utils/config.fixed.ml ++++ b/utils/config.fixed.ml +@@ -20,7 +20,7 @@ + + let boot_cannot_call s = "/ The boot compiler should not call " ^ s + +-let bindir = "/tmp" ++let bindir_default = "/tmp" + let standard_library_default = "/tmp" + let ccomp_type = "n/a" + let c_compiler = boot_cannot_call "the C compiler" +diff --git a/utils/config.generated.ml.in b/utils/config.generated.ml.in +index e5e1b15d31..ff8a9a4513 100644 +--- a/utils/config.generated.ml.in ++++ b/utils/config.generated.ml.in +@@ -18,7 +18,7 @@ + (* This file is included in config_main.ml during the build rather + than compiled on its own *) + +-let bindir = {@QS@|@ocaml_bindir@|@QS@} ++let bindir_default = {@QS@|@ocaml_bindir@|@QS@} + + let standard_library_default = {@QS@|@ocaml_libdir@|@QS@} + +diff --git a/utils/config.mli b/utils/config.mli +index 3e61d6e66b..c1a90bd8f3 100644 +--- a/utils/config.mli ++++ b/utils/config.mli +@@ -26,6 +26,9 @@ val version: string + val bindir: string + (** The directory containing the binary programs *) + ++val bindir_default: string ++(** The directory containing the binary programs (at build-time) *) ++ + val standard_library: string + (** The directory containing the standard libraries *) + diff --git a/0_RootFS/OCaml/bundled/patches/00002-_Float16-version-guard.patch b/0_RootFS/OCaml/bundled/patches/00002-_Float16-version-guard.patch new file mode 100644 index 00000000000..c5649e2fd47 --- /dev/null +++ b/0_RootFS/OCaml/bundled/patches/00002-_Float16-version-guard.patch @@ -0,0 +1,21 @@ +commit a08e30cf5f3f156893fca360efc4dff22247ce09 +Author: Cody Tapscott +Date: Thu May 8 19:17:14 2025 -0400 + + Avoid using `_Float16` in older GCC + + This was not introduced until GCC 7, even for AArch64. + +diff --git a/runtime/bigarray.c b/runtime/bigarray.c +index bd3ce896eb..ec77a16c57 100644 +--- a/runtime/bigarray.c ++++ b/runtime/bigarray.c +@@ -37,7 +37,7 @@ + + /* Half-precision floating point numbers */ + +-#if defined(__GNUC__) && defined(__aarch64__) ++#if defined(__GNUC__) && defined(__aarch64__) && (__GNUC__ >= 7) + + union float16_bits { uint16_t i; _Float16 f; }; + diff --git a/0_RootFS/OCaml/bundled/patches/00003-old-clock_gettime-darwin.patch b/0_RootFS/OCaml/bundled/patches/00003-old-clock_gettime-darwin.patch new file mode 100644 index 00000000000..cbfa3e7e228 --- /dev/null +++ b/0_RootFS/OCaml/bundled/patches/00003-old-clock_gettime-darwin.patch @@ -0,0 +1,22 @@ +commit bb13d39852529bcc78292befdbb8bfbd20299942 +Author: Cody Tapscott +Date: Thu May 8 20:18:35 2025 -0400 + + Don't use `clock_gettime_nsec_np` on x86-64 macOS + + This was not introduced until Darwin 16, which is much newer than what + BinaryBuilder runs with by default. + +diff --git a/runtime/unix.c b/runtime/unix.c +index e58c77cf51..7201e037f3 100644 +--- a/runtime/unix.c ++++ b/runtime/unix.c +@@ -424,7 +424,7 @@ char *caml_secure_getenv (char const *var) + + uint64_t caml_time_counter(void) + { +-#if defined(HAS_CLOCK_GETTIME_NSEC_NP) ++#if defined(HAS_CLOCK_GETTIME_NSEC_NP) && !(defined(__APPLE__) && defined(__x86_64__)) + return (clock_gettime_nsec_np(CLOCK_UPTIME_RAW)); + #elif defined(HAS_POSIX_MONOTONIC_CLOCK) + struct timespec t; diff --git a/0_RootFS/OCaml/bundled/patches/00004-redundant-win32-define.patch b/0_RootFS/OCaml/bundled/patches/00004-redundant-win32-define.patch new file mode 100644 index 00000000000..6f1919c0663 --- /dev/null +++ b/0_RootFS/OCaml/bundled/patches/00004-redundant-win32-define.patch @@ -0,0 +1,51 @@ +commit 519375c631557f5c339b1312d2e2eedfdb7744e4 +Author: Cody Tapscott +Date: Thu May 8 20:43:18 2025 -0400 + + Guard `_WIN32_WINNT` definition + +diff --git a/ocamltest/run_win32.c b/ocamltest/run_win32.c +index 5f55206237..c04f9265ca 100644 +--- a/ocamltest/run_win32.c ++++ b/ocamltest/run_win32.c +@@ -16,7 +16,9 @@ + /* Run programs with redirections and timeouts under Windows */ + + /* GetTickCount64() requires Windows Vista or Server 2008 */ ++#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0600 ++#endif + + #include + #include +diff --git a/runtime/win32.c b/runtime/win32.c +index 8a5c8ff4b0..4f5a521fe7 100644 +--- a/runtime/win32.c ++++ b/runtime/win32.c +@@ -19,7 +19,9 @@ + + /* FILE_INFO_BY_HANDLE_CLASS, FILE_NAME_INFO, and INIT_ONCE are only + available from Windows Vista onwards */ ++#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0600 /* _WIN32_WINNT_VISTA */ ++#endif + + #define WIN32_LEAN_AND_MEAN + #define _CRT_RAND_S +diff --git a/yacc/wstr.c b/yacc/wstr.c +index 78c334e691..3ec9b751fb 100644 +--- a/yacc/wstr.c ++++ b/yacc/wstr.c +@@ -13,8 +13,12 @@ + /**************************************************************************/ + + /* Need at least Windows Vista for WC_ERR_INVALID_CHARS */ ++#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x600 ++#endif ++#ifndef WINVER + #define WINVER 0x600 ++#endif + #include + + /* See corresponding values in runtime/win32.c */ diff --git a/H/HelloWorldOCaml/build_tarballs.jl b/H/HelloWorldOCaml/build_tarballs.jl new file mode 100644 index 00000000000..0d2fb49e111 --- /dev/null +++ b/H/HelloWorldOCaml/build_tarballs.jl @@ -0,0 +1,41 @@ +using BinaryBuilder + +name = "HelloWorldOCaml" +version = v"1.0.0" + +# sources generated inline below +sources = [ +] + +# Bash recipe for building across all platforms +script = raw""" +mkdir -p ${prefix}/bin +echo 'let () = print_endline "hello world"' > hello.ml +ocamlopt -o ${prefix}/bin/hello_world${exeext} hello.ml +install_license /usr/share/licenses/MIT +""" + +# These are the platforms we will build for by default, unless further +# platforms are passed in on the command line +platforms = supported_platforms() + +# OCaml 5.0 dropped support for 32-bit targets +filter!(p -> !(arch(p) == "i686"), platforms) +filter!(p -> !(arch(p) == "armv6l"), platforms) +filter!(p -> !(arch(p) == "armv7l"), platforms) + +# Not yet supported by our OCaml toolchain +filter!(p -> !(Sys.isfreebsd(p)), platforms) + +# The products that we will ensure are always built +products = [ + ExecutableProduct("hello_world", :hello_world), +] + +# Dependencies that must be installed before this package can be built +dependencies = Dependency[ +] + +# Build the tarballs, and possibly a `build.jl` as well. +build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies; + compilers=[:c, :ocaml], julia_compat="1.6")