-
Notifications
You must be signed in to change notification settings - Fork 101
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
Setup dependencies that match the GCC ABI of the compiler #604
Changes from all commits
360e9f0
7fcf299
7ca340a
3fb4dc5
32ae74f
68a43fd
213ffd1
18a40fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -319,15 +319,78 @@ function select_closest_version(preferred::VersionNumber, versions::Vector{Versi | |
return versions[closest_idx] | ||
end | ||
|
||
const available_gcc_builds = [v"4.8.5", v"5.2.0", v"6.1.0", v"7.1.0", v"8.1.0", v"9.1.0"] | ||
const available_llvm_builds = [v"6.0.1", v"7.1.0", v"8.0.1", v"9.0.1"] | ||
abstract type CompilerBuild end | ||
|
||
struct GCCBuild <: CompilerBuild | ||
version::VersionNumber | ||
abi::CompilerABI | ||
end | ||
GCCBuild(v::VersionNumber) = GCCBuild(v, CompilerABI()) | ||
|
||
struct LLVMBuild <: CompilerBuild | ||
version::VersionNumber | ||
abi::CompilerABI | ||
end | ||
LLVMBuild(v::VersionNumber) = LLVMBuild(v, CompilerABI()) | ||
|
||
getversion(c::CompilerBuild) = c.version | ||
getabi(c::CompilerBuild) = c.abi | ||
|
||
const available_gcc_builds = [GCCBuild(v"4.8.5", CompilerABI(libgfortran_version = v"3", libstdcxx_version = v"3.4.19", cxxstring_abi = :cxx03)), | ||
GCCBuild(v"5.2.0", CompilerABI(libgfortran_version = v"3", libstdcxx_version = v"3.4.21", cxxstring_abi = :cxx11)), | ||
GCCBuild(v"6.1.0", CompilerABI(libgfortran_version = v"3", libstdcxx_version = v"3.4.22", cxxstring_abi = :cxx11)), | ||
GCCBuild(v"7.1.0", CompilerABI(libgfortran_version = v"4", libstdcxx_version = v"3.4.23", cxxstring_abi = :cxx11)), | ||
GCCBuild(v"8.1.0", CompilerABI(libgfortran_version = v"5", libstdcxx_version = v"3.4.25", cxxstring_abi = :cxx11)), | ||
GCCBuild(v"9.1.0", CompilerABI(libgfortran_version = v"5", libstdcxx_version = v"3.4.26", cxxstring_abi = :cxx11))] | ||
const available_llvm_builds = [LLVMBuild(v"6.0.1"), | ||
LLVMBuild(v"7.1.0"), | ||
LLVMBuild(v"8.0.1"), | ||
LLVMBuild(v"9.0.1")] | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see us eventually adding |
||
""" | ||
gcc_version(cabi::CompilerABI, GCC_builds::Vector{GCCBuild}) | ||
|
||
Returns the closest matching GCC version number for the given CompilerABI | ||
giordano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
representing a particular platofrm, from the given set of options. If no match | ||
is found, returns an empty list. This method assumes that `cabi` represents a | ||
platform that binaries will be run on, and thus versions are always rounded | ||
down; e.g. if the platform supports a `libstdc++` version that corresponds to | ||
`GCC 5.1.0`, but the only GCC versions available to be picked from are `4.8.5` | ||
and `5.2.0`, it will return `4.8.5`, as binaries compiled with that version | ||
will run on this platform, whereas binaries compiled with `5.2.0` may not. | ||
""" | ||
function gcc_version(cabi::CompilerABI, GCC_builds::Vector{GCCBuild}) | ||
# First, filter by libgfortran version. | ||
if cabi.libgfortran_version !== nothing | ||
GCC_builds = filter(b -> getabi(b).libgfortran_version == cabi.libgfortran_version, 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 cabi.libstdcxx_version !== nothing | ||
GCC_builds = filter(b -> getabi(b).libstdcxx_version <= cabi.libstdcxx_version, 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 cabi.cxxstring_abi !== nothing && cabi.cxxstring_abi === :cxx11 | ||
GCC_builds = filter(b -> getversion(b) >= v"5", GCC_builds) | ||
end | ||
|
||
return getversion.(GCC_builds) | ||
end | ||
|
||
function select_gcc_version(p::Platform, | ||
GCC_builds::Vector{VersionNumber} = available_gcc_builds, | ||
preferred_gcc_version::VersionNumber = GCC_builds[1], | ||
GCC_builds::Vector{GCCBuild} = available_gcc_builds, | ||
preferred_gcc_version::VersionNumber = getversion(GCC_builds[1]), | ||
) | ||
# Determine which GCC build we're going to match with this CompilerABI: | ||
GCC_builds = Pkg.BinaryPlatforms.gcc_version(compiler_abi(p), GCC_builds) | ||
GCC_builds = gcc_version(compiler_abi(p), GCC_builds) | ||
|
||
if isempty(GCC_builds) | ||
error("Impossible CompilerABI constraints $(cabi)!") | ||
|
@@ -350,19 +413,22 @@ function choose_shards(p::Platform; | |
compilers::Vector{Symbol} = [:c], | ||
rootfs_build::VersionNumber=v"2020.01.07", | ||
ps_build::VersionNumber=v"2020.01.15", | ||
GCC_builds::Vector{VersionNumber}=available_gcc_builds, | ||
LLVM_builds::Vector{VersionNumber}=available_llvm_builds, | ||
GCC_builds::Vector{GCCBuild}=available_gcc_builds, | ||
LLVM_builds::Vector{LLVMBuild}=available_llvm_builds, | ||
Rust_build::VersionNumber=v"1.18.3", | ||
Go_build::VersionNumber=v"1.13", | ||
archive_type::Symbol = (use_squashfs ? :squashfs : :unpacked), | ||
bootstrap_list::Vector{Symbol} = bootstrap_list, | ||
# We prefer the oldest GCC version by default | ||
preferred_gcc_version::VersionNumber = GCC_builds[1], | ||
preferred_llvm_version::VersionNumber = LLVM_builds[end], | ||
# Because GCC has lots of compatibility issues, we always default to | ||
# the earliest version possible. | ||
preferred_gcc_version::VersionNumber = getversion(GCC_builds[1]), | ||
# Because LLVM doesn't have compatibilty issues, we always default | ||
# to the newest version possible. | ||
preferred_llvm_version::VersionNumber = getversion(LLVM_builds[end]), | ||
giordano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
GCC_build = select_gcc_version(p, GCC_builds, preferred_gcc_version) | ||
LLVM_build = select_closest_version(preferred_llvm_version, LLVM_builds) | ||
LLVM_build = select_closest_version(preferred_llvm_version, getversion.(LLVM_builds)) | ||
# Our host platform is x86_64-linux-musl | ||
host_platform = Linux(:x86_64; libc=:musl) | ||
|
||
|
@@ -531,6 +597,58 @@ function expand_cxxstring_abis(ps::Vector{<:Platform}) | |
return Platform[p for p in Iterators.flatten(expand_cxxstring_abis.(ps))] | ||
end | ||
|
||
""" | ||
preferred_libgfortran_version(platform::Platform, shard::CompilerShard) | ||
|
||
Return the libgfortran version preferred by the given platform or GCCBootstrap shard. | ||
""" | ||
function preferred_libgfortran_version(platform::Platform, shard::CompilerShard) | ||
# Some input validation | ||
if shard.name != "GCCBootstrap" | ||
error("Shard must be `GCCBootstrap`") | ||
end | ||
if shard.target.arch != platform.arch || shard.target.libc != platform.libc | ||
error("Incompatible platform and shard target") | ||
end | ||
|
||
if compiler_abi(platform).libgfortran_version != nothing | ||
# Here we can't use `shard.target` because the shard always has the | ||
# target as ABI-agnostic, thus we have also to ask for the platform. | ||
return compiler_abi(platform).libgfortran_version | ||
elseif shard.version < v"7" | ||
giordano marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return v"3" | ||
elseif v"7" <= shard.version < v"8" | ||
return v"4" | ||
else | ||
return v"5" | ||
end | ||
end | ||
|
||
""" | ||
preferred_cxxstring_abi(platform::Platform, shard::CompilerShard) | ||
|
||
Return the C++ string ABI preferred by the given platform or GCCBootstrap shard. | ||
""" | ||
function preferred_cxxstring_abi(platform::Platform, shard::CompilerShard) | ||
# Some input validation | ||
if shard.name != "GCCBootstrap" | ||
error("Shard must be `GCCBootstrap`") | ||
end | ||
if shard.target.arch != platform.arch || shard.target.libc != platform.libc | ||
error("Incompatible platform and shard target") | ||
end | ||
|
||
if compiler_abi(platform).cxxstring_abi != nothing | ||
# Here we can't use `shard.target` because the shard always has the | ||
# target as ABI-agnostic, thus we have also to ask for the platform. | ||
return compiler_abi(platform).cxxstring_abi | ||
elseif shard.version < v"5" | ||
return :cxx03 | ||
else | ||
return :cxx11 | ||
end | ||
end | ||
|
||
""" | ||
download_all_shards(; verbose::Bool=false) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ function UserNSRunner(workspace_root::String; | |
verbose::Bool = false, | ||
compiler_wrapper_path::String = mktempdir(), | ||
src_name::AbstractString = "", | ||
shards = nothing, | ||
kwargs...) | ||
global use_ccache, use_squashfs, runner_override | ||
|
||
|
@@ -55,8 +56,10 @@ function UserNSRunner(workspace_root::String; | |
push!(workspaces, ccache_dir() => "/root/.ccache") | ||
end | ||
|
||
# Choose the shards we're going to mount | ||
shards = choose_shards(platform; extract_kwargs(kwargs, (:preferred_gcc_version,:preferred_llvm_version,:bootstrap_list,:compilers))...) | ||
if isnothing(shards) | ||
# Choose the shards we're going to mount | ||
shards = choose_shards(platform; extract_kwargs(kwargs, (:preferred_gcc_version,:preferred_llvm_version,:bootstrap_list,:compilers))...) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here; let's try moving this initialization into the kwargs specification above. |
||
|
||
# Construct sandbox command to look at the location it'll be mounted under | ||
mpath = mount_path(shards[1], workspace_root) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move this into the
kwarg
initialization above? I'd rather avoid the "default value ofnothing
means initialize it halfway through the method" pattern if we can, and I don't think there's a hidden reason whychoose_shards()
must be run after the stuff above it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't know
kwargs
when we initialiseshards
, do we?