diff --git a/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md b/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md index 60772f9b6c..adf657b9ff 100644 --- a/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md +++ b/local/docs/NATIVE-TOOLCHAIN-WORKSTREAM.md @@ -141,10 +141,144 @@ printf '#include \nint main(){}' > t.cpp c++ -std=c++17 -I${HOME}/.redoxer/x86_64-unknown-redox/toolchain/include -c t.cpp ``` -So this is a target→host leak, not a host→target one. See the `rust-native` -finding #5 below for the fix pattern (`host:` packages stage into -`COOKBOOK_TOOLCHAIN`, which is a separate tree from the target sysroot); the -same approach should apply here. +So this is a target→host leak, not a host→target one. + +**This section is now historical: `gcc-native` BUILDS (2026-08-05).** Both +`gcc-native` (gcc, cc1, libgcc.a) and the `gcc-native.gcc-native` C++ +subpackage (g++, c++, cc1plus, libstdc++.a, the 16.1.0 C++ headers) cook and +publish. + +A correction to what this file said a few hours earlier: it predicted the +`host:` package pattern from `rust-native` finding #5 would be what unblocked +this. **It was not.** The leak above was already handled in the recipe by +stripping `-I${COOKBOOK_SYSROOT}/include` out of `CPPFLAGS` and restating +`BUILD_CPPFLAGS` without the trailing `$(CPPFLAGS)`. What remained were two +different defects: + +| # | Defect | Resolution | +|---|---|---| +| 11 | Generator links failed with `undefined reference to __letf2@GCC_4.3.0` (+ `__gttf2`, `__eqtf2`, `__getf2`, `__unordtf2`). The Redox `libgcc_s.so.1` sits in `build/gcc/`, and the host `g++` resolves its libstdc++'s `GROUP ( libgcc_s.so.1 -lgcc )` against the cwd first, binding the REDOX libgcc, which has no `GCC_4.3.0` soft-float symbols | pass `CXX_FOR_BUILD="g++ -static-libstdc++"`. The recipe already defined `_rb_linker_for_build` for this and never passed it to make — dead code | +| 12 | `error: 'CXX' has changed since the previous run` from `build-x86_64-pc-linux-gnu/libcpp` — caused by fixing #11, since the top level exports `CXX=$(CXX_FOR_BUILD)` into the build-side subdirs' configure environment | wipe the build dir once (`COOKBOOK_CLEAN_BUILD=true`). Autoconf behaving correctly, not a defect | + +**Why the flag and not the sequencing.** The recipe builds `all-gcc` as its own +make invocation before the target libraries, on the reasoning that sequencing +"removes the cause instead of papering over it". That only holds for a CLEAN +build. Once any previous run has left the Redox `libgcc_s.so.1` in `build/gcc/`, +the *first* `all-gcc` of the next run links its generators beside that file and +fails again — which is exactly what happened. Recipes must rebuild correctly on +a dirty `target/`, so the flag is the fix; the sequencing is kept as defence in +depth. + +**Why `CXX_FOR_BUILD` is the knob that works.** `BUILD_LDFLAGS` and +`BUILD_CPPFLAGS` are `gcc/Makefile` variables that do not exist in the +TOP-LEVEL Makefile, so a top-level `make BUILD_LDFLAGS=…` never reaches the gcc +sub-make. `CXX_FOR_BUILD` is defined at top level and forwarded to every +sub-make explicitly, and `gcc/Makefile.in:870` sets +`LINKER_FOR_BUILD = $(CXX_FOR_BUILD)`. Confirmed with `make -n all-gcc` from +the top level before changing anything: with `CXX_FOR_BUILD` the command +becomes `g++ -static-libstdc++ …`; the `BUILD_LDFLAGS` form leaves it bare. +This supersedes the older in-recipe note claiming `LINKER_FOR_BUILD` was tried +and did not reach — it does reach, from inside `build/gcc`; the problem was +always propagation from the top level. + +### Finding 13 — both C++23 modules were silently dropped (FIXED) + +The build exited 0 while emitting 41 errors, and shipped no `std.gcm` or +`std.compat.gcm`. `gcc/Makefile` deliberately tolerates the failure: + +``` +if ! …compile std.cc…; then + echo "Cannot compile std module" >&2 + echo "Module initialization function will be missing" >&2 + echo > std.cc.tmp && mv std.cc.tmp std.cc && …compile the now-empty file… +fi +``` + +`std.cc` pulls in all of ``, including ``, and libstdc++'s +own `fenv.h` wrapper fails at `using ::fenv_t;` / `::fexcept_t` / the `fe*` +functions. The module source is then replaced with an empty file and the build +continues, so no `std.gcm` is staged. Ordinary `#include ` is unaffected; +only C++23 named modules are. + +**relibc is not at fault, and this is not a missing implementation.** Compiling + +``` +#include +fenv_t e; fexcept_t f; +int main(){ feclearexcept(0); return 0; } +``` + +with `x86_64-unknown-redox-gcc` succeeds cleanly, in C and in C++. Same +"header-path problem, not a missing implementation" pattern as finding #8. + +**Root cause.** `-H` on a reproduction TU shows where `#include_next` lands: + +``` +.. build/…/libstdc++-v3/include/fenv.h <- new wrapper +... prefix/…/relibc-install/x86_64-unknown-redox/include/c++/16.1.0/fenv.h <- include_next +``` + +It reaches the PREFIX toolchain's already-installed copy of the same libstdc++ +wrapper, not relibc's C ``. Both use the guard `_GLIBCXX_FENV_H`, which +the new wrapper defines *before* its `#include_next`, so the installed copy's +body is skipped entirely, the chain dead-ends, and every `using ::` below fails. + +Ordinary `#include` never had this problem — the in-tree `-I` flags come first. +Only `include_next`, which resumes *after* the current header's directory, +walks out of the build tree. + +A stock GCC build never hits it because target libraries are built with the +in-tree compiler, which carries `-nostdinc++`. Here the recipe exports +`CXX=${GNU_TARGET}-g++`, so the top-level Makefile gets +`CXX_FOR_TARGET=RAW_CXX_FOR_TARGET=x86_64-unknown-redox-c++` — plain, with the +installed C++ header directory still on its search path. Only `src/c++17` and +`src/experimental` pass `-nostdinc++` of their own accord, which is why nothing +else broke. + +**Fix:** `export CXXFLAGS_FOR_TARGET="-g -O2 ${CXXFLAGS} -nostdinc++"` before +configure. Unlike `BUILD_*`, it is a top-level variable — forwarded to every +sub-make and exported as target `CXXFLAGS` — so it reaches `std.lo` through +`LTCXXCOMPILE`. Setting it pre-configure bakes it into the generated target +Makefiles so incremental rebuilds stay consistent. + +**Verified:** 41 errors → 0; both "Cannot compile … module" lines gone; +`std.gcm` and `std.compat.gcm` produced; `std.cc`/`std.compat.cc` are 4502/795 +lines rather than emptied; `libstdc++.modules.json` and +`usr/include/c++/16.1.0/bits/std.cc` staged. + +**Process note.** This was first written up as an accepted limitation rather +than fixed. That is a STUB AND WORKAROUND POLICY violation: it does not matter +that GCC's own Makefile performs the emptying — shipping a toolchain whose +modules were removed to make the build pass is the same thing as stubbing them. +Exit code 0 plus present artifacts is not evidence a build is whole; the log +has to be read for swallowed failures. + +### Open: subdirectories configure declines to build + +Not a stub, but a real capability gap in the shipped compiler, recorded rather +than discovered later. `configure` reports: + +``` +*** This configuration is not supported in the following subdirectories: + target-libgomp target-libatomic target-libitm target-libsanitizer + target-libvtv target-libbacktrace target-libffi target-zlib (+ the + Ada/Go/D/Fortran/ObjC/Modula-2/COBOL/Algol68 trees) +``` + +The language trees are irrelevant here (`--enable-languages=c,c++,lto`). These +are not: + +| Subdirectory | Consequence for the shipped toolchain | +|---|---| +| `target-libatomic` | no `libatomic`; some atomic operations will not link | +| `target-libgomp` | `-fopenmp` unavailable | +| `target-libsanitizer` | no ASan/UBSan | +| `target-libbacktrace` | `std::stacktrace` degraded (libstdc++ still builds `stacktrace.cc`) | + +This is GCC's Canadian-cross limitation for a `--host==--target` build driven +from a Linux build machine, not something the recipe introduced. Needs an +operator decision: accept the reduced toolchain, or restructure the build so +these are supported. ## `rust-native` — four findings, one open diff --git a/local/recipes/dev/gcc-native/recipe.toml b/local/recipes/dev/gcc-native/recipe.toml index 0a58d035ca..5784693145 100644 --- a/local/recipes/dev/gcc-native/recipe.toml +++ b/local/recipes/dev/gcc-native/recipe.toml @@ -58,6 +58,30 @@ DYNAMIC_INIT # Same shape as the cpuid.h shadowing in recipes/dev/gcc13. export CPPFLAGS="-I${COOKBOOK_SOURCE}/include ${CPPFLAGS}" +# Drop the target sysroot from CPPFLAGS entirely. +# +# src/cook/script.rs adds -I${COOKBOOK_SYSROOT}/include to CPPFLAGS for every +# recipe. For GCC that is actively harmful: gcc/Makefile feeds $(CPPFLAGS) to +# the build/ generators too, which run on the BUILD machine and are compiled by +# the host g++ against host glibc and libstdc++. relibc's headers then shadow +# glibc's and the host's own headers stop parsing: +# /usr/include/c++/16/.../bits/os_defines.h:44: +# error: missing binary operator before token '(' +# #if __GLIBC_PREREQ(2,15) && defined(_GNU_SOURCE) +# __GLIBC_PREREQ comes from glibc's ; relibc's shadowing copy has +# no such macro. Overriding BUILD_CPPFLAGS alone is not enough -- $(CPPFLAGS) +# reaches those compiles by more than one route. +# +# Nothing needs it here: target headers come from the cross compiler's own +# --with-sysroot, and gmp/mpfr/mpc are located by explicit --with-* flags below. +# (sed with a '|' delimiter rather than bash ${var//a/b}: the pattern contains +# slashes, and a backslash-escaped slash is an invalid escape sequence inside a +# TOML multi-line basic string. The parser reads this whole script as one +# string, so shell comments are not exempt from either that rule or from +# accidentally closing the quote.) +CPPFLAGS="$(printf '%s' "${CPPFLAGS}" | sed "s|-I${COOKBOOK_SYSROOT}/include||g")" +export CPPFLAGS + export CFLAGS="${CFLAGS//-std=gnu17/}" export CXXFLAGS="${CXXFLAGS//-std=gnu17/}" @@ -70,6 +94,44 @@ export LD="${GNU_TARGET}-ld" export NM="${GNU_TARGET}-nm" export STRIP="${GNU_TARGET}-strip" +# Build the TARGET libraries with -nostdinc++, or libstdc++ is compiled against +# the PREFIX toolchain's already-installed libstdc++ headers. +# +# A stock GCC build never needs this stated: it builds target libraries with the +# in-tree compiler, which carries -nostdinc++ and -B flags of its own. Here CXX +# is the prefix compiler (set above, and this configures --host=--target=redox), +# so the top-level Makefile ends up with +# CXX_FOR_TARGET=x86_64-unknown-redox-c++ +# RAW_CXX_FOR_TARGET=x86_64-unknown-redox-c++ +# -- plain, with the installed C++ header directory still on its search path. +# +# Ordinary #include is unaffected, because the -I flags for the in-tree headers +# come first. #include_next is NOT: it resumes the search AFTER the directory +# holding the current header, which walks straight out of the build tree and +# into prefix/.../include/c++/16.1.0. libstdc++'s own c_compatibility/fenv.h +# does exactly that to reach the C , and lands on the INSTALLED copy of +# itself -- which is guarded by the same _GLIBCXX_FENV_H the new one has already +# defined, so its body is skipped, relibc's fenv.h is never reached, and every +# declaration in the block below it fails: +# .../libstdc++-v3/include/fenv.h:65: error: 'fenv_t' has not been declared in '::' +# (then fexcept_t, feclearexcept, fegetexceptflag, ... 41 errors) +# +# That killed the C++23 `std` module: src/c++23/Makefile's std.lo rule retries +# with an EMPTIED std.cc when the compile fails, so the build went green while +# silently shipping no std.gcm. Suppressing a module to make a build pass is a +# stub by another name (local/AGENTS.md, STUB AND WORKAROUND POLICY) -- the +# header path is the defect and is what gets fixed. +# +# Verified by reproducing the failure in a two-line TU with the same -I chain +# and no -fmodules, then compiling it clean with -nostdinc++ added. +# +# CXXFLAGS_FOR_TARGET is the right knob: unlike BUILD_*, it is a TOP-LEVEL +# variable (forwarded to every sub-make, and exported as CXXFLAGS for target +# directories), so it reaches std.lo through LTCXXCOMPILE. Set before configure +# so the generated target Makefiles carry it and incremental rebuilds stay +# consistent. "-g -O2" reproduces the default configure would have derived. +export CXXFLAGS_FOR_TARGET="-g -O2 ${CXXFLAGS} -nostdinc++" + # Configure for native compilation: host AND target are both redox COOKBOOK_CONFIGURE_FLAGS+=( --host="${GNU_TARGET}" @@ -92,8 +154,129 @@ COOKBOOK_CONFIGURE_FLAGS+=( ) "${COOKBOOK_CONFIGURE}" "${COOKBOOK_CONFIGURE_FLAGS[@]}" -"${COOKBOOK_MAKE}" -j "${COOKBOOK_MAKE_JOBS}" all-gcc all-target-libgcc all-target-libstdc++-v3 -"${COOKBOOK_MAKE}" install-gcc install-target-libgcc install-target-libstdc++-v3 DESTDIR="${COOKBOOK_STAGE}" + +# Keep the TARGET sysroot out of HOST-side compiles. +# +# gcc/Makefile.in:875 defines +# BUILD_CPPFLAGS= -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \ +# -I$(srcdir)/../include $(INCINTL) $(CPPINC) $(CPPFLAGS) +# -- it ends in $(CPPFLAGS). The generators in build/ (genversion, genmodes, +# gengtype, ...) run on the BUILD machine and are compiled by the host g++ +# against host glibc and libstdc++ headers, but that trailing $(CPPFLAGS) +# hands them the target's -I${COOKBOOK_SYSROOT}/include as well (the cookbook +# adds it to every recipe, src/cook/script.rs). relibc's headers then shadow +# glibc's, so glibc's own macros are never defined and its headers stop +# parsing: +# /usr/include/sys/single_threaded.h:24: error: '__BEGIN_DECLS' is not a type +# /usr/include/stdlib.h:752: error: expected initializer before '__THROW' +# with relibc's `#define __noreturn [[noreturn]]` colliding on top. +# +# The top-level CPPFLAGS_FOR_BUILD knob does NOT reach this: configure already +# generates it empty in build/Makefile, and gcc/Makefile still appends +# $(CPPFLAGS) regardless. So restate the definition verbatim, minus that one +# trailing variable. Single-quoted: these are make variables, expanded per +# rule by make, not by this shell. +_rb_build_cppflags='-I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) -I$(srcdir)/../include $(INCINTL) $(CPPINC)' + +# Same leak, link side. configure derives BUILD_LDFLAGS from LDFLAGS_FOR_BUILD, +# which defaults to $LDFLAGS -- and the cookbook puts the TARGET sysroot in +# there: "-L${COOKBOOK_SYSROOT}/lib -Wl,-rpath-link,${COOKBOOK_SYSROOT}/lib". +# gcc/Makefile.in:3421 then links the build/ generators with +# $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) +# so the HOST g++ searches Redox libraries first and cannot resolve the host's +# own libgcc_s, leaving its libstdc++.so short of the 128-bit float builtins: +# /usr/lib/gcc/x86_64-pc-linux-gnu/16/libstdc++.so: +# undefined reference to `__letf2@GCC_4.3.0' (also __gttf2, __eqtf2, +# __getf2, __unordtf2 -- all libgcc soft-float TF symbols) +# Emptying BUILD_LDFLAGS is enough here, unlike the CPPFLAGS case: the only +# other variable on that rule is BUILD_LINKERFLAGS, which is BUILD_CXXFLAGS and +# carries no -L. Target-side links are untouched and still resolve through the +# cross compiler's --with-sysroot. +# Link the build/ generators against a STATIC libstdc++. +# +# all-target-libgcc writes the REDOX libgcc_s.so.1 into build/gcc/ -- the very +# directory the host-side generator links run from. The host g++ pulls in its +# own libstdc++.so, whose DT_NEEDED is satisfied through the ld script +# GROUP ( libgcc_s.so.1 -lgcc ) +# and that bare filename resolves against the current directory first, so the +# HOST link binds the REDOX libgcc_s. It carries no GCC_4.3.0-versioned soft +# float symbols, so the host libstdc++ is left unresolved: +# /usr/lib/gcc/x86_64-pc-linux-gnu/16/libstdc++.so: +# undefined reference to `__letf2@GCC_4.3.0' +# (also __gttf2, __eqtf2, __getf2, __unordtf2) +# +# Verified directory-dependent: the identical g++ command passes from the repo +# root and fails from build/gcc. It is also why a FIRST build succeeds and only +# a rebuild fails -- on the first pass target libgcc does not exist yet. +# +# -static-libstdc++ removes the dependency being mis-resolved, and was measured +# to be the variant that links (plain, +libiberty, and +libiberty -lgcc_s all +# fail from that directory; -static-libstdc++ passes). The sysroot -L/-rpath-link +# that LDFLAGS would otherwise contribute is dropped by not forwarding LDFLAGS. +_rb_build_ldflags='-static-libstdc++' +# BUILD_LDFLAGS does not reach these rules AT ALL from a top-level make, and +# the reason is not that the rules ignore it. +# +# gcc/Makefile does use it -- build/genversion links with +# $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) +# and overriding either BUILD_LDFLAGS or LINKER_FOR_BUILD from INSIDE build/gcc +# puts the flag in the emitted command. But BUILD_LDFLAGS and BUILD_CPPFLAGS do +# not exist in the TOP-LEVEL Makefile at all; they are gcc/Makefile variables. +# A top-level `make BUILD_LDFLAGS=...` therefore never lands in the gcc +# sub-make, which is why the generator links kept coming out bare: +# g++ -DIN_GCC -DGENERATOR_FILE build/genversion.o -o build/genversion +# +# CXX_FOR_BUILD is the knob that does reach: the top level defines it (= g++) +# and forwards it to every sub-make explicitly, and gcc/Makefile.in:870 sets +# LINKER_FOR_BUILD = $(CXX_FOR_BUILD) +# so the flag applies uniformly to every build/ generator link. Verified with +# `make -n all-gcc` from the top level: with CXX_FOR_BUILD the command becomes +# g++ -static-libstdc++ -DIN_GCC -DGENERATOR_FILE build/genversion.o -o ... +# while the BUILD_LDFLAGS form leaves it unchanged. +# +# It is passed for compiles as well as links, which is harmless -- g++ accepts +# -static-libstdc++ on a -c command line and it affects nothing there. +# +# NOTE for anyone changing this value: the top level exports it as CXX to the +# build-side subdirectories (Makefile "CXX=$(CXX_FOR_BUILD); export CXX"), so +# it is part of their configure environment. Changing it against an existing +# build/ makes autoconf refuse: +# error: `CXX' has changed since the previous run: +# in `build-x86_64-pc-linux-gnu/libcpp': +# run `make distclean' and/or `rm ./config.cache' and start over +# That is autoconf working correctly, not a defect. Wipe the build directory +# (COOKBOOK_CLEAN_BUILD=true, or make c.gcc-native) when this value changes; +# once configured with it, later incremental rebuilds are consistent. +_rb_cxx_for_build='g++ -static-libstdc++' + +# Build all-gcc FIRST, as its own make invocation, before the target libraries. +# +# all-target-libgcc installs the REDOX libgcc_s.so.1 into build/gcc/ -- the same +# directory the host-side generator links (genchecksum, genversion, ...) run +# from. The host g++ needs its own libstdc++, whose libgcc dependency resolves +# through the ld script "GROUP ( libgcc_s.so.1 -lgcc )", and that bare filename +# is matched against the current directory first -- so the HOST link binds the +# REDOX libgcc_s, which has no GCC_4.3.0-versioned soft-float symbols: +# /usr/lib/gcc/x86_64-pc-linux-gnu/16/libstdc++.so: +# undefined reference to `__letf2@GCC_4.3.0' (+ __gttf2 __eqtf2 +# __getf2 __unordtf2) +# Confirmed cwd-dependent: the identical g++ command passes from the repo root +# and fails from build/gcc. It is also why the FIRST build of this recipe +# succeeds and only rebuilds fail -- initially that file does not exist yet. +# +# Listing the goals in one -j make does not help: make interleaves them, so the +# file can appear before the generators are linked. +# +# Sequencing alone is NOT sufficient, though, and relying on it hid that: it +# only holds for a CLEAN build. Once a previous run has left the Redox +# libgcc_s.so.1 in build/gcc/, the very first all-gcc of the NEXT run links its +# generators next to that file and fails again -- which is exactly what +# happened here, in all-gcc, before any target library was rebuilt. Recipes +# must rebuild correctly on a dirty target/, so the CXX_FOR_BUILD override +# above is the actual fix and the sequencing is kept as defence in depth. +"${COOKBOOK_MAKE}" -j "${COOKBOOK_MAKE_JOBS}" CXX_FOR_BUILD="${_rb_cxx_for_build}" BUILD_CPPFLAGS="${_rb_build_cppflags}" BUILD_LDFLAGS="${_rb_build_ldflags}" all-gcc +"${COOKBOOK_MAKE}" -j "${COOKBOOK_MAKE_JOBS}" CXX_FOR_BUILD="${_rb_cxx_for_build}" BUILD_CPPFLAGS="${_rb_build_cppflags}" BUILD_LDFLAGS="${_rb_build_ldflags}" all-target-libgcc all-target-libstdc++-v3 +"${COOKBOOK_MAKE}" CXX_FOR_BUILD="${_rb_cxx_for_build}" BUILD_CPPFLAGS="${_rb_build_cppflags}" BUILD_LDFLAGS="${_rb_build_ldflags}" install-gcc install-target-libgcc install-target-libstdc++-v3 DESTDIR="${COOKBOOK_STAGE}" # Native GCC doesn't need the target prefix for tool in gcc g++ c++ cpp gcc-ar gcc-nm gcc-ranlib gcov gcov-dump gcov-tool gfortran; do @@ -109,6 +292,29 @@ ln -sf gcc "${COOKBOOK_STAGE}/usr/bin/cc" rm -f "${COOKBOOK_STAGE}"/usr/lib/libgcc_s.so* "${COOKBOOK_STAGE}"/usr/lib/libstdc++.so* rm -f "${COOKBOOK_STAGE}"/usr/lib/*.la +# Stage the static libstdc++. +# +# The comment below has always said "libgcc and libstdc++", but only libgcc was +# ever copied, and the package shipped no usable C++ runtime at all: +# - install-target-libstdc++-v3 installs the SHARED libstdc++.so* (plus +# libstdc++exp.a). libtool does not install a static libstdc++.a, even +# though the build produces one. +# - the `rm -f ... libstdc++.so*` line just above then deletes what it did +# install. +# Net result: usr/lib held libstdc++exp.a and nothing else, so a native g++ +# could compile but never link a C++ program. +# +# Take the static archive straight from the build tree. It lands in usr/lib so +# the `usr/lib/*c++*` glob in [[optional-packages]] routes it into the C++ +# package alongside cc1plus and the headers, rather than the C-only package. +_rb_libstdcxx="${COOKBOOK_BUILD}/${GNU_TARGET}/libstdc++-v3/src/.libs/libstdc++.a" +if [ -f "${_rb_libstdcxx}" ]; then + cp -a "${_rb_libstdcxx}" "${COOKBOOK_STAGE}/usr/lib/" +else + echo "ERROR: static libstdc++.a not found at ${_rb_libstdcxx}" >&2 + exit 1 +fi + # Copy libgcc and libstdc++ into target lib dir mkdir -p "${COOKBOOK_STAGE}/usr/lib/${GNU_TARGET}" # Version-globbed: a hardcoded GCC version here silently stops matching the diff --git a/local/sources/base b/local/sources/base index 70077c518b..3e4e3e4f46 160000 --- a/local/sources/base +++ b/local/sources/base @@ -1 +1 @@ -Subproject commit 70077c518b1bd4b9751d264c226441dac9a46263 +Subproject commit 3e4e3e4f46b8a95ca1a9b6812fe90ddd87f16868