Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make sure the compiler wrappers have the requested C++ string ABI
Browse files Browse the repository at this point in the history
giordano committed Jan 18, 2020
1 parent 213ffd1 commit f6bcbb4
Showing 2 changed files with 84 additions and 5 deletions.
37 changes: 33 additions & 4 deletions src/Runner.jl
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ exeext(p::Union{Linux,FreeBSD,MacOS}) = ""
exeext(p::Platform) = error("Unknown exeext for platform $(p)")

"""
generate_compiler_wrappers(p::Platform, bin_path::AbstractString)
generate_compiler_wrappers!(p::Platform, bin_path::AbstractString)
We generate a set of compiler wrapper scripts within our build environment to force all
build systems to honor the necessary sets of compiler flags to build for our systems.
@@ -61,6 +61,32 @@ function generate_compiler_wrappers!(platform::Platform; bin_path::AbstractStrin
host_target = aatriplet(host_platform)
rust_target = aatriplet(rust_platform)


# If the ABI-agnostic triplets of the target and the host platform are the
# same, then we have to be very careful: we can't have distinct wrappers, so
# we have to be sure that their ABIs are consistent, in particular that
# we're correctly writing the wrappers for the target platform. In
# particular, what we care about with regard to the wrappers is the C++
# string ABI. We have the following situations:
# * they are equal: this is fine
# * they're different and the host has a prefernce for the C++ string ABI:
# we can't deal with this situation as the host wrappers will be always
# overwritten, then error out
# * in all other cases we don't do anything here but later below we'll let
# the host wrappers to be overwritten by the wrappers for the target
if target == host_target
target_cxxabi = compiler_abi(platform).cxxstring_abi
host_cxxabi = compiler_abi(host_platform).cxxstring_abi
if target_cxxabi !== host_cxxabi
if host_cxxabi !== nothing
# This is a very unlikely situation as ideally the host
# shouldn't have particular preferences for the ABI, thus in
# practice we shouldn't never reach this.
error("Incompatible C++ string ABIs between the host and target platforms")
end
end
end

# If we should use ccache, prepend this to every compiler invocation
ccache = use_ccache ? "ccache" : ""

@@ -73,7 +99,7 @@ function generate_compiler_wrappers!(platform::Platform; bin_path::AbstractStrin
unsafe_flags = String[])
write(io, """
#!/bin/bash
# This compiler wrapper script brought into existence by `generate_compiler_wrappers()`
# This compiler wrapper script brought into existence by `generate_compiler_wrappers!()`
if [ "x\${SUPER_VERBOSE}" = "x" ]; then
vrun() { "\$@"; }
@@ -308,8 +334,11 @@ function generate_compiler_wrappers!(platform::Platform; bin_path::AbstractStrin
chmod(joinpath(bin_path, fname), 0o775)
end

## Generate compiler wrappers for both our target and our host
for p in unique((platform, host_platform))
## Generate compiler wrappers for both our host and our target. In
## particular, we write the wrapper for the target after those for the host,
## to override host-specific ABI in case this is incompatible with that of
## the target
for p in unique((host_platform, platform))
t = aatriplet(p)

# Generate `:c` compilers
52 changes: 51 additions & 1 deletion test/basic.jl
Original file line number Diff line number Diff line change
@@ -1,6 +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, gcc_version, available_gcc_builds, getversion
using BinaryBuilder: preferred_runner, resolve_jlls, CompilerShard, preferred_libgfortran_version, preferred_cxxstring_abi, gcc_version, available_gcc_builds, getversion, generate_compiler_wrappers!

@testset "File Collection" begin
temp_prefix() do prefix
@@ -358,4 +358,54 @@ end
cabi = CompilerABI(cabi; libstdcxx_version=v"3.4.23")
@test gcc_version(cabi, available_gcc_builds) == [v"7.1.0"]
end

@testset "Compiler wrappers" begin
platform = Linux(:x86_64, libc=:musl)
mktempdir() do bin_path
generate_compiler_wrappers!(platform; bin_path = bin_path)
# Make sure the C++ string ABI is not set
@test !occursin("-D_GLIBCXX_USE_CXX11_ABI", read(joinpath(bin_path, "gcc"), String))
# Make sure gfortran doesn't uses ccache when BinaryBuilder.use_ccache is true
BinaryBuilder.use_ccache && @test !occursin("ccache", read(joinpath(bin_path, "gfortran"), String))
end
platform = Linux(:x86_64, libc=:musl, compiler_abi=CompilerABI(cxxstring_abi=:cxx03))
mktempdir() do bin_path
generate_compiler_wrappers!(platform; bin_path = bin_path)
gcc = read(joinpath(bin_path, "gcc"), String)
# Make sure the C++ string ABI is set as expected
@test occursin("-D_GLIBCXX_USE_CXX11_ABI=0", gcc)
# Make sure the unsafe flags check is there
@test occursin("You used one or more of the unsafe flags", gcc)
end
platform = Linux(:x86_64, libc=:musl, compiler_abi=CompilerABI(cxxstring_abi=:cxx11))
mktempdir() do bin_path
generate_compiler_wrappers!(platform; bin_path = bin_path, allow_unsafe_flags = true)
gcc = read(joinpath(bin_path, "gcc"), String)
# Make sure the C++ string ABI is set as expected
@test occursin("-D_GLIBCXX_USE_CXX11_ABI=1", gcc)
# Make sure the unsafe flags check is not there in this case
@test !occursin("You used one or more of the unsafe flags", gcc)
end
platform = FreeBSD(:x86_64)
mktempdir() do bin_path
generate_compiler_wrappers!(platform; bin_path = bin_path, compilers = [:c, :rust, :go])
clang = read(joinpath(bin_path, "clang"), String)
# Check link flags
@test occursin("-L/opt/$(triplet(platform))/$(triplet(platform))/lib", clang)
@test occursin("fuse-ld=$(triplet(platform))", clang)
# Other compilers
@test occursin("GOOS=\"freebsd\"", read(joinpath(bin_path, "go"), String))
@test occursin("--target=x86_64-unknown-freebsd", read(joinpath(bin_path, "rustc"), String))
end
platform = Linux(:x86_64, libc=:musl, compiler_abi=CompilerABI(cxxstring_abi=:cxx03))
host_platform = Linux(:x86_64, libc=:musl, compiler_abi=CompilerABI(cxxstring_abi=:cxx11))
mktempdir() do bin_path
@test_throws ErrorException generate_compiler_wrappers!(platform; bin_path = bin_path, host_platform = host_platform)
end
platform = Linux(:x86_64, libc=:musl)
host_platform = Linux(:x86_64, libc=:musl, compiler_abi=CompilerABI(cxxstring_abi=:cxx03))
mktempdir() do bin_path
@test_throws ErrorException generate_compiler_wrappers!(platform; bin_path = bin_path, host_platform = host_platform)
end
end
end

0 comments on commit f6bcbb4

Please sign in to comment.