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..164fecf14056 100644 --- a/bazel/defs.bzl +++ b/bazel/defs.bzl @@ -2,6 +2,7 @@ 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") @@ -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..8005952145da 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,16 @@ configure_make( "--with-systemd-unit-dir=no", ], env = { - "CFLAGS": "-g -O2 -static", - "LDFLAGS": "-static", + "CFLAGS": "-O2 -static -I$$EXT_BUILD_DEPS/include", + "LDFLAGS": "-static -L$$EXT_BUILD_DEPS/lib", }, lib_source = ":all_srcs", - out_binaries = ["mke2fs"], + 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 +58,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 +66,29 @@ 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), +# 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..5c0e0bb2faf0 --- /dev/null +++ b/third_party/BUILD.libfuse.bazel @@ -0,0 +1,35 @@ +load("@rules_foreign_cc//foreign_cc:defs.bzl", "meson") + +filegroup( + name = "all_srcs", + srcs = glob( + include = ["**"], + exclude = ["*.bazel"], + ), +) + +# This only builds with --hermetic_cc=false or the disable_hermetic_cc transition. +meson( + name = "libfuse", + env = { + "CFLAGS": "-O2", + }, + lib_source = ":all_srcs", + options = { + "default_library": "static", + "disable-mtab": "true", + "examples": "false", + "tests": "false", + "useroot": "false", + "utils": "false", + "bindir": "/bin", + }, + 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" + ), + visibility = ["//visibility:public"], +) 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: