Skip to content

Add creation of the build-id to the linker flags #435

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 6 commits into from
Aug 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "BinaryBuilderBase"
uuid = "7f725544-6523-48cd-82d1-3fa08ff4056e"
authors = ["Elliot Saba <[email protected]>"]
version = "1.39.1"
version = "1.40.0"

[deps]
Bzip2_jll = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
Expand Down
15 changes: 15 additions & 0 deletions src/Runner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,17 @@ function generate_compiler_wrappers!(platform::AbstractPlatform; bin_path::Abstr
end
end

function buildid_link_flags!(p::AbstractPlatform, flags::Vector{String})
# build-id is not supported on macOS compilers
if !Sys.isapple(p)
# Windows build-id requires binutils 2.25+, which we only have for GCC 5+
if !Sys.iswindows(p) || (Sys.iswindows(p) && gcc_version ≥ v"5")
# Use a known algorithm to embed the build-id for reproducibility
push!(flags, "-Wl,--build-id=sha1")
end
end
end

function clang_compile_flags!(p::AbstractPlatform, flags::Vector{String} = String[])
if lock_microarchitecture
append!(flags, get_march_flags(arch(p), march(p), "clang"))
Expand Down Expand Up @@ -540,6 +551,9 @@ function generate_compiler_wrappers!(platform::AbstractPlatform; bin_path::Abstr
append!(flags, min_macos_version_linker_flags())
end
end

buildid_link_flags!(p, flags)

return flags
end

Expand Down Expand Up @@ -630,6 +644,7 @@ function generate_compiler_wrappers!(platform::AbstractPlatform; bin_path::Abstr
push!(flags, "-Wl,--no-insert-timestamp")
end
sanitize_link_flags!(p, flags)
buildid_link_flags!(p, flags)
return flags
end

Expand Down
79 changes: 79 additions & 0 deletions test/runners.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Test
using BinaryBuilderBase
using BinaryBuilderBase: platform_dlext, platform_exeext, prefer_clang
using Pkg
using ObjectFile

@testset "Wrappers utilities" begin
@test nbits(Platform("i686", "linux")) == 32
Expand Down Expand Up @@ -130,8 +131,12 @@ end
if lowercase(get(ENV, "BINARYBUILDER_FULL_SHARD_TEST", "false")) == "true"
@info("Beginning full shard test... (this can take a while)")
platforms = supported_platforms()
elf_platforms = filter(p -> Sys.islinux(p) || Sys.isfreebsd(p), supported_platforms())
win_platforms = filter(p -> Sys.iswindows(p), supported_platforms())
else
platforms = (default_host_platform,)
elf_platforms = (default_host_platform,)
win_platforms = (Platform("x86_64", "windows"),)
end

# Checks that the wrappers provide the correct C++ string ABI
Expand All @@ -153,6 +158,80 @@ end
end
end

# Checks that the compiler/linker include a build-id
# This is only available on ELF-based platforms
@testset "Compilation - Linux build-id note $(platform) - $(compiler)" for platform in elf_platforms, compiler in ("cc", "gcc", "clang", "c++", "g++", "clang++")
mktempdir() do dir
ur = preferred_runner()(dir; platform=platform)
iobuff = IOBuffer()
test_c = """
#include <stdlib.h>
int test(void) {
return 0;
}
"""
test_script = """
set -e
cd /workspace
# Make sure setting `CCACHE` doesn't affect the compiler wrappers.
export CCACHE=pwned
export USE_CCACHE=false
echo '$(test_c)' > test.c
# Build shared library
$(compiler) -shared test.c -o libtest.\${dlext}
"""
cmd = `/bin/bash -c "$(test_script)"`
@test run(ur, cmd, iobuff)

# Load the library file and test it for the build-id
lib_path = joinpath(dir, "libtest."*platform_dlext(platform))
lib = open(lib_path)
obj_handles = readmeta(lib)
obj = first(obj_handles)
secs = Sections(obj)

# The section must exist for the build-id to be present
@test !isnothing(findfirst(s -> section_name(s) == ".note.gnu.build-id", secs))
end
end

# Checks that Windows can include a build-id
@testset "Compilation - Windows build-id note $(platform) - $(compiler)" for platform in win_platforms, compiler in ("cc", "gcc", "clang", "c++", "g++", "clang++")
mktempdir() do dir
# Windows build-id support requires binutils 2.25, which is part of our GCC 5
ur = preferred_runner()(dir; platform=platform, preferred_gcc_version=v"5")
iobuff = IOBuffer()
test_c = """
#include <stdlib.h>
int test(void) {
return 0;
}
"""
test_script = """
set -e
cd /workspace
# Make sure setting `CCACHE` doesn't affect the compiler wrappers.
export CCACHE=pwned
export USE_CCACHE=false
echo '$(test_c)' > test.c
# Build shared library
$(compiler) -shared test.c -o libtest.\${dlext}
"""
cmd = `/bin/bash -c "$(test_script)"`
@test run(ur, cmd, iobuff)

# Load the library file and test it for the build-id
lib_path = joinpath(dir, "libtest."*platform_dlext(platform))
lib = open(lib_path)
obj_handles = readmeta(lib)
obj = first(obj_handles)
secs = Sections(obj)

# The section must exist for the build-id to be present
@test !isnothing(findfirst(s -> section_name(s) == ".buildid", secs))
end
end

# This tests only that compilers for all platforms can build and link simple C code
@testset "Compilation - $(platform) - $(compiler)" for platform in platforms, compiler in ("cc", "gcc", "clang")
mktempdir() do dir
Expand Down