You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Document the i586-only exact-float-compare test failure pattern: x87 80-bit
excess precision; -fexcess-precision=standard is a no-op; -mfpmath=sse/-msse2
is unsafe (no SSE2 in the i586 baseline -> SIGILL); fix by narrowing both
sides to float (asFloat()/cast); and verify via the server-side i586 build
(not flaky local QEMU) before the Factory SR. Real case: jsoncpp 1.9.8
ValueTest/objects, upstream PR gh#open-source-parsers/jsoncpp#1700.
Copy file name to clipboardExpand all lines: references/update-build.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -284,6 +284,7 @@ When a build fails locally, check this list before debugging from scratch.
284
284
- **A major version bump of old C code often breaks on Factory's current GCC — expect it, it is not your spec's fault.** GCC 14 turned `-Wimplicit-function-declaration`, `-Wincompatible-pointer-types` and `-Wint-conversion` into **errors** by default; GCC 15 defaults to **C23** (`-std=gnu23`), where an empty parameter list `T (*fp)()` means *zero* args (not "unspecified"), so a call `fp(arg)` fails with `too many arguments to function 'fp'`. These are hard errors, not warnings — they are not caused by `-Werror` and `-Wno-error=` will not silence the C23 one. Prefer a **targeted source patch** when there are few sites: `grep -rnE '\(\s*\*\s*[A-Za-z_]+\s*\)\s*\(\s*\)' src/*.c` counts empty-paren function-pointer declarations (ior 4.0.0 had exactly one — patched `void(*fp)()` → `void(*fp)(void*)`). `-std=gnu17` (set in `CFLAGS`; `export CFLAGS="%{optflags} -std=gnu17"` before `%cmake`) is a blunt whole-package fallback that restores pre-C23 semantics — appropriate for old K&R C (e.g. an inline `double atof();`) where patching every site is excessive. **Check upstream `main` first** — the fix is almost always already there but unreleased: `gh api repos/<o>/<r>/contents/<path>?ref=main --jq .content | base64 -d` shows the current file, so you can backport the exact upstream change and tag it `PATCH-FIX-UPSTREAM`.
285
285
-**C23 also promotes `bool`/`true`/`false`/`nullptr`/`static_assert`/`thread_local` to keywords**, so old code that does `typedef _Bool bool;` (or `typedef unsigned char bool;`) now fails with `'bool' cannot be defined via 'typedef'`. Same `-std=gnu17` fix.
286
286
-**A package can FTBFS on *some arches only* because upstream forces the C standard for just one arch.** Watch for a CMake/configure branch like `if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") … set(CMAKE_C_FLAGS "… -std=gnu99") …`: x86_64 then gets a pre-C23 standard and builds, while aarch64/ppc64le/s390x inherit GCC 15's C23 default and break — so Factory shows the package green on x86_64 but **failed on every other arch**. Fix by forcing the standard for *all* arches (`export CFLAGS="%{optflags} -std=gnu17"` before `%cmake`). (Real case: blosc 1.21.6 — `bool` typedef in `shuffle.c`, only non-x86 failed.)
287
+
- **An i586-only `%check` failure on an exact float==double comparison is x87 excess precision — and the two "obvious" fixes are a no-op and a footgun respectively.** A test that stores a `float` literal into a `double` (or otherwise round-trips float↔double) and then asserts *exact* equality passes on x86_64/aarch64/… but fails **only on i586**, because GCC defaults to x87 (`-mfpmath=387`, 80-bit) on 32-bit x86: the stored/reloaded value comes back as the true double instead of the float-widened value (e.g. `0.12345` vs `0.12345000356435776`). Two tempting fixes are wrong: (a) **`-fexcess-precision=standard` is usually a no-op** here — it governs *expression* excess precision, not the x87 store/convert, so it builds but doesn't change the result (verify per the "prove a flag fix is effective" HARD RULE above — diff the failing test output, don't assume). (b) **`-mfpmath=sse -msse2` is unsafe**: the openSUSE i586 baseline has **no SSE2** (`Optflags: i586` carries no `-march`, so it's the `i586-suse-linux`/Pentium default; the separate `i686` line is also pre-SSE2), so forcing SSE2 makes the library **SIGILL on the very hardware the i586 port targets**. The correct fix is to make the *test* representation-robust — **narrow both sides back to `float`** (cast, or the project's `asFloat()`/`toFloat()` accessor) so they collapse to the same value on every arch; this keeps the round-trip check and is upstreamable. **Verifying an i586 fix from a non-x86 host:** local `osc build … i586` runs under QEMU user emulation and is slow/flaky (package-cache `hdrmd5` mismatch loops); instead commit to the devel project and watch the **server-side** i586 result, confirming the specific test now passes, *before* the Factory SR. (Real case: jsoncpp 1.9.8 — `ValueTest/objects` compared `0.12345f` exactly against the stored double; patched to `numericFound->asFloat()`, server i586 went green, submitted upstream as gh#open-source-parsers/jsoncpp#1700.)
287
288
-**The C++ analogue: a dependency's headers may newly *require* C++17, while the project's own code needs an older standard — and C++17 library names can clash with the project's identifiers.** Current **googletest** headers `#error` on `< C++17`; building the test suite then forces C++17 on code that may use constructs C++17 removed or names it now defines. Set `CMAKE_CXX_STANDARD 17` (or `-std=gnu++17`) for the whole package, and fix clashes by qualifying: under `using namespace std;` + `using namespace itpp;`, a call to the project's `any(...)` became ambiguous with C++17's `std::any` → qualify as `itpp::any(...)`. (Real case: itpp — re-introduced to Factory after this fixed the FTBFS that got it bot-deleted.)
288
289
- **A big version jump can cross an upstream *build-system migration* — budget for rewriting `%build`/`%check`/`%install` and the whole `BuildRequires` set, not just bumping `Version`.** The common case is **Autotools → CMake**: replace `autoreconf`/`%configure`/`%make_build` with `%cmake`/`%cmake_build` (add `BuildRequires: cmake` + `ninja` and `%define __builder ninja`), `make check` → `%ctest`, `%make_install` → `%cmake_install`, and **drop `autoconf`/`automake`/`libtool`**. Map the old `--with-foo`/`--enable-foo` switches to the new `-DWITH_FOO=`/`-DBUILD_FOO=`/`-DENABLE_FOO=` options — read them from `option()`/`cmake_dependent_option()` in the top `CMakeLists.txt` (don't guess names). The same jump often **removes whole features** (and thus their deps) — read the release notes / `doc/dependencies.md`: e.g. bitcoin 28→31 dropped BerkeleyDB (legacy wallet), miniupnpc (UPnP), protobuf+openssl (BIP70), so `libdb-4_8-devel`/`libminiupnpc-devel`/`pkgconfig(protobuf)`/`pkgconfig(openssl)` all became dead BRs. A **Qt5 → Qt6** migration rides along similarly: take the required modules from the upstream `find_package(Qt6 …COMPONENTS…)` list, express them as `pkgconfig(Qt6Core)` … (with the upstream min version, e.g. `>= 6.2`); `lrelease`/`Qt6LinguistTools` comes from a *separate* `qt6-linguist-devel` (no pkgconfig form, like its qt5 sibling); and **rename the GUI subpackage** (`foo-qt5` → `foo-qt6`) with **`Obsoletes: foo-qt5 < %{version}-%{release}` only — do NOT add a matching `Provides: foo-qt5`.** The `Obsoletes` carries the upgrade (the new package replaces the installed `foo-qt5`), but a `Provides: foo-qt5` would be a *lie*: the Qt6 build does not provide the "qt5" capability, and falsely advertising it could wrongly satisfy something that genuinely wants the qt5 GUI. (Real case: a Factory reviewer flagged exactly this on the bitcoin 31.0 SR — *"that is likely a lie… the qt5 capability is not available; only keep the obsoletes"*.) This is the general rule for a **flavor/toolkit rename**: `Provides` of the old name is only honest when the new package is a true drop-in providing the same capability; for a Qt5→Qt6 (or similar) change it isn't, so `Obsoletes`-only. Disable optional new subsystems that drag in heavy new deps unless wanted (bitcoin's `-DENABLE_IPC=OFF` avoids Cap'n Proto).
289
290
- **For a hard repackaging problem (build-system migration, install-layout change, soname-scheme change), consult how OTHER distros already package it before inventing a solution.** Pull the recipe from a fast-moving distro: Arch `PKGBUILD` (`https://gitlab.archlinux.org/archlinux/packaging/packages/<pkg>/-/raw/main/PKGBUILD`), AUR (`https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=<pkg>`), Alpine `APKBUILD`, Fedora (`https://src.fedoraproject.org/rpms/<pkg>/raw/rawhide/f/<pkg>.spec`), Debian. They've usually already solved the same wall, and their `prepare()`/`build()`/`package()` shows the canonical patch or install-rearrange. (Real case: vapoursynth R74+ switched to a **wheel-only meson build** that installs everything into Python `site-packages`; Arch's PKGBUILD showed the approach — build the wheel and symlink/redirect the libs/headers/pkgconfig into FHS, with the proper upstream SONAME `libvapoursynth.so.4`.) **Corollary:** if the package is *not* packaged by any of them (e.g. it's normally vendored into a larger project), then **upstream's own files are authoritative** — follow upstream's `*.service`/install layout/defaults rather than guessing. (Real case: nqptp is bundled into shairport-sync everywhere, not packaged standalone — so upstream's `DynamicUser` service file was the reference, doubly trustworthy because the same author maintains both ends.)
0 commit comments