fix: toolchain - update docs
This commit is contained in:
+78
-4
@@ -38,9 +38,80 @@ What the target does by default:
|
||||
wanted.
|
||||
- Defines `__montauk__` / `__MONTAUK__`.
|
||||
|
||||
C++ works with `-fno-exceptions -fno-rtti` (the project convention).
|
||||
There is no libstdc++ yet — only libgcc is built. A hosted libstdc++
|
||||
needs a more complete libc and is the next step toward self-hosting.
|
||||
The in-tree programs are built `-fno-exceptions -fno-rtti` (the project
|
||||
convention), but that is a project style choice, not a toolchain limit —
|
||||
see the STL section below.
|
||||
|
||||
## C++ standard library (hosted libstdc++)
|
||||
|
||||
`build-montauk-toolchain.sh` builds and installs a **hosted** libstdc++
|
||||
(`all-target-libstdc++-v3`), so the full STL is available to
|
||||
`x86_64-montauk-g++` with no special flags:
|
||||
|
||||
```bash
|
||||
toolchain/local/bin/x86_64-montauk-g++ app.cpp -o app.elf
|
||||
```
|
||||
|
||||
Headers live in `toolchain/local/x86_64-montauk/include/c++/14.2.0/`,
|
||||
the library in `toolchain/local/x86_64-montauk/lib/libstdc++.a`.
|
||||
`_GLIBCXX_HOSTED` follows `__STDC_HOSTED__`, i.e. 1 for ordinary
|
||||
compiles.
|
||||
|
||||
Note that `toolchain/sysroot/usr/include/` *also* holds a freestanding
|
||||
C++ subset (copied from `kernel/freestnd-cxx-hdrs`, which is what the
|
||||
kernel and the in-tree programs build against). That directory is last
|
||||
on the include search path, so for a plain `g++` invocation the hosted
|
||||
headers win and the freestanding copies are shadowed. Check
|
||||
`g++ -x c++ -E -v -` if you ever need to confirm the order.
|
||||
|
||||
### What works
|
||||
|
||||
Link-verified with the cross compiler, no flags beyond the source file:
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| `<string>`, `<vector>`, `<map>`, `<algorithm>` | works |
|
||||
| `<memory>` (`unique_ptr`, `shared_ptr`, `make_*`) | works |
|
||||
| Exceptions (`throw` / `catch`, `std::exception`) | works |
|
||||
| RTTI (`typeid`, `dynamic_cast`) | works |
|
||||
| `<iostream>`, `<sstream>` | works (links a large binary — see below) |
|
||||
| Static constructors | works (`crt1.c` runs `.init_array`) |
|
||||
|
||||
`toolchain/files/cxx-test.cpp` is the on-OS regression check for this;
|
||||
`make devkit` compiles it to `0:/sdk/bin/cxx-test.elf`. Run it on the
|
||||
target to confirm the above at **runtime** rather than just at link
|
||||
time — that is the authoritative check, since a clean link does not by
|
||||
itself prove exception unwinding works on hardware.
|
||||
|
||||
### What does not work
|
||||
|
||||
- **Threads.** libstdc++ is built `gthr-single`
|
||||
(`_GLIBCXX_HAS_GTHREADS` is undefined), because the libc has no
|
||||
pthreads. `std::thread`, `std::mutex`, `std::condition_variable`,
|
||||
`std::async` and `std::call_once` do not exist — code using them
|
||||
fails to *compile*, not to link.
|
||||
|
||||
Consequence worth knowing: in single-threaded mode libstdc++ selects
|
||||
the **non-atomic** `shared_ptr` refcount path. The kernel does have
|
||||
real threads (`SYS_THREAD_SPAWN/EXIT/JOIN/SELF`,
|
||||
`programs/include/montauk/thread.h`), so it is possible to spawn
|
||||
threads and share a `shared_ptr` across them — that will corrupt the
|
||||
refcount and is a silent use-after-free. Do not do it until a
|
||||
pthreads/gthreads shim exists and libstdc++ is rebuilt against it.
|
||||
|
||||
- **`<iostream>` is expensive.** It drags in the static locale and
|
||||
iostream init machinery; a hello-world using it links to roughly
|
||||
5.7 MB versus ~1.8 MB for `<string>` + `<vector>`. Prefer `<cstdio>`
|
||||
where binary size matters, which on a ramdisk image is most places.
|
||||
|
||||
- **`libm.a` is an empty stand-in.** The math functions live inside
|
||||
`libc.a` (the g++ driver links `-lm` unconditionally, hence the empty
|
||||
archive). Roughly 50 functions are present — `sqrt`, `sin`, `cos`,
|
||||
`pow`, `log`, `exp`, `atan2`, `hypot`, `floor`, `ceil`, `fmod`,
|
||||
`round` and some `float` variants. Absent: `fma`, `cbrt`, `expm1`,
|
||||
`log1p`, `erf`, `tgamma`, `nearbyint`, `remquo`, most remaining
|
||||
`float` variants, and all `long double` variants. Ports that need
|
||||
these have to add them to `programs/lib/libc/libc.c`.
|
||||
|
||||
## Refreshing the sysroot
|
||||
|
||||
@@ -146,7 +217,10 @@ Notes:
|
||||
- The `devkit` target in programs/GNUmakefile ships the staged tools
|
||||
into the OS image at 0:/sdk/bin (as.elf, ld.elf, ar.elf, ...) with a
|
||||
target-side sysroot at 0:/sdk/include + 0:/sdk/lib (libc.a, crt
|
||||
objects, empty libm/libstdc++) - the Montauk SDK. The kernel
|
||||
objects, the real hosted libstdc++.a plus its c++/ headers, and an
|
||||
empty libm stand-in) - the Montauk SDK. On-OS g++ therefore gets the
|
||||
same STL as the cross compiler; see the C++ standard library section
|
||||
above for what is and is not supported. The kernel
|
||||
resolves driveless absolute paths ("/sdk/lib") against the cwd
|
||||
drive, so the --prefix=/sdk layout works natively. The shell
|
||||
searches 0:/sdk/bin and tab-completes it. Future ports configure
|
||||
|
||||
@@ -121,8 +121,12 @@ cp -r "${REPO_DIR}/programs/include/libc/." "${SYSROOT}/usr/include/"
|
||||
cp -r "${REPO_DIR}/programs/include/montauk" "${SYSROOT}/usr/include/montauk"
|
||||
cp -r "${REPO_DIR}/programs/include/Api" "${SYSROOT}/usr/include/Api"
|
||||
# Freestanding C++ headers (<cstdint>, <type_traits>, <atomic>, ...) —
|
||||
# there is no hosted libstdc++ yet, so C++ programs get the same
|
||||
# freestanding subset the rest of the tree builds against.
|
||||
# the subset the kernel and the in-tree programs build against. This is
|
||||
# NOT the whole C++ story: a hosted libstdc++ is built further down and
|
||||
# installs its own headers under ${PREFIX}/x86_64-montauk/include/c++.
|
||||
# That directory comes first on the include path and this one comes
|
||||
# last, so a plain g++ invocation gets the hosted headers and these are
|
||||
# shadowed. See "C++ standard library" in README.md.
|
||||
cp -r "${REPO_DIR}/kernel/freestnd-cxx-hdrs/x86_64/include/." "${SYSROOT}/usr/include/"
|
||||
cp "${REPO_DIR}/programs/lib/libc/crt1.o" \
|
||||
"${REPO_DIR}/programs/lib/libc/crti.o" \
|
||||
@@ -161,9 +165,11 @@ else
|
||||
fi
|
||||
|
||||
# ── Build GCC ─────────────────────────────────────────────────────────────────
|
||||
# Hosted against the Montauk libc headers in the sysroot. Only the
|
||||
# compiler and libgcc are built; libstdc++ needs a more complete libc
|
||||
# (that is the self-hosting step, not the cross-toolchain step).
|
||||
# Hosted against the Montauk libc headers in the sysroot. Builds the
|
||||
# compiler, libgcc, and a hosted libstdc++ (full STL: string/vector/map,
|
||||
# exceptions, RTTI, iostream). libstdc++ is built gthr-single because
|
||||
# the libc has no pthreads, so <thread>/<mutex> are absent and
|
||||
# shared_ptr uses non-atomic refcounts. See README.md.
|
||||
if [[ -x "${PREFIX}/bin/${TARGET}-gcc" ]]; then
|
||||
bold "GCC already installed — skipping."
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user