1151 lines
42 KiB
Markdown
1151 lines
42 KiB
Markdown
# Package Build Quirks — Known Cross-Compilation Issues and Fixes
|
|
|
|
**Created:** 2026-06-19
|
|
**Scope:** All recipes in `recipes/` and `local/recipes/` that have known build quirks
|
|
**Purpose:** Central reference for cross-compilation issues encountered when building
|
|
Red Bear OS packages, their root causes, and fixes.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Building packages for the `x86_64-unknown-redox` target from a Linux x86_64 host
|
|
involves a cross-compilation environment managed by the cookbook tool. Several
|
|
packages require specific adjustments to their recipe or source to build correctly
|
|
in this environment. This document captures all known quirks and their fixes.
|
|
|
|
---
|
|
|
|
## Cookbook Environment: `DYNAMIC_INIT`
|
|
|
|
### Problem
|
|
|
|
The cookbook's `DYNAMIC_INIT` function (defined in `src/cook/script.rs`) sets up
|
|
the cross-compilation environment. **It overwrites several environment variables
|
|
entirely**, including:
|
|
|
|
- `CFLAGS` — set to `-I<sysroot>/include`
|
|
- `CXXFLAGS` — set to `-I<sysroot>/include`
|
|
- `LDFLAGS` — set to `-L<sysroot>/lib --static -L<prefix>/lib`
|
|
- `CPPFLAGS` — set to `-I<sysroot>/include`
|
|
- `PKG_CONFIG_LIBDIR`, `PKG_CONFIG_SYSROOT_DIR`
|
|
- `RUSTFLAGS`
|
|
- `CARGO_TARGET_DIR`
|
|
- `PATH`
|
|
|
|
### Impact
|
|
|
|
Any `export FOO="..."` that runs **BEFORE** `DYNAMIC_INIT` will be overwritten.
|
|
Any `export FOO="..."` that runs **AFTER** `DYNAMIC_INIT` will persist.
|
|
|
|
### Fix Pattern
|
|
|
|
For variables that `DYNAMIC_INIT` overwrites, you must set them **AFTER**
|
|
`DYNAMIC_INIT`:
|
|
|
|
```bash
|
|
# WRONG: LDFLAGS overwritten by DYNAMIC_INIT
|
|
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
|
DYNAMIC_INIT
|
|
# At this point, LDFLAGS = "-L<sysroot>/lib --static ..." (our flag is gone)
|
|
|
|
# CORRECT: Set after DYNAMIC_INIT preserves the flag
|
|
DYNAMIC_INIT
|
|
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
|
# At this point, LDFLAGS = "-Wl,--allow-multiple-definition -L<sysroot>/lib ..."
|
|
```
|
|
|
|
For `CFLAGS` specifically, the pre-`DYNAMIC_INIT` approach **can** work because
|
|
the `reexport_flags` function (called by `cookbook_configure`) re-reads the
|
|
current `$CFLAGS` and incorporates it into `CFLAGS_x86_64_unknown_redox`. But
|
|
this is fragile — the safest approach is to set flags **AFTER** `DYNAMIC_INIT`
|
|
for ALL variables.
|
|
|
|
### Exceptions
|
|
|
|
`CFLAGS` set BEFORE `DYNAMIC_INIT` works because `reexport_flags` (called
|
|
inside `cookbook_configure`) reads `$CFLAGS` at configure time and prepends it
|
|
to `CFLAGS_x86_64_unknown_redox`. However, `LDFLAGS` set BEFORE `DYNAMIC_INIT`
|
|
is overwritten by `DYNAMIC_INIT` and NOT re-read by `reexport_flags`.
|
|
|
|
**Safe rule: Set ALL custom flags AFTER `DYNAMIC_INIT`.**
|
|
|
|
### Reference
|
|
|
|
- `src/cook/script.rs` — `DYNAMIC_INIT` function definition
|
|
- `src/cook/script.rs` — `reexport_flags` function definition
|
|
|
|
---
|
|
|
|
## Package: m4 (GNU M4 macro processor)
|
|
|
|
**Recipe:** `local/recipes/dev/m4/recipe.toml`
|
|
**Source:** `https://ftp.gnu.org/gnu/m4/m4-1.14.21.tar.xz`
|
|
**Template:** `custom` (uses `cookbook_configure`)
|
|
|
|
### Quirk 1: `-fcommon` Required (GCC 10+ Compatibility)
|
|
|
|
**Problem:** GCC 10+ defaults to `-fno-common`, which causes multiple definition
|
|
errors for gnulib's `rpl_realloc` wrapper. The gnulib replacement function is
|
|
defined as a tentative symbol across multiple translation units.
|
|
|
|
**Error:**
|
|
```
|
|
/usr/bin/x86_64-unknown-redox-ld: libm4.a(libm4_a-malloc.o):(.bss+0x0):
|
|
multiple definition of `rpl_realloc';
|
|
libm4_a-realloc.o:(.bss+0x0): first defined here
|
|
```
|
|
|
|
**Fix:** Add `-fcommon` to CFLAGS:
|
|
```bash
|
|
export CFLAGS="-fcommon ${CFLAGS}"
|
|
```
|
|
|
|
**Placement:** BEFORE `DYNAMIC_INIT` (works because `reexport_flags` re-reads
|
|
`$CFLAGS` at configure time).
|
|
|
|
**Better placement (recommended for future):** AFTER `DYNAMIC_INIT` — same
|
|
result, more robust.
|
|
|
|
### Quirk 2: `--allow-multiple-definition` Required (Linker)
|
|
|
|
**Problem:** Even with `-fcommon`, the linker encounters multiple definitions of
|
|
`rpl_realloc` because gnulib provides it in multiple object files and the
|
|
static library linking order causes duplicates.
|
|
|
|
**Error:**
|
|
```
|
|
/usr/bin/x86_64-unknown-redox-ld: libm4.a(libm4_a-malloc.o):(.bss+0x0):
|
|
multiple definition of `rpl_realloc';
|
|
libm4_a-realloc.o:(.bss+0x0): first defined here
|
|
/usr/bin/x86_64-unknown-redox-ld: error: ld returned 1 exit status
|
|
```
|
|
|
|
**Fix:** Add `--allow-multiple-definition` to LDFLAGS:
|
|
```bash
|
|
DYNAMIC_INIT
|
|
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
|
```
|
|
|
|
**Placement:** **MUST be AFTER `DYNAMIC_INIT`** — `DYNAMIC_INIT` overwrites
|
|
`LDFLAGS` entirely. Setting it before `DYNAMIC_INIT` has no effect.
|
|
|
|
### Quirk 3: Locale Platform Detection
|
|
|
|
**Problem:** m4's gnulib `getlocalename_l-unsafe.c` has a Redox case guarded by
|
|
`HAVE_GETLOCALENAME_L`, which relibc doesn't define. The file hits an `#error`
|
|
when neither the guard nor the platform detection matches.
|
|
|
|
**Error:**
|
|
```
|
|
error: #error "Please port gnulib getlocalename_l-unsafe.c to your platform"
|
|
```
|
|
|
|
**Fix:** Changed the guard from `__redox__ && HAVE_GETLOCALENAME_L` to just
|
|
`__redox__` and return `"C"` (Redox only supports the C/POSIX locale).
|
|
|
|
**File:** `lib/getlocalename_l-unsafe.c` — line ~661:
|
|
```c
|
|
#elif defined __redox__
|
|
return "C";
|
|
```
|
|
|
|
**Applied via:** `local/recipes/dev/m4/source/` (local recipe with source bundled)
|
|
|
|
### Quirk 4: Configure Cache Variables
|
|
|
|
**Problem:** m4's `configure` script tests for functions that don't exist or
|
|
behave differently on Redox, causing false negatives.
|
|
|
|
**Fix:** Pass cache variables to skip problematic tests:
|
|
```bash
|
|
COOKBOOK_CONFIGURE_FLAGS+=(
|
|
--disable-nls
|
|
ac_cv_func___freadahead=yes
|
|
ac_cv_have_decl___freadahead=yes
|
|
gl_cv_header_wchar_h_correct_inline=yes
|
|
gl_cv_func_btowc_nul=yes
|
|
gl_cv_func_btowc_consistent=yes
|
|
gl_cv_onwards_func___freadahead=yes
|
|
)
|
|
```
|
|
|
|
### Quirk 5: wchar.h Circular Include (gnulib + relibc)
|
|
|
|
**Problem:** m4's gnulib generates a `wchar.h` wrapper that does
|
|
`#include_next <wchar.h>`. relibc's `wchar.h` included `<stdio.h>` at line 4,
|
|
before defining `wint_t` (line 20) and `mbstate_t` (line 41). The circular
|
|
chain:
|
|
|
|
```
|
|
wchar.h -> stdio.h -> stdint.h -> gnulib inttypes.h -> sysroot inttypes.h -> #include wchar.h -> BACK TO GNULIB wchar.h (guard not set!)
|
|
```
|
|
|
|
caused gnulib's `wchar.h` to process its replacements before
|
|
`wint_t`/`mbstate_t` were defined, producing `unknown type name 'wint_t'` and
|
|
`unknown type name 'mbstate_t'`.
|
|
|
|
**Error:**
|
|
```
|
|
error: unknown type name 'wint_t'
|
|
error: unknown type name 'mbstate_t'
|
|
```
|
|
|
|
**Root cause:** relibc's `wchar.h` included `<stdio.h>` before defining
|
|
`wint_t`/`mbstate_t`, AND relibc's `inttypes.h` included `<wchar.h>` instead of
|
|
`<stdint.h>` + `<stddef.h>` per POSIX spec.
|
|
|
|
**Fix:** Two parts, both in the relibc fork (`local/sources/relibc/`):
|
|
|
|
1. `src/header/wchar/cbindgen.toml`: Moved `stdio.h`/`time.h` from
|
|
`sys_includes` into `after_includes`, placed AFTER the
|
|
`wchar_t`/`wint_t`/`mbstate_t` typedefs. Also defined `mbstate_t` in
|
|
`after_includes` with a `_RELIBC_MBSTATE_T` guard and excluded it from
|
|
cbindgen export via `[export] exclude = ["mbstate_t"]`.
|
|
2. `src/header/inttypes/cbindgen.toml`: Changed `sys_includes` from
|
|
`["wchar.h"]` to `["stdint.h", "stddef.h"]` per POSIX spec (`inttypes.h`
|
|
only needs `wchar_t` from `stddef.h`, not the full `wchar.h`).
|
|
|
|
**Reference:** See the relibc section below (Quirk 3) for the same fix
|
|
documented from the relibc side. Commits `d28963d` (wchar.h fix) and
|
|
`a2e4cd2` (inttypes.h fix) in `local/sources/relibc/`.
|
|
|
|
### Quirk 6: `__freadahead` Prefix Staleness
|
|
|
|
**Problem:** The recipe sets `ac_cv_func___freadahead=yes` to tell gnulib that
|
|
relibc provides `__freadahead`. The function IS implemented in relibc's
|
|
`src/header/stdio/ext.rs` (commit `047e7c0`). But the PREFIX `libc.a` was built
|
|
before that commit, so the symbol was missing from the compiled library.
|
|
|
|
**Error:**
|
|
```
|
|
undefined reference to `__freadahead'
|
|
```
|
|
|
|
**Fix:** Rebuild relibc in the prefix after adding new functions:
|
|
```bash
|
|
touch relibc && make prefix
|
|
```
|
|
|
|
**Prevention:** The build script now warns when prefix artifacts are older than
|
|
fork commits.
|
|
|
|
### Complete Recipe
|
|
|
|
```toml
|
|
[source]
|
|
tar = "https://ftp.gnu.org/gnu/m4/m4-1.14.21.tar.xz"
|
|
patches = ["redox.patch"]
|
|
|
|
[build]
|
|
template = "custom"
|
|
script = """
|
|
export CFLAGS="-fcommon ${CFLAGS}"
|
|
DYNAMIC_INIT
|
|
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
|
COOKBOOK_CONFIGURE_FLAGS+=(
|
|
--disable-nls
|
|
ac_cv_func___freadahead=yes
|
|
ac_cv_have_decl___freadahead=yes
|
|
gl_cv_header_wchar_h_correct_inline=yes
|
|
gl_cv_func_btowc_nul=yes
|
|
gl_cv_func_btowc_consistent=yes
|
|
gl_cv_onwards_func___freadahead=yes
|
|
)
|
|
cookbook_configure
|
|
"""
|
|
|
|
[package]
|
|
description = "GNU M4 macro processor"
|
|
```
|
|
|
|
**Note:** Quirks 5 and 6 do not require changes to `recipe.toml`. Quirk 5 is
|
|
fixed in the relibc fork (header generation), and Quirk 6 is resolved by
|
|
rebuilding the relibc prefix artifact (`touch relibc && make prefix`).
|
|
|
|
---
|
|
|
|
## Package: ninja-build (Ninja build system)
|
|
|
|
**Recipe:** `local/recipes/dev/ninja-build/recipe.toml`
|
|
**Source:** `https://github.com/ninja-build/ninja` (v1.13.1)
|
|
**Template:** `cmake`
|
|
|
|
### Quirk: `BUILD_TESTING=OFF` Required (Cross-Compilation)
|
|
|
|
**Problem:** ninja-build's `CMakeLists.txt` includes `CTest`, which enables
|
|
`BUILD_TESTING=ON` by default. Tests require Google Test (gtest), which is found
|
|
on the host system at `/usr/include/gtest/`. When the C++ compiler includes
|
|
gtest headers, it transitively includes the host `/usr/include/stdlib.h`, which
|
|
conflicts with the Redox sysroot `stdlib.h`.
|
|
|
|
**Error:**
|
|
```
|
|
/usr/include/stdlib.h:67:5: error: conflicting declaration 'typedef struct div_t div_t'
|
|
/usr/include/stdlib.h:75:5: error: conflicting declaration 'typedef struct ldiv_t ldiv_t'
|
|
/usr/include/stdlib.h:85:5: error: conflicting declaration 'typedef struct lldiv_t lldiv_t'
|
|
/usr/include/stdlib.h:761:18: error: conflicting declaration of 'int at_quick_exit(void (*)())' with 'C++' linkage
|
|
```
|
|
|
|
Additionally, the Redox sysroot `stdlib.h` uses `__noreturn` and `__deprecated`
|
|
attributes that C++ doesn't recognize, causing further errors when test files
|
|
are compiled.
|
|
|
|
**Root cause:** This is NOT a Redox capability gap — it is a fundamental
|
|
cross-compilation constraint. Test suites require a test framework (gtest) that
|
|
exists on the host, and tests are designed to run on the target platform, not
|
|
during cross-compilation. Building tests during cross-compile is incorrect.
|
|
|
|
**Fix:** Disable test building via CMake flag:
|
|
```toml
|
|
[build]
|
|
template = "cmake"
|
|
cmakeflags = ["-DBUILD_TESTING=OFF"]
|
|
```
|
|
|
|
This is standard practice for cross-compilation — the ninja binary itself is
|
|
the deliverable, not its test suite.
|
|
|
|
### Complete Recipe
|
|
|
|
```toml
|
|
[source]
|
|
git = "https://github.com/ninja-build/ninja"
|
|
rev = "v1.13.1"
|
|
|
|
[build]
|
|
template = "cmake"
|
|
cmakeflags = ["-DBUILD_TESTING=OFF"]
|
|
|
|
[package]
|
|
description = "Ninja build system"
|
|
```
|
|
|
|
---
|
|
|
|
## Package: kernel (Redox kernel — local fork)
|
|
|
|
**Recipe:** `recipes/core/kernel/recipe.toml` (uses `path = "../../../local/sources/kernel"`)
|
|
**Source:** `local/sources/kernel/` (local fork)
|
|
|
|
### Quirk: `-Zjson-target-spec` Cargo Flag
|
|
|
|
**Problem:** The upstream kernel Makefile passes `-Zjson-target-spec` as a cargo
|
|
CLI flag. The redoxer build environment's cargo accepts it in `cargo -Z help`
|
|
but rejects it when invoked through `make` inside `redoxer env bash -ex`.
|
|
|
|
**Fix:** Use the env-var form instead of the CLI flag in the kernel Makefile:
|
|
```makefile
|
|
export CARGO_UNSTABLE_JSON_TARGET_SPEC=true
|
|
# Remove -Zjson-target-spec from the cargo rustc command line
|
|
```
|
|
|
|
---
|
|
|
|
## General Cross-Compilation Patterns
|
|
|
|
### Pattern: Disable Tests During Cross-Compilation
|
|
|
|
When a package's build system includes test targets (cmake `BUILD_TESTING`,
|
|
automake `TESTS`, meson `tests`), tests must be disabled during cross-compilation.
|
|
|
|
**Why:** Tests require:
|
|
1. A test framework (gtest, catch2, etc.) that exists on the HOST, not the TARGET
|
|
2. The test framework headers transitively include HOST system headers
|
|
3. HOST system headers conflict with TARGET sysroot headers (type redefinition)
|
|
4. Tests are designed to RUN on the target, not during cross-compile
|
|
|
|
**How (cmake):**
|
|
```toml
|
|
cmakeflags = ["-DBUILD_TESTING=OFF"]
|
|
```
|
|
|
|
**How (meson):**
|
|
```toml
|
|
mesonflags = ["-Dtests=false"]
|
|
```
|
|
|
|
**How (configure/automake):**
|
|
```bash
|
|
COOKBOOK_CONFIGURE_FLAGS+=(--disable-tests)
|
|
# or if no --disable-tests option:
|
|
COOKBOOK_CONFIGURE_FLAGS+=(ac_cv_prog_have_gtest=no)
|
|
```
|
|
|
|
### Pattern: Gnulib Compatibility (`-fcommon` and `--allow-multiple-definition`)
|
|
|
|
Packages using gnulib (m4, bison, flex, autoconf, etc.) may need:
|
|
|
|
1. `-fcommon` in CFLAGS — gnulib provides replacement functions (`rpl_malloc`,
|
|
`rpl_realloc`) that are defined as tentative symbols in multiple translation
|
|
units. GCC 10+ defaults to `-fno-common`, causing multiple definition errors.
|
|
|
|
2. `-Wl,--allow-multiple-definition` in LDFLAGS — Even with `-fcommon`, the
|
|
linker may encounter duplicate definitions from static library archives.
|
|
|
|
**Note:** These flags should be added per-recipe only when needed, not globally.
|
|
|
|
### Pattern: Configure Cache Variables for Autoconf Packages
|
|
|
|
Autoconf-based packages (m4, bison, flex, etc.) run `configure` tests that may
|
|
fail on Redox because:
|
|
- The function exists but behaves differently
|
|
- The function doesn't exist (but the test expects it)
|
|
- Cross-compilation can't run test programs
|
|
|
|
Fix by passing cache variables to skip problematic tests:
|
|
```bash
|
|
COOKBOOK_CONFIGURE_FLAGS+=(
|
|
ac_cv_func___freadahead=yes
|
|
ac_cv_have_decl___freadahead=yes
|
|
gl_cv_header_wchar_h_correct_inline=yes
|
|
)
|
|
```
|
|
|
|
### Pattern: NLS Disabled
|
|
|
|
Most packages should disable NLS (Native Language Support) for Redox:
|
|
```bash
|
|
COOKBOOK_CONFIGURE_FLAGS+=(--disable-nls)
|
|
```
|
|
|
|
Redox doesn't have a full gettext/libintl stack. The `--disable-nls` flag is
|
|
standard for cross-compilation targets that don't need internationalization.
|
|
|
|
### Pattern: C++ Cross-Compilation Header Isolation
|
|
|
|
When compiling C++ files for Redox, the compiler must use the Redox sysroot
|
|
headers, not the host headers. The cookbook sets up `--sysroot` via the CMake
|
|
toolchain file and `CFLAGS_x86_64_unknown_redox`/`CXXFLAGS_x86_64_unknown_redox`.
|
|
|
|
If host headers leak in (usually through `#include <gtest>` or similar), the fix
|
|
is to remove the dependency on host headers, not to try to isolate the include
|
|
path further. This typically means disabling tests or the feature that requires
|
|
the host-only dependency.
|
|
|
|
---
|
|
|
|
## Package: libiconv (GNU libiconv 1.17)
|
|
|
|
### Quirk: Libtool Version Mismatch (2.6.0.23-b08cb)
|
|
|
|
#### Problem
|
|
|
|
libiconv 1.17 ships a pre-generated `configure` script that embeds the
|
|
libtool release identifier at configure-generation time. On Debian hosts
|
|
where the system libtool has been updated to `2.6.0.23-b08cb`, the bundled
|
|
configure declares `macro_version='2.6.0'`, but the running `libtool`
|
|
binary advertises `VERSION=2.6.0.23-b08cb` and `package_revision=2.6.0.23`.
|
|
At compile time, libtool aborts with:
|
|
|
|
```
|
|
libtool: Version mismatch error. This is libtool 2.6.0.23-b08cb, revision 2.6.0.23,
|
|
libtool: but the definition of this LT_INIT comes from revision 2.6.0.
|
|
libtool: You should recreate aclocal.m4 with macros from revision 2.6.0.23
|
|
libtool: of libtool 2.6.0.23-b08cb and run autoconf again.
|
|
```
|
|
|
|
This affects the nested `libcharset` subdir as well — both configure
|
|
scripts need patching.
|
|
|
|
#### Root Cause
|
|
|
|
`ltmain.sh` (the libtool script template that ships with the host's
|
|
`libtool` package) is the source of truth for the running libtool's
|
|
`VERSION` and `package_revision`. The bundled `configure` script was
|
|
generated against an older libtool and embeds the older `macro_version`/
|
|
`macro_revision` strings. When libtool runs at compile time it compares
|
|
its own `VERSION`/`package_revision` against the values configure
|
|
generated, and aborts when they differ.
|
|
|
|
#### Fix
|
|
|
|
Source the shared helper from the build script and rewrite both
|
|
configure scripts' `macro_version` and `macro_revision` to match the host
|
|
libtool:
|
|
|
|
```bash
|
|
. "${COOKBOOK_ROOT}/local/scripts/lib/libtool-version-sync.sh"
|
|
redbear_sync_libtool_version \
|
|
"${COOKBOOK_SOURCE}/configure" \
|
|
"${COOKBOOK_SOURCE}/libcharset/configure"
|
|
```
|
|
|
|
The helper detects the host libtool version (via `/usr/bin/libtool
|
|
--version` — **must be the absolute path, not `command -v libtool`,
|
|
because the cookbook prepends the Redox cross sysroot's `bin/` to PATH
|
|
and `command -v libtool` would return the Redox-target libtool
|
|
`2.5.4-redox-9510` instead of the host toolchain's libtool**) and
|
|
rewrites the known bundled version strings (`2.4.7`, `2.5.4-redox-9510`,
|
|
`2.6.0`) to the host values. Other recipes that bundle pre-generated
|
|
configure scripts (older gettext, autotools packages from before the
|
|
host libtool was updated) can use the same helper.
|
|
|
|
#### Reference
|
|
|
|
- `local/scripts/lib/libtool-version-sync.sh` — shared helper
|
|
- `recipes/libs/libiconv/recipe.toml` — usage in the [build] script
|
|
- `redoxer` host: `libtool (GNU libtool) 2.6.0.23-b08cb`
|
|
- Upstream libtool version detection:
|
|
- `libtool --version` (preferred)
|
|
- `VERSION=` line in `/usr/share/libtool/build-aux/ltmain.sh` (fallback)
|
|
|
|
---
|
|
|
|
## Package: gnu-binutils (GNU Binutils 2.43.1)
|
|
|
|
**Recipe:** `recipes/tools/gnu-binutils/recipe.toml`
|
|
**Source:** `https://ftp.gnu.org/gnu/binutils/binutils-2.43.1.tar.xz`
|
|
**Template:** `custom` (uses `cookbook_configure`)
|
|
|
|
### Quirk: Autoconf Version Lock — Skip Autoreconf
|
|
|
|
**Problem:** Binutils 2.43.1 ships `config/override.m4` which enforces
|
|
**exactly** Autoconf 2.69 via `_GCC_AUTOCONF_VERSION_CHECK`. If the host
|
|
has Autoconf 2.73 (common on modern Debian/Ubuntu), autoreconf aborts:
|
|
|
|
```
|
|
configure.ac:21: error: Please use exactly Autoconf 2.69 instead of 2.73.
|
|
```
|
|
|
|
The original recipe used `COOKBOOK_AUTORECONF=autoreconf2.69` which
|
|
requires the Debian-specific `autoconf2.69` package — not available on
|
|
all distros.
|
|
|
|
**Root cause:** GCC/Binutils lock their autoreconf to a specific Autoconf
|
|
version. This is intentional upstream behavior, not a bug.
|
|
|
|
**Fix:** Skip the autoreconf step entirely. The source tarball ships with
|
|
pre-generated `configure` scripts that work correctly without regeneration.
|
|
The `01_build_fix.patch` modifies `configure.ac`, but the pre-generated
|
|
`configure` scripts remain functional for cross-compilation.
|
|
|
|
**Recipe change:** Removed the `autotools_recursive_regenerate` call and
|
|
the `COOKBOOK_AUTORECONF` override from the fetch script. Only the
|
|
`config.sub`/`config.guess`/`install-sh` copy step remains.
|
|
|
|
---
|
|
|
|
## Package: gettext (GNU gettext 0.22.5)
|
|
|
|
**Recipe:** `recipes/tools/gettext/recipe.toml`
|
|
**Source:** `https://ftp.gnu.org/gnu/gettext/gettext-0.22.5.tar.gz`
|
|
**Template:** `custom` (uses `cookbook_configure`)
|
|
|
|
### Quirk: `libintl.a` Not Installed by Default
|
|
|
|
**Problem:** gettext's `make install` skips installing `libintl.a` and
|
|
`libintl.h`. The Makefile has `install-exec-libintl` **commented out**
|
|
with the note: "We must not install the libintl.h/libintl.la files."
|
|
|
|
Downstream packages (glib, etc.) that depend on `intl` via meson's
|
|
dependency lookup fail with:
|
|
|
|
```
|
|
Run-time dependency intl found: NO (tried builtin and system)
|
|
```
|
|
|
|
**Root cause:** gettext's configure detects the C library might already
|
|
provide gettext functions and disables separate `libintl` installation.
|
|
On Redox (relibc), gettext functions are NOT provided by the C library,
|
|
so `libintl` must be installed separately.
|
|
|
|
**Fix:** Two changes in the recipe build script:
|
|
|
|
1. Pass `--with-included-gettext` to configure to force building
|
|
`libintl` from the included source.
|
|
2. Manually install `libintl.a` and `libintl.h` after `cookbook_configure`:
|
|
|
|
```bash
|
|
cookbook_configure
|
|
cp -f gettext-runtime/intl/.libs/libgnuintl.a "${COOKBOOK_STAGE}/usr/lib/libintl.a"
|
|
cp -f gettext-runtime/intl/libgnuintl.h "${COOKBOOK_STAGE}/usr/include/libintl.h"
|
|
```
|
|
|
|
The library is built as `libgnuintl.a` (GNU internal name) and must be
|
|
installed as `libintl.a` (POSIX name that meson/pkg-config expects).
|
|
|
|
---
|
|
|
|
## Package: glib (GLib 2.87.0)
|
|
|
|
**Recipe:** `recipes/libs/glib/recipe.toml`
|
|
**Source:** `https://download.gnome.org/sources/glib/2.87/glib-2.87.0.tar.xz`
|
|
**Template:** `custom` (uses `cookbook_meson`)
|
|
|
|
### Quirk: Source Tarball Contains `.orig` Files (False Positive in Patch Checker)
|
|
|
|
**Problem:** glib's source tarball legitimately includes `.orig` files
|
|
as part of its test suite:
|
|
|
|
```
|
|
gio/tests/org.gtk.test.gschema.xml.orig
|
|
gio/tests/org.gtk.test.gschema.override.orig
|
|
```
|
|
|
|
The cookbook's atomic patch checker (`src/cook/fetch.rs`) detects `.orig`
|
|
files after patch application and treats them as evidence of failed hunks,
|
|
rolling back the patch and aborting the build.
|
|
|
|
**Root cause:** The patch checker did not distinguish between pre-existing
|
|
`.orig` files (from the source tarball) and newly-created `.orig` files
|
|
(from `patch` command failures).
|
|
|
|
**Fix:** Updated the atomic patch checker in `src/cook/fetch.rs` to
|
|
snapshot pre-existing `.orig` files before patch application, and only
|
|
flag `.orig` files that were NOT in the pre-existing set. The
|
|
`--no-backup-if-mismatch` flag (already used) prevents `patch` from
|
|
creating new `.orig` files, so any `.orig` file found after patching
|
|
that was in the pre-existing set is safe to ignore.
|
|
|
|
---
|
|
|
|
## Package: relibc (Redox C Library — local fork)
|
|
|
|
**Recipe:** `recipes/core/relibc/recipe.toml` (uses `path = "../../../local/sources/relibc"`)
|
|
**Source:** `local/sources/relibc/` (local fork)
|
|
|
|
### Quirk 1: cbindgen Generates `...` Instead of `va_list`
|
|
|
|
**Problem:** cbindgen translates Rust's `VaList<'_>` type as `...`
|
|
(variadic) in generated C headers. This affects all `v*printf` functions:
|
|
|
|
```c
|
|
// Generated (WRONG):
|
|
int vsnprintf(char *s, size_t n, const char *format, ...);
|
|
|
|
// Expected (CORRECT):
|
|
int vsnprintf(char *s, size_t n, const char *format, va_list ap);
|
|
```
|
|
|
|
This breaks C++ standard library code that takes the address of
|
|
`vsnprintf` (e.g., `std::to_string(float)` → `__to_xstring(&std::vsnprintf, ...)`),
|
|
causing compilation failures in Qt6 and other C++ packages.
|
|
|
|
**Root cause:** cbindgen does not natively understand the `va_list` crate's
|
|
`VaList` type and defaults to generating `...`.
|
|
|
|
**Fix:** Post-generation `sed` in the relibc recipe build script:
|
|
|
|
```bash
|
|
sed -i '/^int vfprintf(/s/\\.\\.\\./va_list ap/' "${COOKBOOK_STAGE}/usr/include/stdio.h"
|
|
sed -i '/^int vsnprintf(/s/\\.\\.\\./va_list ap/' "${COOKBOOK_STAGE}/usr/include/stdio.h"
|
|
sed -i '/^int vsprintf(/s/\\.\\.\\./va_list ap/' "${COOKBOOK_STAGE}/usr/include/stdio.h"
|
|
```
|
|
|
|
**Note:** The `\\.` sequences are required because TOML triple-quoted
|
|
strings interpret `\\` as a literal `\`, producing the sed pattern `\.\.\.`
|
|
|
|
### Quirk 2: VaList API Version Mismatch Between Toolchains
|
|
|
|
**Problem:** relibc HEAD uses `VaList<'a>` (1 lifetime) and
|
|
`VaList::next_arg()` from Rust 1.98-dev. The PREFIX toolchain
|
|
(nightly-2025-11-15) has the older `VaList<'a, 'f: 'a>` (2 lifetimes)
|
|
with no `next_arg()` method.
|
|
|
|
When building via `make live`, `mk/prefix.mk:24` exports
|
|
`REDOXER_TOOLCHAIN=PREFIX`, forcing the older Rust. This causes
|
|
compilation errors in relibc.
|
|
|
|
**Fix:** Override `RUSTUP_TOOLCHAIN` in the relibc recipe build script
|
|
to use the redoxer default toolchain (`~/.redoxer/${TARGET}/toolchain`,
|
|
Rust 1.98-dev) when `REDOXER_TOOLCHAIN` is set and not pointing to a
|
|
`.partial` directory (PREFIX bootstrap):
|
|
|
|
```bash
|
|
REDOXER_TC="${REDOXER_TOOLCHAIN:-}"
|
|
if [ -n "${REDOXER_TC}" ] && [[ "${REDOXER_TC}" != *".partial"* ]]; then
|
|
REDOXER_DEFAULT="${HOME}/.redoxer/${TARGET}/toolchain"
|
|
if [ -d "${REDOXER_DEFAULT}/lib/rustlib/src/rust/library/core" ]; then
|
|
export RUSTUP_TOOLCHAIN="${REDOXER_DEFAULT}"
|
|
export PATH="${REDOXER_DEFAULT}/bin:${PATH}"
|
|
fi
|
|
fi
|
|
```
|
|
|
|
### Quirk 3: wchar.h / inttypes.h Circular Include Chain
|
|
|
|
**Problem:** relibc's generated `wchar.h` included `<stdio.h>` (via cbindgen
|
|
`sys_includes`) before defining `wint_t` and `mbstate_t`. And `inttypes.h`
|
|
included `<wchar.h>` for `wchar_t` instead of using `stddef.h` per POSIX spec.
|
|
This created a circular include chain that broke gnulib-based packages (m4,
|
|
bison, flex, etc.).
|
|
|
|
**Error:**
|
|
```
|
|
error: unknown type name 'wint_t'
|
|
error: unknown type name 'mbstate_t'
|
|
```
|
|
|
|
**Root cause:** Two intertwined issues in relibc's cbindgen header generation:
|
|
|
|
1. `wchar/cbindgen.toml` listed `stdio.h` and `time.h` in `sys_includes`, which
|
|
cbindgen emits at the top of the generated header, before the
|
|
`wchar_t`/`wint_t`/`mbstate_t` typedefs. When a gnulib wrapper did
|
|
`#include_next <wchar.h>`, the preprocessor pulled in `stdio.h` -> `stdint.h`
|
|
-> `inttypes.h` -> `wchar.h` again before any of those types were defined.
|
|
2. `inttypes/cbindgen.toml` listed `wchar.h` in `sys_includes`. Per POSIX,
|
|
`inttypes.h` only needs `wchar_t` (from `stddef.h`), not the full
|
|
`wchar.h`. Including `wchar.h` closed the circular chain.
|
|
|
|
**Fix:** Both changes are in the relibc fork (`local/sources/relibc/`):
|
|
|
|
1. `src/header/wchar/cbindgen.toml`: `sys_includes = ["features.h"]` only. The
|
|
type definitions (`wchar_t`, `wint_t`, `mbstate_t`) and the `stdio.h`/
|
|
`time.h` includes were moved to `after_includes`, so the typedefs land before
|
|
any transitive include. `mbstate_t` is defined in `after_includes` under a
|
|
`_RELIBC_MBSTATE_T` guard, and excluded from cbindgen export via
|
|
`[export] exclude = ["mbstate_t"]`.
|
|
2. `src/header/inttypes/cbindgen.toml`: `sys_includes = ["stdint.h", "stddef.h"]`
|
|
(POSIX spec compliant, breaks the circular chain by removing the
|
|
`inttypes.h` -> `wchar.h` edge).
|
|
|
|
**Commits:** `d28963d` (wchar.h fix), `a2e4cd2` (inttypes.h fix) in
|
|
`local/sources/relibc/`.
|
|
|
|
**Reference:** The m4 section (Quirk 5) documents the same fix from the
|
|
consuming package's perspective.
|
|
|
|
---
|
|
|
|
## Package: qtbase (Qt 6 Base — local recipe)
|
|
|
|
**Recipe:** `local/recipes/qt/qtbase/recipe.toml`
|
|
**Source:** `local/recipes/qt/qtbase/source/` (local overlay with tar source)
|
|
**Template:** `custom`
|
|
|
|
### Quirk 1: Source Tarball Not Extracted for Local Overlay Recipes
|
|
|
|
**Problem:** The cookbook treats `local/recipes/qt/qtbase/source/` as a
|
|
local overlay (immutable). The `is_local_overlay()` check prevents
|
|
wiping and re-extracting the source from `source.tar`. As a result, only
|
|
the Red Bear-specific files (`tests/`, `util/`) exist in `source/`, but
|
|
the full Qt6 source code is missing.
|
|
|
|
**Error:**
|
|
```
|
|
FileNotFoundError: No such file or directory: '.../source/src/tools/CMakeLists.txt'
|
|
```
|
|
|
|
**Fix:** Manually extract the source tarball into the `source/` directory:
|
|
|
|
```bash
|
|
cd local/recipes/qt/qtbase
|
|
tar xf source.tar --strip-components=1 -C source/
|
|
```
|
|
|
|
This must be done once after updating the source tarball. Patches must
|
|
also be applied manually since the cookbook won't apply them to local
|
|
overlay sources:
|
|
|
|
```bash
|
|
cd source
|
|
patch -p1 --batch --no-backup-if-mismatch < ../redox.patch
|
|
```
|
|
|
|
**Affected recipes:** All Qt6 local overlay recipes with `tar` sources:
|
|
`qtbase`, `qt5compat`, `qtdeclarative`, `qtsvg`, `qtshadertools`, `qtwayland`.
|
|
|
|
### Quirk 2: `forkfd.h` Missing `<sys/resource.h>` Include
|
|
|
|
**Problem:** `src/3rdparty/forkfd/forkfd.h` declares functions using
|
|
`struct rusage` but only includes `<sys/wait.h>`. On Linux glibc,
|
|
`<sys/wait.h>` transitively includes `<sys/resource.h>` (which defines
|
|
`struct rusage`). On Redox/relibc, this transitive include doesn't exist.
|
|
|
|
**Error:**
|
|
```
|
|
forkfd.h:57: warning: 'struct rusage' declared inside parameter list
|
|
forkfd.c:918: error: conflicting types for 'forkfd_wait4'
|
|
```
|
|
|
|
**Fix:** Add `#include <sys/resource.h>` to `forkfd.h`:
|
|
|
|
```c
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/resource.h> // Added for struct rusage
|
|
```
|
|
|
|
### Quirk 3: `netinet/in6_pktinfo_compat.h` Not Available
|
|
|
|
**Problem:** `src/network/socket/qnativesocketengine_unix.cpp` includes
|
|
`<netinet/in6_pktinfo_compat.h>`, which relibc does not provide.
|
|
|
|
**Fix:** The `P0-fix-broken-include.patch` removes this include line.
|
|
Ensure the patch is applied to the source (see Quirk 1 about manual
|
|
patch application).
|
|
|
|
---
|
|
|
|
## Package: redox-driver-sys (Driver System Library)
|
|
|
|
**Recipe:** `local/recipes/drivers/redox-driver-sys/`
|
|
**Source:** `local/recipes/drivers/redox-driver-sys/source/` (local recipe)
|
|
|
|
### Quirk: Inline Assembly Register Constraints for I/O Port Access
|
|
|
|
**Problem:** The `io.rs` module uses inline assembly for x86 `IN`/`OUT`
|
|
instructions with generic register constraints (`in(reg)`, `out(reg_byte)`).
|
|
The x86 `IN`/`OUT` instructions require specific registers:
|
|
- Port: must be `DX`
|
|
- Data: must be `AL` (byte), `AX` (word), or `EAX` (dword)
|
|
|
|
Generic constraints let the compiler choose any register, producing
|
|
invalid instructions like `outb ax, esi` instead of `outb dx, al`.
|
|
|
|
**Error:**
|
|
```
|
|
error: invalid operand for instruction
|
|
--> <inline asm>:2:2
|
|
|
|
|
2 | outb ax, esi
|
|
| ^
|
|
```
|
|
|
|
**Fix:** Use explicit register operands in `src/io.rs`:
|
|
|
|
```rust
|
|
pub fn inb(port: u16) -> u8 {
|
|
let val: u8;
|
|
unsafe { core::arch::asm!("in al, dx", in("dx") port, out("al") val,
|
|
options(nomem, nostack, preserves_flags)) };
|
|
val
|
|
}
|
|
|
|
pub fn outb(port: u16, val: u8) {
|
|
unsafe { core::arch::asm!("out dx, al", in("dx") port, in("al") val,
|
|
options(nomem, nostack, preserves_flags)) };
|
|
}
|
|
```
|
|
|
|
Apply the same pattern for `inw`/`outw` (`ax`/`dx`) and `inl`/`outl`
|
|
(`eax`/`dx`).
|
|
|
|
---
|
|
|
|
## Package: mesa (Mesa 3D Graphics Library)
|
|
|
|
**Recipe:** `recipes/libs/mesa/recipe.toml`
|
|
**Source:** `https://gitlab.redox-os.org/redox-os/mesa.git` (branch `redox-24.0`)
|
|
**Template:** `custom` (meson-based)
|
|
|
|
### Status (2026-06-20): ALL RED BEAR PATCHES WIRED
|
|
|
|
Mesa builds successfully for the `x86_64-unknown-redox` target. The recipe's `patches=[...]`
|
|
list contains all six Red Bear Mesa patches, in order:
|
|
|
|
| # | Patch | Purpose |
|
|
|---|-------|---------|
|
|
| 01 | `local/patches/mesa/01-virgl-redox-disk-cache.patch` | Nullifies virgl's disk shader cache on Redox (no `XDG_CACHE_HOME` semantics on Redox) |
|
|
| 02 | `local/patches/mesa/02-gbm-dumb-prime-export.patch` | Adds `gbm_dri_bo_get_fd` fallback path via DRM dumb buffers (PRIME export on Redox) |
|
|
| 03 | `local/patches/mesa/03-platform-redox-gpu-probe.patch` | EGL platform probe: tells `platform_redox.c` to enumerate `/scheme/drm/cardN` and try virgl-capable GPUs |
|
|
| 04 | `local/patches/mesa/04-sys-ioccom-stub-header.patch` | New file `include/sys/ioccom.h` (63 lines) implementing BSD-style `IOCPARM_LEN` / `_IO` / `_IOW` / `_IOR` macros for DRM UAPI ioctl encoding |
|
|
| 05 | `local/patches/mesa/05-vk-sync-wchar-include.patch` | Adds `#include <wchar.h>` to `vk_sync.h` for `wchar_t` (relibc does not transitively pull in `<wchar.h>` via `<vulkan/vulkan_core.h>` the way glibc does) |
|
|
| 06 | `local/patches/mesa/06-redox-surface-image-fields.patch` | Adds `__DRIimage *dri_image_back;` and `__DRIimage *dri_image_front;` to the `HAVE_REDOX_PLATFORM` section of `egl_dri2.h` (see quirk below) |
|
|
|
|
Build artifacts (verified 2026-06-20 12:30):
|
|
- `recipes/libs/mesa/target/x86_64-unknown-redox/stage/usr/lib/dri/virtio_gpu_dri.so` (17,474,080 bytes)
|
|
- `stage.pkgar` published to `local/cache/pkgar/mesa/`
|
|
|
|
### Quirk: `dri_image_back` / `dri_image_front` fields missing from Redox platform section (RESOLVED)
|
|
|
|
**Problem:** `src/egl/drivers/dri2/platform_redox.c` references
|
|
`dri2_surf->dri_image_back` and `dri2_surf->dri_image_front`, but these fields are only
|
|
defined inside `#ifdef HAVE_ANDROID_PLATFORM` in `egl_dri2.h`. The Redox platform section
|
|
(`#ifdef HAVE_REDOX_PLATFORM`) only had `orb_window` and `orb_surface`.
|
|
|
|
**Error (prior to fix):**
|
|
```
|
|
platform_redox.c:65:18: error: 'struct dri2_egl_surface' has no member named 'dri_image_back'
|
|
```
|
|
|
|
**Root cause:** When `03-platform-redox-gpu-probe.patch` was added to teach
|
|
`platform_redox.c` to allocate GBM-backed images for the EGL surface (so the virgl probe
|
|
can attach to a real GPU), it referenced `dri_image_back` and `dri_image_front`. These
|
|
fields existed only for the Android platform because the original EGL/Redox port only used
|
|
`orb_window` / `orb_surface` (the Orbital display server's native window/buffer types).
|
|
A complete Redox EGL platform needs both the Orbital legacy fields AND the DRI image
|
|
fields so a Wayland/DRM-style compositor can attach GBM-backed buffers.
|
|
|
|
**Fix:** Patch `06-redox-surface-image-fields.patch` adds the missing fields to the
|
|
`HAVE_REDOX_PLATFORM` section of `src/egl/drivers/dri2/egl_dri2.h`:
|
|
|
|
```c
|
|
#ifdef HAVE_REDOX_PLATFORM
|
|
void *orb_window;
|
|
void *orb_surface;
|
|
__DRIimage *dri_image_back;
|
|
__DRIimage *dri_image_front;
|
|
#endif
|
|
```
|
|
|
|
The patch is a 13-line unified diff. With this fix:
|
|
- `platform_redox.c` (post-`03-platform-redox-gpu-probe.patch`) compiles cleanly
|
|
- `redox_free_images()` can now free the GBM-backed images
|
|
- The EGL platform probe can attach a virgl backend to a Redox DRM/KMS surface
|
|
|
|
**Verification**: Mesa `cook` succeeds, `virtio_gpu_dri.so` links, `stage.pkgar` produced.
|
|
|
|
**Runtime caveat**: The build is verified. The runtime EGL platform selection
|
|
(`EGL_PLATFORM=redox`, choosing `virtio_gpu_dri.so` vs `swrast_dri.so`) is **not yet
|
|
runtime-validated** in a QEMU `-device virtio-vga-gl` boot. This is the last remaining gap
|
|
for hardware-accelerated SDDM greeter rendering.
|
|
|
|
### Why `-Dstatic_assert(...)=`
|
|
|
|
Mesa's upstream `configure` (meson) emits `-Dstatic_assert=_Static_assert` when
|
|
`_Static_assert` is unavailable on the target. On glibc/Linux, this collides with the
|
|
`<sys/cdefs.h>` `static_assert` macro. Redox's relibc doesn't define `static_assert` as
|
|
a macro, so the explicit `=` nullifies the macro and lets Mesa use the C11 keyword
|
|
`_Static_assert` instead. The recipe applies this via
|
|
`-Dc_args="['-Wno-error=implicit-function-declaration','-Wno-error','-std=gnu11','-Dstatic_assert=_Static_assert']"`.
|
|
|
|
---
|
|
|
|
## Package: sddm (Simple Desktop Display Manager — Wayland-only build)
|
|
|
|
**Recipe:** `local/recipes/kde/sddm/recipe.toml`
|
|
**Source:** `https://github.com/sddm/sddm.git` (rev `63780fcd79f1dbf81a30eef48c28c699ab15aded`)
|
|
**Template:** `custom` (cmake-based)
|
|
**Status (2026-06-20): BUILDS — Wayland-only, all X11 excluded
|
|
|
|
### Build-Side Quirks
|
|
|
|
SDDM's CMake build assumes X11/XCB/XAUTH are available. Red Bear OS has none of these.
|
|
The recipe handles this in three coordinated ways:
|
|
|
|
1. **`wayland-patch.sh` (~245 lines, sed-based)** — applied at build time to:
|
|
- Remove `find_package(XCB ...)` calls (CMakeLists)
|
|
- Remove XCB include/library refs in `src/{daemon,helper,greeter}/CMakeLists.txt`
|
|
- Replace `cmake/FindXKB.cmake`'s xcb-xkb lookups with xkbcommon
|
|
- Remove `XcbKeyboardBackend.cpp` from the greeter
|
|
- Rewrite `src/common/XAuth.cpp` as a Wayland-only stub
|
|
- Replace `Qt5.15.0 CONFIG REQUIRED ...` with the components SDDM needs (Core, DBus, Gui, Network, Qml, Quick) + OPTIONAL_COMPONENTS LinguistTools/Test/QuickTest
|
|
- Gate `qt_add_translation` on `Qt6LinguistTools_FOUND`
|
|
- Guard the `test/CMakeLists.txt` block on `Qt6Test_FOUND AND Qt6QuickTest_FOUND`
|
|
|
|
2. **`remove-x11user-helper.py`** — strips the `sddm-helper-start-x11user` add_executable
|
|
and `install(TARGETS sddm-helper-start-x11user ...)` from `src/helper/CMakeLists.txt`,
|
|
plus the `target_link_libraries(sddm-helper-start-x11user ${JOURNALD_LIBRARIES})` line.
|
|
|
|
3. **`stubs/` directory** — provides fake headers for headers SDDM `#include`s but
|
|
relibc does not yet provide:
|
|
- `linux/kd.h`, `linux/vt.h` — VT ioctl definitions (SDDM only uses the
|
|
ioctl numbers, not the kernel-side semantics)
|
|
- `utmpx.h` — POSIX `utmpx` (SDDM only compiles against it; runtime stub)
|
|
- `X11/Xauth.h` — minimal stub matching the rewritten `XAuth.cpp` (Wayland-only)
|
|
|
|
**Note on stubs**: Per `local/AGENTS.md` zero-tolerance policy, the `X11/Xauth.h` stub
|
|
is a temporary carrier because the corresponding `XAuth.cpp` is rewritten as a no-op for
|
|
Wayland-only mode. When relibc gains a real `utmpx.h`, the `utmpx.h` stub here should
|
|
be removed and SDDM should compile against the relibc version. The `linux/kd.h` and
|
|
`linux/vt.h` stubs should be replaced by a proper `redbear-input-headers`-style header
|
|
package in a future cleanup pass.
|
|
|
|
### CMake flags that make the build work
|
|
|
|
The recipe passes these critical flags:
|
|
|
|
```bash
|
|
cmake "${COOKBOOK_SOURCE}" \
|
|
-DCMAKE_TOOLCHAIN_FILE="${COOKBOOK_ROOT}/local/recipes/qt/redox-toolchain.cmake" \
|
|
-DQT_HOST_PATH="${HOST_BUILD}" \
|
|
-DKF6_HOST_TOOLING="${HOST_BUILD}/lib/cmake" \
|
|
-DBUILD_TESTING=OFF \
|
|
-DBUILD_WITH_QT6=ON \
|
|
-DNO_SYSTEMD=ON \
|
|
-DENABLE_JOURNALD=OFF \
|
|
-DENABLE_PAM=ON \
|
|
-DUID_MIN=1000 \
|
|
-DUID_MAX=65000 \
|
|
-DLIBXKB_INCLUDE_DIR="${COOKBOOK_SYSROOT}/usr/include" \
|
|
-DLIBXKB_LIBRARIES="${COOKBOOK_SYSROOT}/usr/lib/libxkbcommon.so" \
|
|
-Wno-dev
|
|
```
|
|
|
|
Key flags:
|
|
- `-DBUILD_WITH_QT6=ON` — required; SDDM defaults to Qt5
|
|
- `-DNO_SYSTEMD=ON` — required; no systemd on Redox
|
|
- `-DENABLE_JOURNALD=OFF` — required; no journald on Redox
|
|
- `-DENABLE_PAM=ON` — required; `pam-redbear` provides `libpam.so.0`
|
|
- `-DUID_MIN=1000 -DUID_MAX=65000` — required at CMake time; SDDM hardcodes these
|
|
via `add_definitions` if not provided
|
|
- `-DQT_HOST_PATH` and `-DKF6_HOST_TOOLING` — required for `moc`/`qmltyperegistrar`/ECMs
|
|
tools that must run on the host (they cannot cross-compile for the Redox target)
|
|
|
|
### Build verification (2026-06-20)
|
|
|
|
- `cook sddm - successful` (0 errors)
|
|
- Stage output:
|
|
- `usr/bin/sddm` — main daemon
|
|
- `usr/bin/sddm-greeter-qt6` — QML greeter binary
|
|
- `usr/libexec/sddm-helper` — session spawn helper
|
|
- `usr/libexec/sddm-helper-start-wayland` — Wayland session starter (forks compositor + greeter)
|
|
- `usr/share/sddm/` — themes, scripts, translations
|
|
- `etc/pam.d/{sddm,sddm-greeter,sddm-autologin}` — PAM service files
|
|
- `patchelf --set-rpath "/usr/lib"` applied to all binaries so dynamic linking works
|
|
against the sysroot at runtime
|
|
|
|
### Runtime caveat
|
|
|
|
The QML greeter (`sddm-greeter-qt6`) is a Qt6 Wayland client and is therefore gated on
|
|
the Qt6 Wayland `null+8` crash fix (see `CONSOLE-TO-KDE-DESKTOP-PLAN.md` §3.1). The
|
|
daemon and helpers will start under init, but the greeter QML window will not appear
|
|
until the null+8 fix is runtime-validated.
|
|
|
|
---
|
|
|
|
## General Pattern: Source Tarball Extraction for Local Overlay Recipes
|
|
|
|
**Problem:** When a recipe lives under `local/recipes/` (local overlay),
|
|
the cookbook's `is_local_overlay()` check prevents wiping and re-extracting
|
|
the source from `source.tar`. If the `source/` directory only contains
|
|
Red Bear-specific files (tests, utils, etc.), the main source code is
|
|
missing.
|
|
|
|
**Affected recipes:** Any local overlay recipe that uses `tar = "..."`:
|
|
- `qtbase`, `qt5compat`, `qtdeclarative`, `qtsvg`, `qtshadertools`, `qtwayland`
|
|
- Possibly others added in the future
|
|
|
|
**Fix:** Extract the tarball manually before building:
|
|
|
|
```bash
|
|
cd <recipe-directory>
|
|
tar xf source.tar --strip-components=1 -C source/
|
|
# Apply patches manually:
|
|
cd source
|
|
for patch in ../*.patch; do
|
|
patch -p1 --batch --no-backup-if-mismatch < "$patch" || true
|
|
done
|
|
# Clean up rejects:
|
|
find . -name "*.rej" -delete
|
|
```
|
|
|
|
**Future improvement:** The cookbook could be enhanced to support
|
|
"extract-and-overlay" mode for local recipes with `tar` sources —
|
|
extracting the tarball first, then overlaying the local `source/` files.
|
|
|
|
---
|
|
|
|
## Adding a New Quirk
|
|
|
|
When you encounter a new build quirk:
|
|
|
|
1. **Document it here** — add a section under the appropriate package, or create
|
|
a new package section.
|
|
2. **Explain the root cause** — why does this happen?
|
|
3. **Show the fix** — what change resolves it?
|
|
4. **Note the placement** — should the fix go before or after `DYNAMIC_INIT`?
|
|
5. **Is it a cross-compilation pattern?** — if so, add it to the General Patterns
|
|
section so future recipes can benefit.
|
|
6. **Update the recipe** — apply the fix to `recipe.toml`.
|
|
7. **Update UPSTREAM-SYNC-PROCEDURE.md** — if the quirk is related to upstream
|
|
sync.
|
|
|
|
---
|
|
|
|
## Package: base-initfs (initfs image builder)
|
|
|
|
### pcid Must Start Before pcid-spawner
|
|
|
|
**Problem:** `pcid-spawner` calls `fs::read_dir("/scheme/pci")` as its first
|
|
action. `/scheme/pci` is created by `pcid` via `register_sync_scheme()`. If
|
|
`pcid` is not started, `pcid-spawner` fails with `ENODEV`.
|
|
|
|
**Root cause:** No init service started `pcid` in initfs. The upstream model
|
|
assumed `pcid` would be started, but no `.service` file existed for it. This
|
|
was masked in 0.2.3 because `driver-manager` (Red Bear's replacement) does
|
|
its own PCI enumeration via `redox_driver_pci` and doesn't depend on
|
|
`/scheme/pci`.
|
|
|
|
**Fix:** Added `35_pcid.service` to `init.initfs.d/`:
|
|
```ini
|
|
[unit]
|
|
description = "PCI bus enumeration daemon (creates /scheme/pci)"
|
|
requires_weak = ["30_acpid.service"]
|
|
|
|
[service]
|
|
cmd = "pcid"
|
|
type = { scheme = "pci" }
|
|
```
|
|
|
|
The `type = { scheme = "pci" }` tells init to wait for `/scheme/pci` to be
|
|
registered before marking the service as started. This ensures `pcid-spawner`
|
|
(which depends on `35_pcid.service` via `requires_weak`) only runs after
|
|
`/scheme/pci` exists.
|
|
|
|
### driver-manager Removed During Sync
|
|
|
|
**Problem:** The 0.2.3 → 0.2.4 upstream sync silently removed `driver-manager`
|
|
from `base-initfs` dependencies and `redbear-device-services.toml` packages.
|
|
|
|
**Root cause:** Upstream doesn't have `driver-manager` — it's a Red Bear
|
|
in-house project. The sync blindly overwrote tracked files with upstream
|
|
versions.
|
|
|
|
**Fix:** Restored:
|
|
- `"driver-manager"` in `base-initfs/recipe.toml` dependencies
|
|
- `cp driver-manager` binary copy to initfs/bin/
|
|
- `driver-manager = {}` in `redbear-device-services.toml` `[packages]`
|
|
- `drivers.d/` config directory creation in build script
|
|
- `set -eo pipefail` in build script
|
|
|
|
**See also:** `UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Upstream Not Ready"
|
|
|
|
---
|
|
|
|
## Redox Flag Values (Critical for Ported Code)
|
|
|
|
Redox flag values differ from Linux. Code ported from Linux that assumes
|
|
Linux conventions will be WRONG on Redox:
|
|
|
|
| Flag | Linux | Redox |
|
|
|------|-------|-------|
|
|
| `O_RDONLY` | `0` | `0x0001_0000` |
|
|
| `O_WRONLY` | `1` | `0x0002_0000` |
|
|
| `O_RDWR` | `2` | `0x0003_0000` |
|
|
| `O_ACCMODE` | `3` | `0x0003_0000` |
|
|
| `O_CLOEXEC` | `0x80000` | `0x0100_0000` |
|
|
|
|
**Common bug:** `flags & O_ACCMODE == O_RDONLY` evaluates to `0 == 0` on Linux
|
|
(read-only check passes), but on Redox `O_CLOEXEC & O_ACCMODE = 0 ≠ O_RDONLY`,
|
|
so a file opened with `O_CLOEXEC` without explicit `O_RDONLY` fails with `EROFS`.
|
|
|
|
**Fix:** Always pass `O_RDONLY` explicitly when opening for read:
|
|
```rust
|
|
let fd = Fd::open(path, O_RDONLY | O_CLOEXEC, 0)?;
|
|
```
|
|
|
|
### Kernel kcall on ACPI Scheme
|
|
|
|
**Problem:** Upstream-synced `acpid` uses `AcpiVerb` call API (`ReadRxsdt=1`,
|
|
`CheckShutdown=2`) but the kernel's `AcpiScheme` didn't implement `kcall`,
|
|
returning `EOPNOTSUPP`.
|
|
|
|
**Fix:** Added `kcall` method to `impl KernelScheme for AcpiScheme` in
|
|
`src/scheme/acpi.rs`. The kernel fork commit is `c7af6c43`.
|
|
|
|
**Signature:**
|
|
```rust
|
|
fn kcall(&self, fds: &[usize], payload: UserSliceRw, flags: CallFlags,
|
|
metadata: &[u64], token: &mut CleanLockToken) -> Result<usize>
|
|
```
|
|
|
|
- `fds[0]` = handle id
|
|
- `metadata[0]` = verb (u64): `1` = ReadRxsdt, `2` = CheckShutdown
|
|
- `payload` = UserSliceRw (read/write buffer)
|
|
|
|
---
|
|
|
|
## Cross-Reference
|
|
|
|
| Document | Relevance |
|
|
|----------|-----------|
|
|
| `local/docs/UPSTREAM-SYNC-PROCEDURE.md` | Per-package sync notes include build quirks |
|
|
| `AGENTS.md` | Project-level build commands and conventions |
|
|
| `local/AGENTS.md` | Local fork model, recipe structure |
|
|
| `src/cook/script.rs` | `DYNAMIC_INIT`, `reexport_flags`, `cookbook_cmake` definitions |
|
|
| `src/recipe.rs` | Recipe TOML schema (`cmakeflags`, `configureflags`, etc.) |
|