Skip to content

Implement preliminary OCaml support #425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jul 7, 2025
Merged

Implement preliminary OCaml support #425

merged 18 commits into from
Jul 7, 2025

Conversation

topolarity
Copy link
Contributor

This is a preliminary implementation of OCaml compiler support in BinaryBuilder.

Dependent on JuliaPackaging/Yggdrasil#11146

@topolarity topolarity force-pushed the ct/ocaml-runner branch 5 times, most recently from 26cc6c5 to 3acfe1b Compare May 10, 2025 21:54
@topolarity
Copy link
Contributor Author

topolarity commented May 10, 2025

This looks to be almost working. There is some slight disagreement about darwinX in the target triples:

sandbox:${WORKSPACE}/srcdir # /opt/aarch64-apple-darwin/bin/ocamlopt.opt -v
The OCaml native-code compiler, version 5.4.0+dev2-2025-04-22
Standard library directory: /opt/aarch64-apple-darwin/bin/../lib/ocaml
sandbox:${WORKSPACE}/srcdir # ocamlopt.opt -v
/opt/bin/aarch64-apple-darwin20-libgfortran5-cxx11/ocamlopt.opt: line 5: /opt/aarch64-apple-darwin20/bin/ocamlopt.opt: No such file or directory

Any preference for how to resolve that?

@maleadt
Copy link
Member

maleadt commented Jun 27, 2025

/opt/x86_64-linux-gnu/bin/../lib/gcc/x86_64-linux-gnu/5.2.0/../../../../x86_64-linux-gnu/bin/ld: /opt/x86_64-linux-gnu/bin/../lib/ocaml/stdlib.a(camlinternalFormatBasics.o): unrecognized relocation (0x2a) in section `.text.caml.camlCamlinternalFormatBasics$entry'
/opt/x86_64-linux-gnu/bin/../lib/gcc/x86_64-linux-gnu/5.2.0/../../../../x86_64-linux-gnu/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

I guess this is because of using GCC 6 for building the shards (technically, OCaml only needs GCC 4.9+, but opam, one of the build tools I added to the shard, only builds on GCC 6 or later).

@maleadt maleadt marked this pull request as draft June 27, 2025 16:30
@maleadt maleadt self-assigned this Jun 27, 2025
@maleadt maleadt force-pushed the ct/ocaml-runner branch from dd55a0a to dd70539 Compare July 4, 2025 13:09
@maleadt maleadt added the enhancement New feature or request label Jul 4, 2025
@maleadt
Copy link
Member

maleadt commented Jul 4, 2025

Okay, this should be the first in the OCaml series (also including JuliaPackaging/BinaryBuilder.jl#1382 and JuliaPackaging/Yggdrasil#11146) that's ready for review, merge and tag. It's all fairly straightforward, only involving OCaml, with the exception of two broadly-impacting changes:

  • preferred_gcc_version now defaults to nothing, indicating unspecifiedness, which I use to bump it from the default 4.8 to 6 when OCaml is requested. This because the OCaml compiler shards themselves are built using GCC v6.
  • symlinks to wrappers are now also provided for host platform binaries, making it possible to switch to the host toolchain by doing PATH=/opt/bin/$host_full:/opt/$host/bin:$PATH. Before, there was no easy way to e.g. get a as that mapped to x86_64-linux-musl-as, which was problematic for my ocamlopt-based recipe that simply executes as.

@maleadt maleadt marked this pull request as ready for review July 4, 2025 13:17
@maleadt maleadt requested a review from giordano July 4, 2025 13:17
Comment on lines +613 to +615
# The preferred GCC version depends on the compilers we are using.
if preferred_gcc_version === nothing
preferred_gcc_version = if :ocaml in compilers
Copy link
Member

Choose a reason for hiding this comment

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

So, I think this is ok, but I wanted to point out that we already do some shenanigans in gcc_version at

function gcc_version(p::AbstractPlatform,
GCC_builds::Vector{GCCBuild},
compilers::Vector{Symbol}=[:c];
llvm_version::Union{Nothing,VersionNumber}=nothing)
# First, filter by libgfortran version.
if libgfortran_version(p) !== nothing
GCC_builds = filter(b -> getabi(b).libgfortran_version == libgfortran_version(p), GCC_builds)
end
# Next, filter by libstdc++ GLIBCXX symbol version. Note that this
# mapping is conservative; it is often the case that we return a
# version that is slightly lower than what is actually installed on
# a system. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
# for the whole list, as well as many other interesting factoids.
if libstdcxx_version(p) !== nothing
GCC_builds = filter(b -> getabi(b).libstdcxx_version <= libstdcxx_version(p), GCC_builds)
end
# Finally, enforce cxxstring_abi guidelines. It is possible to build
# :cxx03 binaries on GCC 5+, (although increasingly rare) so the only
# filtering we do is that if the platform is explicitly :cxx11, we
# disallow running on < GCC 5.
if cxxstring_abi(p) === "cxx11"
GCC_builds = filter(b -> getversion(b) >= v"5", GCC_builds)
end
# LLVMBootstrap 12 needs to be built with GCCBootstrap ≥ 7, see
# <https://github.com/JuliaPackaging/BinaryBuilderBase.jl/pull/112#issuecomment-776940748>.
# However, when building for FreeBSD with LLVMBootstrap 12 we can't use `ld` from
# binutils < 2.26 (which corresponds to GCCBootstrap < 6) to link some object files, see
# <https://github.com/JuliaPackaging/BinaryBuilderBase.jl/issues/158>. The solution is
# to not allow old GCCBootstrap with new versions of LLVMBootstrap for FreeBSD.
if llvm_version !== nothing && Sys.isfreebsd(p) && llvm_version v"12"
GCC_builds = filter(b -> getversion(b) v"6", GCC_builds)
end
# We don't have GCC 8 or older for FreeBSD 14.1+ on AArch64
if Sys.isfreebsd(p) && arch(p) == "aarch64"
GCC_builds = filter(b -> getversion(b) v"9", GCC_builds)
end
# We only use GCC 14 or newer for riscv64.
if arch(p) == "riscv64"
GCC_builds = filter(b -> getversion(b) v"14", GCC_builds)
end
# Rust on Windows requires binutils 2.25 (it invokes `ld` with `--high-entropy-va`),
# which we bundle with GCC 5.
# Rust requires glibc 2.17 (https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html),
# which we only use for GCC >5
if :rust in compilers
GCC_builds = filter(b -> getversion(b) v"5", GCC_builds)
end
# Msan uses clang, which emits R_X86_64_REX_GOTPCRELX, and thus requires
# binutils >= 2.26.
if sanitize(p) in ("memory", "memory_origins", "address")
GCC_builds = filter(b -> getversion(b) v"6", GCC_builds)
end
# Filter the possible GCC versions depending on the microarchitecture
if march(p) in ("avx", "avx2", "neonvfpv4")
# "sandybridge", "haswell", "cortex-a53" introduced in GCC v4.9.0:
# https://www.gnu.org/software/gcc/gcc-4.9/changes.html
GCC_builds = filter(b -> getversion(b) >= v"4.9", GCC_builds)
elseif march(p) in ("power9",)
# "power9" introduced in GCC v6.1:
# https://www.gnu.org/software/gcc/gcc-6/changes.html
GCC_builds = filter(b -> getversion(b) >= v"6.1", GCC_builds)
elseif march(p) in ("avx512", "armv8_1")
# "thunderx2t99" introduced in GCC v7.1:
# <https://www.gnu.org/software/gcc/gcc-7/changes.html>.
# "skylake-avx512" introduced in GCC v6.1, but header files were broken
# in that release:
# <https://github.com/JuliaPackaging/Yggdrasil/pull/4485#issuecomment-1048226993>
# <https://github.com/JuliaPackaging/Yggdrasil/pull/6392#discussion_r1138808437>.
GCC_builds = filter(b -> getversion(b) >= v"7.1", GCC_builds)
elseif march(p) in ("armv8_2_crypto",)
# `cortex-a76` target introduced in GCC v9.1:
# https://www.gnu.org/software/gcc/gcc-9/changes.html
GCC_builds = filter(b -> getversion(b) >= v"9.1", GCC_builds)
elseif march(p) in ("a64fx",)
# `a64fx` target introduced in GCC v10.3:
# https://www.gnu.org/software/gcc/gcc-10/changes.html
GCC_builds = filter(b -> getversion(b) >= v"10.3", GCC_builds)
elseif march(p) in ("apple_m1",)
# At the moment we can only target this CPU with GCC 12
GCC_builds = filter(b -> getversion(b) >= v"12", GCC_builds)
end
return getversion.(GCC_builds)
end
for example in certain cases we change the version of the gcc toolchain based on the...llvm toolchain. I was never proud of that mess though.

@maleadt
Copy link
Member

maleadt commented Jul 7, 2025

Let's merge this once CI is tagged. IIUC I also have to do a version bump, since BinaryBuilder.jl doesn't contain a committed Manifest (and we want JuliaPackaging/BinaryBuilder.jl#1382 to actually test OCaml support).

@maleadt maleadt merged commit eea82df into master Jul 7, 2025
8 checks passed
@maleadt maleadt deleted the ct/ocaml-runner branch July 7, 2025 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants