Skip to content

Commit

Permalink
Move here definition of Pkg.BinaryPlatforms.gcc_versions
Browse files Browse the repository at this point in the history
  • Loading branch information
giordano committed Jan 17, 2020
1 parent 7ca340a commit 3fb4dc5
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 25 deletions.
72 changes: 71 additions & 1 deletion src/Rootfs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ function select_gcc_version(p::Platform,
preferred_gcc_version::VersionNumber = 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)!")
Expand Down Expand Up @@ -583,6 +583,76 @@ function preferred_cxxstring_abi(platform::Platform, shard::CompilerShard)
end
end

"""
gcc_version(cabi::CompilerABI, GCC_versions::Vector{VersionNumber};
rounding_mode=:platform)
Returns the closest matching GCC version number for the given CompilerABI
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_versions::Vector{VersionNumber})
filt_gcc_majver(versions...) = filter(v -> v.major in versions, GCC_versions)

# First, filter by libgfortran version.
# libgfortran3 -> GCC 4.X, 5.X, 6.X
# libgfortran4 -> GCC 7.x
# libgfortran5 -> GCC 8.X, 9.X
if cabi.libgfortran_version !== nothing
if cabi.libgfortran_version.major == 3
GCC_versions = filt_gcc_majver(4,5,6)
elseif cabi.libgfortran_version.major == 4
GCC_versions = filt_gcc_majver(7)
elseif cabi.libgfortran_version.major == 5
GCC_versions = filt_gcc_majver(8, 9)
end
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.
if cabi.libstdcxx_version !== nothing
cxxvp = cabi.libstdcxx_version.patch
# Is this platform so old that nothing is supported?
if cxxvp < 19
return VersionNumber[]

# Is this platform in a nominal range?
elseif cxxvp < 27
# See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
# for the whole list, as well as many other interesting factoids.
mapping = Dict(
19 => v"4.8.5",
20 => v"4.9.0",
21 => v"5.1.0",
22 => v"6.1.0",
23 => v"7.1.0",
24 => v"7.2.0",
25 => v"8.0.0",
26 => v"9.0.0",
)
GCC_versions = filter(v -> v <= mapping[cxxvp], GCC_versions)

# The implicit `else` here is that no filtering occurs; this platform
# has such broad support that any C++ code compiled will run on it.
end
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_versions = filter(v -> v >= v"5", GCC_versions)
end

return GCC_versions
end

"""
download_all_shards(; verbose::Bool=false)
Expand Down
80 changes: 56 additions & 24 deletions test/basic.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
## Basic tests for simple utilities within BB
using BinaryBuilder, Test, Pkg
using BinaryBuilder: preferred_runner, resolve_jlls, CompilerShard, preferred_libgfortran_version, preferred_cxxstring_abi

using BinaryBuilder: preferred_runner, resolve_jlls, CompilerShard, preferred_libgfortran_version, preferred_cxxstring_abi, gcc_version

@testset "File Collection" begin
temp_prefix() do prefix
Expand Down Expand Up @@ -314,26 +313,59 @@ end
@testset "Rootfs" begin
@test_throws ErrorException CompilerShard("GCCBootstrap", v"4", Linux(:x86_64), :invalid_archive_type)

# Preferred libgfortran version and C++ string ABI
platform = FreeBSD(:x86_64)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"3"
@test preferred_cxxstring_abi(platform, shard) == :cxx03
shard = CompilerShard("GCCBootstrap", v"5.2.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"3"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("GCCBootstrap", v"7.10.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"4"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("GCCBootstrap", v"9.10.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"5"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("LLVMBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs)
@test_throws ErrorException preferred_libgfortran_version(platform, shard)
@test_throws ErrorException preferred_cxxstring_abi(platform, shard)
platform = Linux(:x86_64, libc=:musl)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = MacOS(:x86_64))
@test_throws ErrorException preferred_libgfortran_version(platform, shard)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = Linux(:x86_64, libc=:glibc))
@test_throws ErrorException preferred_cxxstring_abi(platform, shard)
@testset "GCC ABI matching" begin
# Preferred libgfortran version and C++ string ABI
platform = FreeBSD(:x86_64)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"3"
@test preferred_cxxstring_abi(platform, shard) == :cxx03
shard = CompilerShard("GCCBootstrap", v"5.2.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"3"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("GCCBootstrap", v"7.10.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"4"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("GCCBootstrap", v"9.10.0", Linux(:x86_64, libc=:musl), :squashfs, target = platform)
@test preferred_libgfortran_version(platform, shard) == v"5"
@test preferred_cxxstring_abi(platform, shard) == :cxx11
shard = CompilerShard("LLVMBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs)
@test_throws ErrorException preferred_libgfortran_version(platform, shard)
@test_throws ErrorException preferred_cxxstring_abi(platform, shard)
platform = Linux(:x86_64, libc=:musl)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = MacOS(:x86_64))
@test_throws ErrorException preferred_libgfortran_version(platform, shard)
shard = CompilerShard("GCCBootstrap", v"4.8.5", Linux(:x86_64, libc=:musl), :squashfs, target = Linux(:x86_64, libc=:glibc))
@test_throws ErrorException preferred_cxxstring_abi(platform, shard)

# Explicitly test our `gcc_version()` helper function
GCC_versions = [
v"4.8.5",
v"5.4.0",
v"6.3.0",
v"7.1.0",
v"7.2.0",
v"8.0.0",
]

# With no constraints, we should get them all back
@test gcc_version(CompilerABI(), GCC_versions) == GCC_versions

# libgfortran v3 and libstdcxx 20 restrict us to only v4 and v5
cabi = CompilerABI(;libgfortran_version=v"3", libstdcxx_version=v"3.4.22")
@test gcc_version(cabi, GCC_versions) == [v"4.8.5", v"5.4.0"]

# Adding `:cxx11` eliminates `v"4.X"`:
cabi = CompilerABI(cabi; cxxstring_abi=:cxx11)
@test gcc_version(cabi, GCC_versions) == [v"5.4.0"]

# Just libgfortran v3 allows GCC 6 as well though
cabi = CompilerABI(;libgfortran_version=v"3")
@test gcc_version(cabi, GCC_versions) == [v"4.8.5", v"5.4.0", v"6.3.0"]

# Test libgfortran version v4, then splitting on libstdcxx_version:
cabi = CompilerABI(;libgfortran_version=v"4")
@test gcc_version(cabi, GCC_versions) == [v"7.1.0", v"7.2.0"]
cabi = CompilerABI(cabi; libstdcxx_version=v"3.4.23")
@test gcc_version(cabi, GCC_versions) == [v"7.1.0"]
end
end

0 comments on commit 3fb4dc5

Please sign in to comment.