From 492ff2106b7d43e75373d298deb6c2da89d7fd80 Mon Sep 17 00:00:00 2001 From: David Frank Date: Tue, 23 Jun 2026 21:23:42 +0200 Subject: [PATCH 1/9] feat: Add fuse2fs tool built from e2fsprogs fuse2fs will be used to extract the contents of released ext4 images without root, it comes from the same e2fsprogs package that we already have but a few compile options had to be tweaked. In addition, libfuse must be provided as a dependency. --- BUILD.bazel | 9 +++++++ MODULE.bazel | 9 +++++++ bazel/defs.bzl | 39 ++++++++++++++++++++++++++++ third_party/BUILD.e2fsprogs.bazel | 42 +++++++++++++++++++++++++------ third_party/BUILD.libfuse.bazel | 36 ++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 third_party/BUILD.libfuse.bazel diff --git a/BUILD.bazel b/BUILD.bazel index 68e98bac510b..de7d8256f0a8 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -218,6 +218,15 @@ alias( }), ) +### fuse2fs, used to mount ext filesystems in userspace +alias( + name = "fuse2fs", + actual = select({ + "@bazel_tools//src/conditions:linux_x86_64": "@e2fsprogs//:fuse2fs", + "//conditions:default": "@platforms//:incompatible", + }), +) + ### dosfstools, used to build (mkfs.fat) and label (fatlabel) FAT filesystem images # Both aliases resolve to the dosfstools package, which builds the mkfs.fat and diff --git a/MODULE.bazel b/MODULE.bazel index ec0a3b8ca89a..2427b92c490d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -735,6 +735,15 @@ http_archive( ], ) +http_archive( + name = "libfuse", + build_file = "@//third_party:BUILD.libfuse.bazel", + sha256 = "f01de85717e20adf5f98aff324acd85dd73d61a5ca3834d573dcf0bd6e54a298", + strip_prefix = "fuse-3.18.2", + type = "tar.gz", + urls = ["https://github.com/libfuse/libfuse/releases/download/fuse-3.18.2/fuse-3.18.2.tar.gz"], +) + http_archive( name = "e2fsprogs", build_file = "@//third_party:BUILD.e2fsprogs.bazel", diff --git a/bazel/defs.bzl b/bazel/defs.bzl index 881cc5d7319c..55107cf78ea6 100644 --- a/bazel/defs.bzl +++ b/bazel/defs.bzl @@ -5,6 +5,7 @@ Utilities for building IC replica and canisters. load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_test", "rust_test_suite") load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("@rules_shell//shell:sh_test.bzl", "sh_test") +load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("//publish:defs.bzl", "release_nostrip_binary") _COMPRESS_CONCURRENCY = 16 @@ -392,6 +393,44 @@ volatile_status = rule( implementation = _volatile_status_impl, ) +def _disable_hermetic_cc_transition(_settings, _attr): + return { + "//bazel:hermetic_cc": False, + } + +disable_hermetic_cc_transition = transition( + implementation = _disable_hermetic_cc_transition, + inputs = [], + outputs = [ + "//bazel:hermetic_cc", + ], +) + +def _disable_hermetic_cc_target_impl(ctx): + dep = ctx.attr.target[0] + providers = [dep[DefaultInfo]] + + if CcInfo in dep: + providers.append(dep[CcInfo]) + if OutputGroupInfo in dep: + providers.append(dep[OutputGroupInfo]) + + return providers + +disable_hermetic_cc_target = rule( + implementation = _disable_hermetic_cc_target_impl, + attrs = { + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + "target": attr.label( + mandatory = True, + cfg = disable_hermetic_cc_transition, + allow_files = True, + ), + }, +) + def file_size_check( name, file, diff --git a/third_party/BUILD.e2fsprogs.bazel b/third_party/BUILD.e2fsprogs.bazel index 874b95dda5c5..864218504bb4 100644 --- a/third_party/BUILD.e2fsprogs.bazel +++ b/third_party/BUILD.e2fsprogs.bazel @@ -3,6 +3,7 @@ e2fsprogs, built from source. The bundled libuuid/libblkid are enabled so we don't link against system copies. """ +load("@//bazel:defs.bzl", "disable_hermetic_cc_target") load("@rules_foreign_cc//foreign_cc:defs.bzl", "configure_make") filegroup( @@ -11,7 +12,7 @@ filegroup( ) configure_make( - name = "mke2fs", + name = "e2fsprogs_impl", args = ["-j"], configure_in_place = True, configure_options = [ @@ -19,8 +20,8 @@ configure_make( # stays self-contained. "--enable-libuuid", "--enable-libblkid", + "--enable-fuse2fs", # Trim optional features that would pull in extra deps or shared libs. - "--disable-fuse2fs", "--disable-uuidd", "--disable-nls", "--disable-tls", @@ -35,13 +36,19 @@ configure_make( "--with-systemd-unit-dir=no", ], env = { - "CFLAGS": "-g -O2 -static", - "LDFLAGS": "-static", + "CFLAGS": "-g -O2 -static -I$$EXT_BUILD_DEPS/include", + "LDFLAGS": "-static -L$$EXT_BUILD_DEPS/lib", }, lib_source = ":all_srcs", - out_binaries = ["mke2fs"], + deps = [ + "@libfuse//:libfuse", + ], + out_binaries = [ + "fuse2fs", + "mke2fs", + ], # We don't ship any libs out of this build; everything is folded into the - # mke2fs binary. + # exported binaries. out_shared_libs = [], out_static_libs = [], # mke2fs is installed under sbin/ by autotools (it's a sysadmin tool); @@ -54,7 +61,7 @@ configure_make( "mkdir -p $$INSTALLDIR/bin" + " && cp $$INSTALLDIR/sbin/mke2fs $$INSTALLDIR/bin/mke2fs" + " && find $$INSTALLDIR -mindepth 1 -maxdepth 1 ! -name bin ! -name include -exec rm -rf {} +" + - " && find $$INSTALLDIR/bin -mindepth 1 ! -name mke2fs -delete" + " && find $$INSTALLDIR/bin -mindepth 1 ! -name fuse2fs ! -name mke2fs -delete" ), # Static glibc linking is a Linux/glibc thing; this isn't expected to work # elsewhere. @@ -62,5 +69,26 @@ configure_make( "@platforms//cpu:x86_64", "@platforms//os:linux", ], +) + +# e2fsprogs' dependency, libfuse does not build with hermetic toolchains (meson is not happy with the zig linker), +# and building libfuse without the hermetic and e2fsprogs with the hermetic toolchain causes linking issues because of +# glibc version mismatch. So just disable the hermetic toolchain for e2fsprogs. +disable_hermetic_cc_target( + name = "e2fsprogs", + target = ":e2fsprogs_impl", +) + +filegroup( + name = "fuse2fs", + srcs = [":e2fsprogs"], + output_group = "fuse2fs", + visibility = ["//visibility:public"], +) + +filegroup( + name = "mke2fs", + srcs = [":e2fsprogs"], + output_group = "mke2fs", visibility = ["//visibility:public"], ) diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel new file mode 100644 index 000000000000..942d2f1e1daa --- /dev/null +++ b/third_party/BUILD.libfuse.bazel @@ -0,0 +1,36 @@ +load("@//bazel:defs.bzl", "disable_hermetic_cc_target") +load("@rules_foreign_cc//foreign_cc:defs.bzl", "meson") + +filegroup( + name = "all_srcs", + srcs = glob( + include = ["**"], + exclude = ["*.bazel"], + ), +) + +meson( + name = "libfuse", + options = { + "default_library": "static", + "disable-mtab": "true", + "examples": "false", + "tests": "false", + "useroot": "false", + "utils": "false", + }, + env = { + "CFLAGS": "-g -O2", + }, + lib_source = ":all_srcs", + postfix_script = ( + "libfuse_archive=$$(find $$INSTALLDIR/lib -name libfuse3.a -print -quit)" + + " && test -n \"$$libfuse_archive\"" + + " && cp \"$$libfuse_archive\" $$INSTALLDIR/lib/libfuse3.a" + ), + out_shared_libs = [], + out_static_libs = ["libfuse3.a"], + #visibility = ["//visibility:private"], + visibility = ["//visibility:public"], +) + From b82377e456caceb59a69c2ca91234e300687e691 Mon Sep 17 00:00:00 2001 From: IDX GitHub Automation Date: Tue, 23 Jun 2026 19:29:37 +0000 Subject: [PATCH 2/9] Automatically fixing code for linting and formatting issues --- bazel/defs.bzl | 2 +- third_party/BUILD.e2fsprogs.bazel | 6 +++--- third_party/BUILD.libfuse.bazel | 14 ++++++-------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/bazel/defs.bzl b/bazel/defs.bzl index 55107cf78ea6..164fecf14056 100644 --- a/bazel/defs.bzl +++ b/bazel/defs.bzl @@ -2,10 +2,10 @@ Utilities for building IC replica and canisters. """ +load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_test", "rust_test_suite") load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("@rules_shell//shell:sh_test.bzl", "sh_test") -load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("//publish:defs.bzl", "release_nostrip_binary") _COMPRESS_CONCURRENCY = 16 diff --git a/third_party/BUILD.e2fsprogs.bazel b/third_party/BUILD.e2fsprogs.bazel index 864218504bb4..1227900d674a 100644 --- a/third_party/BUILD.e2fsprogs.bazel +++ b/third_party/BUILD.e2fsprogs.bazel @@ -40,9 +40,6 @@ configure_make( "LDFLAGS": "-static -L$$EXT_BUILD_DEPS/lib", }, lib_source = ":all_srcs", - deps = [ - "@libfuse//:libfuse", - ], out_binaries = [ "fuse2fs", "mke2fs", @@ -69,6 +66,9 @@ configure_make( "@platforms//cpu:x86_64", "@platforms//os:linux", ], + deps = [ + "@libfuse", + ], ) # e2fsprogs' dependency, libfuse does not build with hermetic toolchains (meson is not happy with the zig linker), diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel index 942d2f1e1daa..6314dcec041c 100644 --- a/third_party/BUILD.libfuse.bazel +++ b/third_party/BUILD.libfuse.bazel @@ -1,4 +1,3 @@ -load("@//bazel:defs.bzl", "disable_hermetic_cc_target") load("@rules_foreign_cc//foreign_cc:defs.bzl", "meson") filegroup( @@ -11,6 +10,10 @@ filegroup( meson( name = "libfuse", + env = { + "CFLAGS": "-g -O2", + }, + lib_source = ":all_srcs", options = { "default_library": "static", "disable-mtab": "true", @@ -19,18 +22,13 @@ meson( "useroot": "false", "utils": "false", }, - env = { - "CFLAGS": "-g -O2", - }, - lib_source = ":all_srcs", + out_shared_libs = [], + out_static_libs = ["libfuse3.a"], postfix_script = ( "libfuse_archive=$$(find $$INSTALLDIR/lib -name libfuse3.a -print -quit)" + " && test -n \"$$libfuse_archive\"" + " && cp \"$$libfuse_archive\" $$INSTALLDIR/lib/libfuse3.a" ), - out_shared_libs = [], - out_static_libs = ["libfuse3.a"], #visibility = ["//visibility:private"], visibility = ["//visibility:public"], ) - From 1e28ea05c0d3e655fa6befdc439f1477bd1b3a44 Mon Sep 17 00:00:00 2001 From: David Frank Date: Tue, 23 Jun 2026 23:51:59 +0200 Subject: [PATCH 3/9] Update third_party/BUILD.libfuse.bazel Co-authored-by: Bas van Dijk --- third_party/BUILD.libfuse.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel index 6314dcec041c..3de5651fee52 100644 --- a/third_party/BUILD.libfuse.bazel +++ b/third_party/BUILD.libfuse.bazel @@ -29,6 +29,5 @@ meson( " && test -n \"$$libfuse_archive\"" + " && cp \"$$libfuse_archive\" $$INSTALLDIR/lib/libfuse3.a" ), - #visibility = ["//visibility:private"], visibility = ["//visibility:public"], ) From 84c281333686b73fffa8925693c9f96e36499aef Mon Sep 17 00:00:00 2001 From: David Frank Date: Wed, 24 Jun 2026 13:54:49 +0200 Subject: [PATCH 4/9] Try to fix build determinism --- third_party/BUILD.libfuse.bazel | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel index 3de5651fee52..4d10397153c6 100644 --- a/third_party/BUILD.libfuse.bazel +++ b/third_party/BUILD.libfuse.bazel @@ -8,10 +8,12 @@ filegroup( ), ) +# This only builds with --hermetic_cc=false or the disable_hermetic_cc transition. meson( name = "libfuse", env = { - "CFLAGS": "-g -O2", + "ARFLAGS": "crD", # for build determinism + "CFLAGS": "-O2", }, lib_source = ":all_srcs", options = { From 15feb516258ed230d6b19bd6c4a40e8a55870768 Mon Sep 17 00:00:00 2001 From: IDX GitHub Automation Date: Wed, 24 Jun 2026 12:00:12 +0000 Subject: [PATCH 5/9] Automatically fixing code for linting and formatting issues --- third_party/BUILD.libfuse.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel index 4d10397153c6..ec33433a6dd0 100644 --- a/third_party/BUILD.libfuse.bazel +++ b/third_party/BUILD.libfuse.bazel @@ -12,7 +12,7 @@ filegroup( meson( name = "libfuse", env = { - "ARFLAGS": "crD", # for build determinism + "ARFLAGS": "crD", # for build determinism "CFLAGS": "-O2", }, lib_source = ":all_srcs", From 0f594c5d3768fe14b716c67c6ad4f711603a9fd7 Mon Sep 17 00:00:00 2001 From: David Frank Date: Wed, 24 Jun 2026 15:13:28 +0200 Subject: [PATCH 6/9] Try to fix build determinism, attempt #2 --- third_party/BUILD.e2fsprogs.bazel | 11 +++++------ third_party/BUILD.libfuse.bazel | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/third_party/BUILD.e2fsprogs.bazel b/third_party/BUILD.e2fsprogs.bazel index 1227900d674a..61b16ab44b48 100644 --- a/third_party/BUILD.e2fsprogs.bazel +++ b/third_party/BUILD.e2fsprogs.bazel @@ -36,7 +36,7 @@ configure_make( "--with-systemd-unit-dir=no", ], env = { - "CFLAGS": "-g -O2 -static -I$$EXT_BUILD_DEPS/include", + "CFLAGS": "-O2 -static -I$$EXT_BUILD_DEPS/include", "LDFLAGS": "-static -L$$EXT_BUILD_DEPS/lib", }, lib_source = ":all_srcs", @@ -55,11 +55,10 @@ configure_make( # The headers under include/ are kept since rules_foreign_cc declares them # as an output. postfix_script = ( - "mkdir -p $$INSTALLDIR/bin" + - " && cp $$INSTALLDIR/sbin/mke2fs $$INSTALLDIR/bin/mke2fs" + - " && find $$INSTALLDIR -mindepth 1 -maxdepth 1 ! -name bin ! -name include -exec rm -rf {} +" + - " && find $$INSTALLDIR/bin -mindepth 1 ! -name fuse2fs ! -name mke2fs -delete" - ), + "mkdir -p $$INSTALLDIR/bin" + + " && cp misc/mke2fs $$INSTALLDIR/bin/mke2fs" + + " && cp misc/fuse2fs $$INSTALLDIR/bin/fuse2fs" + ), # Static glibc linking is a Linux/glibc thing; this isn't expected to work # elsewhere. target_compatible_with = [ diff --git a/third_party/BUILD.libfuse.bazel b/third_party/BUILD.libfuse.bazel index ec33433a6dd0..5c0e0bb2faf0 100644 --- a/third_party/BUILD.libfuse.bazel +++ b/third_party/BUILD.libfuse.bazel @@ -12,7 +12,6 @@ filegroup( meson( name = "libfuse", env = { - "ARFLAGS": "crD", # for build determinism "CFLAGS": "-O2", }, lib_source = ":all_srcs", @@ -23,6 +22,7 @@ meson( "tests": "false", "useroot": "false", "utils": "false", + "bindir": "/bin", }, out_shared_libs = [], out_static_libs = ["libfuse3.a"], From 2f4907fff08ed5c4351919e488d6d52e38a3aade Mon Sep 17 00:00:00 2001 From: IDX GitHub Automation Date: Wed, 24 Jun 2026 13:19:07 +0000 Subject: [PATCH 7/9] Automatically fixing code for linting and formatting issues --- third_party/BUILD.e2fsprogs.bazel | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/third_party/BUILD.e2fsprogs.bazel b/third_party/BUILD.e2fsprogs.bazel index 61b16ab44b48..9da261f66b49 100644 --- a/third_party/BUILD.e2fsprogs.bazel +++ b/third_party/BUILD.e2fsprogs.bazel @@ -55,10 +55,10 @@ configure_make( # The headers under include/ are kept since rules_foreign_cc declares them # as an output. postfix_script = ( - "mkdir -p $$INSTALLDIR/bin" + - " && cp misc/mke2fs $$INSTALLDIR/bin/mke2fs" + - " && cp misc/fuse2fs $$INSTALLDIR/bin/fuse2fs" - ), + "mkdir -p $$INSTALLDIR/bin" + + " && cp misc/mke2fs $$INSTALLDIR/bin/mke2fs" + + " && cp misc/fuse2fs $$INSTALLDIR/bin/fuse2fs" + ), # Static glibc linking is a Linux/glibc thing; this isn't expected to work # elsewhere. target_compatible_with = [ From 46d54c8e17e34f5bdbba5fd1ab16daadd7ee1844 Mon Sep 17 00:00:00 2001 From: David Frank Date: Wed, 24 Jun 2026 16:45:21 +0200 Subject: [PATCH 8/9] Try to fix build determinism, attempt #3 --- third_party/BUILD.e2fsprogs.bazel | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/third_party/BUILD.e2fsprogs.bazel b/third_party/BUILD.e2fsprogs.bazel index 9da261f66b49..8005952145da 100644 --- a/third_party/BUILD.e2fsprogs.bazel +++ b/third_party/BUILD.e2fsprogs.bazel @@ -56,8 +56,9 @@ configure_make( # as an output. postfix_script = ( "mkdir -p $$INSTALLDIR/bin" + - " && cp misc/mke2fs $$INSTALLDIR/bin/mke2fs" + - " && cp misc/fuse2fs $$INSTALLDIR/bin/fuse2fs" + " && cp $$INSTALLDIR/sbin/mke2fs $$INSTALLDIR/bin/mke2fs" + + " && find $$INSTALLDIR -mindepth 1 -maxdepth 1 ! -name bin ! -name include -exec rm -rf {} +" + + " && find $$INSTALLDIR/bin -mindepth 1 ! -name fuse2fs ! -name mke2fs -delete" ), # Static glibc linking is a Linux/glibc thing; this isn't expected to work # elsewhere. From 859b6af5e4fdb1d870a00868d4d72decc3ce4a31 Mon Sep 17 00:00:00 2001 From: David Frank Date: Wed, 24 Jun 2026 18:10:28 +0200 Subject: [PATCH 9/9] Try to fix build determinism, attempt #4 --- toolchains/sysimage/build_ext4_image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolchains/sysimage/build_ext4_image.py b/toolchains/sysimage/build_ext4_image.py index ca50297f8105..5ed4aee4efcc 100755 --- a/toolchains/sysimage/build_ext4_image.py +++ b/toolchains/sysimage/build_ext4_image.py @@ -227,7 +227,7 @@ def main(): image_file, str(image_size), ] - subprocess.run(mke2fs_args, check=True, env={"E2FSPROGS_FAKE_TIME": "0"}) + subprocess.run(mke2fs_args, check=True, env={"SOURCE_DATE_EPOCH": "0"}) # Use our tool, diroid, to create an fs_config file to be used by e2fsdroid. # This file is a simple list of files with their desired uid, gid, and mode. @@ -263,7 +263,7 @@ def main(): if file_contexts_file: e2fsdroid_args += ["-S", file_contexts_file] e2fsdroid_args += [image_file] - subprocess.run(e2fsdroid_args, check=True, env={"E2FSPROGS_FAKE_TIME": "0"}) + subprocess.run(e2fsdroid_args, check=True, env={"SOURCE_DATE_EPOCH": "0"}) # We use our tool, dflate, to quickly create a sparse, deterministic, tar. # If dflate is ever misbehaving, it can be replaced with: