From dfe053a0ae21cf11ac20092269bd7de2e4f222f2 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Wed, 13 May 2026 12:15:50 -0500 Subject: [PATCH] Require C++20-capable build toolchains Important changes: - Switch mergerfs and vendored libfuse Makefiles to -std=c++20. - Select the latest available GCC/G++ or toolset in container builds. - Verify compiler C++20 support during package installation. - Fix dynamic SysLog formatting for fmt C++20 checks. --- Makefile | 2 +- buildtools/build-mergerfs | 5 +- buildtools/containerfiles/static.installer | 5 +- buildtools/install-build-pkgs | 129 ++++++++++++++++++++- src/fuse_create.cpp | 2 +- src/mergerfs.cpp | 2 +- vendored/libfuse/Makefile | 2 +- vendored/libfuse/lib/debug.cpp | 4 +- 8 files changed, 140 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 07cfdf4d..9ef42bda 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ CXXFLAGS ?= \ -Wno-unused-result \ -pipe override CXXFLAGS += \ - -std=c++17 \ + -std=c++20 \ -MMD \ -MP override INC_FLAGS := \ diff --git a/buildtools/build-mergerfs b/buildtools/build-mergerfs index 75ac36c2..efb9140f 100755 --- a/buildtools/build-mergerfs +++ b/buildtools/build-mergerfs @@ -1,6 +1,10 @@ #!/bin/sh set -e +if [ -e /tmp/build-env ]; then + . /tmp/build-env +fi + if [ $# -ne 2 ]; then echo "usage: $0 " echo "argv: $@" @@ -30,7 +34,6 @@ if [ -e /usr/bin/apt-get ]; then elif [ -e /usr/bin/dnf ]; then make rpm elif [ -e /usr/bin/yum ]; then - . /opt/rh/devtoolset-9/enable make rpm elif [ -e /sbin/apk ]; then echo "NOT YET SUPPORTED" diff --git a/buildtools/containerfiles/static.installer b/buildtools/containerfiles/static.installer index ea0d2fee..0d3b29b8 100644 --- a/buildtools/containerfiles/static.installer +++ b/buildtools/containerfiles/static.installer @@ -1,6 +1,9 @@ ARG BUILD_TIMESTAMP=0 FROM --platform=linux/amd64 ubuntu:latest as build -RUN apt-get update && apt-get install -y makeself +COPY install-build-pkgs /tmp/ +RUN /tmp/install-build-pkgs && \ + DEBIAN_FRONTEND=noninteractive apt-get -qy --no-install-suggests --no-install-recommends install \ + makeself RUN mkdir -p /tmp/mergerfs/ RUN ls -lhd /pkgs RUN cp -v /pkgs/*static*.gz /tmp/mergerfs/ diff --git a/buildtools/install-build-pkgs b/buildtools/install-build-pkgs index 20eb3bba..7751df7b 100755 --- a/buildtools/install-build-pkgs +++ b/buildtools/install-build-pkgs @@ -1,39 +1,162 @@ #!/bin/sh +set -e + +BUILD_ENV=/tmp/build-env + +write_gcc_env() +{ + { + printf 'export CC=%s\n' "$1" + printf 'export CXX=%s\n' "$2" + } > "$BUILD_ENV" +} + +write_toolset_env() +{ + { + printf '. %s\n' "$1" + printf 'export CC=gcc\n' + printf 'export CXX=g++\n' + } > "$BUILD_ENV" +} + +latest_apt_gxx() +{ + apt-cache --names-only search '^g[+][+]-[0-9]' \ + | sed -n 's/^\(g++-[0-9][0-9]*\) .*/\1/p' \ + | sort -t- -k2,2V \ + | tail -n 1 +} + +latest_dnf_toolset() +{ + dnf -q list --showduplicates 'gcc-toolset-*-gcc-c++' 2>/dev/null \ + | sed -n 's/^gcc-toolset-\([0-9][0-9]*\)-gcc-c++\..*/\1/p' \ + | sort -V \ + | tail -n 1 +} + +latest_yum_toolset() +{ + yum -q list available 'devtoolset-*-gcc-c++' 2>/dev/null \ + | sed -n 's/^devtoolset-\([0-9][0-9]*\)-gcc-c++\..*/\1/p' \ + | sort -V \ + | tail -n 1 +} + +version_gt() +{ + highest="$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n 1)" + [ "$highest" = "$1" ] && [ "$1" != "$2" ] +} + +check_cxx20() +{ + cxx="${CXX:-g++}" + test_src=/tmp/mergerfs-cxx20-check.cpp + test_bin=/tmp/mergerfs-cxx20-check + + cat > "$test_src" <<'EOF' +template +concept Incrementable = requires(T value) { value + 1; }; + +static_assert(Incrementable); + +int main() +{ + return 0; +} +EOF + + if ! "$cxx" -std=c++20 "$test_src" -o "$test_bin" >/dev/null 2>&1; then + echo "error: $cxx does not support C++20" >&2 + exit 1 + fi + + rm -f "$test_src" "$test_bin" +} + +: > "$BUILD_ENV" + if [ -e /usr/bin/apt-get ]; then export DEBIAN_FRONTEND=noninteractive apt-get -qy update + cxx_pkg="$(latest_apt_gxx)" + if [ -n "$cxx_pkg" ]; then + gcc_pkg="gcc-${cxx_pkg#g++-}" + compiler_pkgs="$gcc_pkg $cxx_pkg" + write_gcc_env "$gcc_pkg" "$cxx_pkg" + else + compiler_pkgs="g++" + write_gcc_env gcc g++ + fi apt-get -qy --force-yes --no-install-suggests --no-install-recommends \ install \ ca-certificates \ build-essential \ dpkg-dev \ git \ - g++ \ + $compiler_pkgs \ debhelper \ lsb-release \ fakeroot + . "$BUILD_ENV" + check_cxx20 elif [ -e /usr/bin/dnf ]; then dnf -y update + toolset="$(latest_dnf_toolset)" dnf -y install \ git rpm-build gcc-c++ make which libatomic + default_gxx_major="$(g++ -dumpversion | cut -f1 -d.)" + if [ -n "$toolset" ] && version_gt "$toolset" "$default_gxx_major"; then + dnf -y install \ + "gcc-toolset-${toolset}-gcc" \ + "gcc-toolset-${toolset}-gcc-c++" + write_toolset_env "/opt/rh/gcc-toolset-${toolset}/enable" + else + write_gcc_env gcc g++ + fi + . "$BUILD_ENV" + check_cxx20 elif [ -e /usr/bin/yum ]; then yum -y update yum -y install \ git rpm-build gcc-c++ make which - yum -y install centos-release-scl - yum -y install devtoolset-9-gcc\* + yum -y install centos-release-scl || true + yum -y update + toolset="$(latest_yum_toolset)" + default_gxx_major="$(g++ -dumpversion | cut -f1 -d.)" + if [ -n "$toolset" ] && version_gt "$toolset" "$default_gxx_major"; then + yum -y install \ + "devtoolset-${toolset}-gcc" \ + "devtoolset-${toolset}-gcc-c++" + write_toolset_env "/opt/rh/devtoolset-${toolset}/enable" + else + write_gcc_env gcc g++ + fi + . "$BUILD_ENV" + check_cxx20 elif [ -e /usr/bin/zypper ]; then zypper update -y zypper install -y \ git rpm-build gcc-c++ make which + write_gcc_env gcc g++ + . "$BUILD_ENV" + check_cxx20 elif [ -e /sbin/apk ]; then apk add \ abuild git gcc g++ make \ linux-headers + write_gcc_env gcc g++ + . "$BUILD_ENV" + check_cxx20 elif [ -e /usr/sbin/pkg ]; then pkg install \ git gmake gcc elif [ -e /usr/bin/pacman ]; then pacman -Sy --noconfirm base-devel git fakeroot + write_gcc_env gcc g++ + . "$BUILD_ENV" + check_cxx20 fi diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 49f61b7b..2fe50b40 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -334,7 +334,7 @@ _create(const fuse_req_ctx_t *ctx_, delete fi; ffi_->fh = 0; - SysLog::crit(msg); + SysLog::crit("{}",msg); fmt::println(stderr,"{}",msg); return -EIO; diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index a928eba6..c4ad8903 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -301,7 +301,7 @@ _warn_if_not_root() "mergerfs is not running as root" " and may not work correctly"; fmt::println(stderr,"* WARNING: {}",s); - SysLog::warning(s); + SysLog::warning("{}",s); } int diff --git a/vendored/libfuse/Makefile b/vendored/libfuse/Makefile index d41928c8..c22eaa4a 100644 --- a/vendored/libfuse/Makefile +++ b/vendored/libfuse/Makefile @@ -114,7 +114,7 @@ CXXFLAGS ?= \ -Wall \ -pipe override CXXFLAGS += \ - -std=c++17 \ + -std=c++20 \ -MMD \ -MP FUSERMOUNT_DIR := $(BINDIR) diff --git a/vendored/libfuse/lib/debug.cpp b/vendored/libfuse/lib/debug.cpp index d435a0d2..aaeb4f10 100644 --- a/vendored/libfuse/lib/debug.cpp +++ b/vendored/libfuse/lib/debug.cpp @@ -1191,7 +1191,7 @@ fuse_syslog_fuse_init_in(const struct fuse_init_in *arg_) output.pop_back(); output += ");"; - SysLog::info(output); + SysLog::info("{}",output); } void @@ -1239,7 +1239,7 @@ fuse_syslog_fuse_init_out(const struct fuse_init_out *arg_) output.pop_back(); output += ");"; - SysLog::info(output); + SysLog::info("{}",output); }