Aether install layout
When you install Aether (make install or ./install.sh), the toolchain + headers + sources + module descriptors land under a single $PREFIX (default ~/.aether):
$PREFIX/
├── bin/ # toolchain binaries
│ ├── ae # the user-facing CLI (`ae build`, `ae run`, …)
│ ├── aetherc # the compiler (lower-level; ae usually wraps)
│ └── aether-lsp # language server (install.sh only, if built;
│ # `make install` does not install it)
│
├── lib/aether/
│ └── libaether.a # prebuilt static archive, link target for downstream
│ # programs / libraries that compile against the runtime
│
├── include/aether/ # public headers, mirrors source-tree layout
│ ├── runtime/
│ └── std/
│
└── share/aether/
├── MANIFEST # authoritative list of link-suitable .c files (#329)
├── runtime/ # runtime C sources (the actor scheduler, memory,
│ # panic/try-catch, sandbox, etc.)
├── std/ # stdlib sources + module.ae descriptors
└── contrib/ # contrib module.ae descriptors + headers
# (matching libaether_<x>.a archives come from
# `make install-contrib`; this dir alone gives
# downstream `import contrib.X` resolution
# without the .a archive)
How downstream tools should consume the install
Two consumption shapes, in priority order:
- Link against
libaether.a(recommended). Every Aether runtime + stdlib.cfile that ships compiles into this single archive. The canonical recipe for the include + link flags is:
gcc your.c $(ae cflags) -o your-program
ae cflags resolves to the right -I<prefix>/include/aether/... plus -L<prefix>/lib/aether -laether plus the OS-level deps (-pthread -lm, plus -lssl -lcrypto -lz -lnghttp2 -ldl if the build picked them up at install time). It works identically for in-tree dev builds, ~/.aether user installs, and /usr/local system installs.
Do not hand-craft -L / -l: libaether.a lives at <prefix>/lib/aether/libaether.a (under the aether/ subdir, not flat under <prefix>/lib/), so a bare -laether will fail to resolve without the explicit -L<prefix>/lib/aether. tools/ae.c itself uses this same path, see cmd_cflags for the construction.
ae build is tolerant of a package that ships the archive flat at <prefix>/lib/libaether.a instead: it tries the canonical nested path first and falls back to the flat one before resorting to the compile-from-source path below (#959). The nested layout is still the canonical one install.sh and make install produce.
- Compile from source, falling through to the
.cfiles inshare/aether/. This is whatae builddoes whenlibaether.aisn't found. It's also what tooling like aetherBuild'saeb-linkdoes.
In this mode, read share/aether/MANIFEST to discover which .c files to compile. The MANIFEST is the authoritative list, one path per non-comment, non-empty line, paths relative to share/aether/. Naive find runtime -name '*.c' walks would pull in benchmarks, orphaned poller hubs, and other source that isn't link-suitable.
# Read MANIFEST + build the link command:
cd $PREFIX/share/aether
src=$(grep -v -E '^(#|$)' MANIFEST)
gcc your.c $src -I $PREFIX/include/aether/runtime -I $PREFIX/include/aether/std \
-pthread -lm -lssl -lcrypto -lz -lnghttp2 \
-o your-program
MANIFEST format
# Aether MANIFEST, link-suitable C source files for
# downstream consumers compiling against the runtime/std
# source tree (e.g. aetherBuild's aeb-link). Generated by
# the Makefile; do not edit by hand. Regenerated on every
# `make stdlib`.
#
# Format: one path per non-comment, non-empty line. Paths
# are relative to this install root (share/aether/ on a
# system install; the repo root in the source tree).
# Lines starting with '#' are comments.
# Runtime sources:
runtime/scheduler/multicore_scheduler.c
runtime/scheduler/scheduler_optimizations.c
runtime/aether_runtime.c
…
# Standard library sources:
std/string/aether_string.c
std/http/server/h2/aether_h2.c
…
The MANIFEST is generated from RUNTIME_SRC + STD_SRC in the Makefile so it always matches what we actually link into libaether.a. The build target is build/MANIFEST; both make install and install.sh copy it into $PREFIX/share/aether/MANIFEST.
What does NOT ship to the install
make install and install.sh deliberately trim a few directories that aren't link-suitable:
runtime/examples/standalone benches with their ownmain(). Compiling these into a downstream link would produce duplicate-mainlink errors.runtime/io/orphaned poller dispatch hub plus four platform variants from an earlier design iteration. The active poller variants live underruntime/scheduler/aether_io_poller_*.c; the orphaned dir would produce missing-typedef errors if a downstream tool tried to compile it.contrib/<X>/{tests,benchmarks,example_*.ae,test_*.sh,build.sh, ci.sh,*.m}, contrib source-tree noise..cfiles are also dropped EXCEPT the host-language bridges atcontrib/host/<lang>/aether_host_<lang>.c. The bridges ship as source becausemake installdoes NOT also build/installlibaether_host_<lang>.aonlymake install-contribdoes that, and it's a separate opt-in step (because each bridge needs the matching dev library:python3-dev,liblua5.4-dev, etc.). Downstream apps thatimport contrib.host.<lang>from a plainmake installtree compile the bridge as source into their own build. The matchinglibaether_<X>.aarchives carry the C side for everything else; onlymodule.aedescriptors + public headers ship undershare/aether/contrib/.
Building against an installed Aether: required defines
Apps that #include runtime/std headers and link against libaether.a from a plain make install tree must compile with the same preprocessor defines the install was built with, otherwise the header-side macros and the library-side symbols disagree. The flag that matters:
-DAETHER_HAS_SANDBOX, gatesaether_sandbox_check(). When defined,runtime/aether_sandbox.hprovides astatic inline aether_sandbox_check()that consults the global_aether_sandbox_checker(defined inlibaether.a); when undefined, the header replaces it with a no-op macro that always returns 1. There's no linker error on skew, the function is inline in both branches, so a build that compiles the header without the flag silently loses sandbox enforcement even when linked against a sandbox-enabled library. The shippedlibaether.ais always built with this flag (seeCFLAGSin the Makefile, which carries-DAETHER_HAS_SANDBOX), so downstream consumers should compile with it too.- Any future
AETHER_HAS_*flags introduced for optional runtime subsystems will follow the same pattern.
The version stamp at lib/aether/VERSION catches the ae-vs-libaether version skew separately; the define skew is its own thing and silent unless a symbol is actually missing.
The MANIFEST never references trimmed paths, the regression test at tests/integration/install_manifest/ verifies this on every build.
Option C alternative (status quo + docs)
Issue #329 considered three options for cleaning up the install layout:
- (A) Drop runtime/std sources entirely. Header-only
include/+ prebuiltlibaether.a+module.aeresolver descriptors. Cleanest, but breaks the source-fallback path intools/ae.cthat runs whenlibaether.ais missing (e.g. cross-built / partial installs). - (B) Ship
MANIFEST(the shipped choice). Conservative, keeps the source-fallback path working as a backstop, gives downstream tools an authoritative list, no breakage. - (C) Status quo + docs only. Low-touch, but doesn't help consumers who write naive
findwalks and trip onruntime/examples//runtime/io/.
Chose B. If a future downstream consumer needs the static-only shape, Option A can land additively (the MANIFEST stays useful either way).