Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/descriptor-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ in the [root README](../README.md#reference-examples).
| C++ application framework compat (dependencies reuse packages already in the index) | [`compat.eui-neo`](../pkgs/e/compat.eui-neo.lua) (upstream's `3rd/` ships 8 vendored dependencies; none of them is compiled here — all are redirected to the same-version `compat.*` packages in this index) |
| Mutually exclusive backends (one of several inside one package) | [`compat.eui-neo`](../pkgs/e/compat.eui-neo.lua): `vulkan` / `sdl2` each **replace** the default OpenGL / GLFW, and the default backend is expressed by *naming no feature at all* — there is no `opengl`/`glfw` feature. A `default` feature cannot express exclusivity: its own `defines`/`sources`/`deps` have no effect whatsoever, while its `implies` always applies and cannot be overridden by a named feature (which is, conversely, exactly the solution for the "always-on interface define" row below). The workable answer is to read the `-DMCPP_FEATURE_<NAME>` mcpp passes anyway and decide up front in a force-included header. Note also that `cflags` only reaches C TUs — C++ needs `cxxflags`, so a backend define written only into `cflags` never reaches any `.cpp` |
| Host runtime adaptation (drivers are not vendored) | [`compat.glx-runtime`](../pkgs/c/compat.glx-runtime.lua) · [`compat.vulkan-runtime`](../pkgs/c/compat.vulkan-runtime.lua) (mcpp binaries run against a bundled glibc, so a bare-soname `dlopen` never reaches the host drivers; a symlink farm plus `runtime.library_dirs` bridges that. The farm holds only versioned sonames, so nothing there can shadow an index package. Note that `runtime.library_dirs` renders as `-Wl,-rpath` and **not** as `-L` — the `-L` key is `runtime.link_library_dirs`, which these two do not need because nothing links against their farms; see the row below for one that does) |
| Ecosystem-stack binding (zero host) | [`compat.libgbm`](../pkgs/c/compat.libgbm.lua) (Mesa's GBM — buffer allocation out of a DRM device. The row above reaches the HOST; this one reaches the ECOSYSTEM and nothing else. **Why not a source build**: libgbm is a build target *inside* Mesa, not a separable project — `src/gbm/meson.build` is `link_with: [libloader]`, and `libloader` wants `idep_mesautil`, ~120 TUs of Mesa's internal util library for exactly one function, `loader_open_driver_lib`; and it is a **loader**, whose `gbm_create_device()` dlopens Mesa's own `dri_gbm.so`, so built apart from Mesa it would have nothing to load. **The test on this row is separability, NOT whether the payload also carries a copy** — `compat.libdrm`, from the same stack, passes it and is a source build (see the row below); the two coexist, measured. **What it deliberately does NOT do**: set the backend search path. `GBM_BACKENDS_PATH` is Mesa's own mechanism and the ENVIRONMENT's job — `xim:mesa` declares it through the graphics discovery layer (openxlings/xim-pkgindex#713), so this package sets nothing. **Two directory keys, not one**: `library_dirs` renders as `-Wl,-rpath` and `link_library_dirs` as `-L`, so a package that is *linked against* needs both — with the first alone the build still dies at `ld: cannot find -lgbm`) · [`compat.egl`](../pkgs/c/compat.egl.lua) (the EGL dispatch, provided by libglvnd rather than Mesa. libglvnd **is** a separable project, so by the criterion this should be a source build; it is still a binding for effort alone: `libEGL.so` also needs `egl_dispatch_stubs` (Python-generated `g_egldispatchstubs.c/.h`), `winsys_dispatch` and the whole of `libGLdispatch.so`, plus the vendor discovery path `__EGL_VENDOR_LIBRARY_DIRS` — a fork of the same size as wayland's. Ships **only** `EGL/` out of a payload that also carries `GL/`, `GLES2/`, `KHR/`: a third provider of `GL/` would make compat.glx-headers' documented two-provider race a three-way one, and `KHR/` comes from the index's existing `compat.khrplatform` — load-bearing, since `eglplatform.h` opens with `#include <KHR/khrplatform.h>`. X11 is deliberately NOT a dependency: that include is `USE_X11`-gated) · [`compat.wayland`](../pkgs/c/compat.wayland.lua) (client, server, cursor and EGL shim harvested from `xim:wayland`, with only `-lwayland-client` on `ldflags` — a dependency's ldflags reach the consumer's link line with no way to opt out, so forcing the server library on every client would be unfixable downstream. Wayland IS a separable project, so this row is where it does not belong: it moves to a source build in mcpplibs/wayland, which needs `build.mcpp` because wayland-scanner has to be compiled before it can generate the ~13,000 lines the two libraries are mostly made of) |
| Ecosystem-stack binding (zero host) | [`compat.libgbm`](../pkgs/c/compat.libgbm.lua) (Mesa's GBM — buffer allocation out of a DRM device. The row above reaches the HOST; this one reaches the ECOSYSTEM and nothing else. **Why not a source build**: libgbm is a build target *inside* Mesa, not a separable project — `src/gbm/meson.build` is `link_with: [libloader]`, and `libloader` wants `idep_mesautil`, ~120 TUs of Mesa's internal util library for exactly one function, `loader_open_driver_lib`; and it is a **loader**, whose `gbm_create_device()` dlopens Mesa's own `dri_gbm.so`, so built apart from Mesa it would have nothing to load. **The test on this row is separability, NOT whether the payload also carries a copy** — `compat.libdrm`, from the same stack, passes it and is a source build (see the row below); the two coexist, measured. **What it deliberately does NOT do**: set the backend search path. `GBM_BACKENDS_PATH` is Mesa's own mechanism and the ENVIRONMENT's job — `xim:mesa` declares it through the graphics discovery layer (openxlings/xim-pkgindex#713), so this package sets nothing. **Two directory keys, not one**: `library_dirs` renders as `-Wl,-rpath` and `link_library_dirs` as `-L`, so a package that is *linked against* needs both — with the first alone the build still dies at `ld: cannot find -lgbm`) · [`compat.egl`](../pkgs/c/compat.egl.lua) (the EGL dispatch, provided by libglvnd rather than Mesa. libglvnd **is** a separable project, so by the criterion this should be a source build; it is still a binding for effort alone: `libEGL.so` also needs `egl_dispatch_stubs` (Python-generated `g_egldispatchstubs.c/.h`), `winsys_dispatch` and the whole of `libGLdispatch.so`, plus the vendor discovery path `__EGL_VENDOR_LIBRARY_DIRS` — a fork of the same size as wayland's. Ships **only** `EGL/` out of a payload that also carries `GL/`, `GLES2/`, `KHR/`: a third provider of `GL/` would make compat.glx-headers' documented two-provider race a three-way one, and `KHR/` comes from the index's existing `compat.khrplatform` — load-bearing, since `eglplatform.h` opens with `#include <KHR/khrplatform.h>`. X11 is deliberately NOT a dependency: that include is `USE_X11`-gated) |
| Source build that needs a real project (Form A fork) | [`freedesktop.wayland`](../pkgs/f/freedesktop.wayland.lua) · [`freedesktop.wayland-server`](../pkgs/f/freedesktop.wayland-server.lua) · [`freedesktop.wayland-scanner`](../pkgs/f/freedesktop.wayland-scanner.lua) · [`freedesktop.wayland-util`](../pkgs/f/freedesktop.wayland-util.lua) (wayland 1.26.0, four entries out of one tarball — [mcpplibs/wayland](https://github.com/mcpplibs/wayland), a fork that patches no upstream file. **Why a fork and not an inline descriptor**: wayland is mostly GENERATED — `protocol/wayland.xml` describes every interface and wayland-scanner emits ~13,000 lines from it — and the generator is a C program in the same tree, so it must be COMPILED before it can run. An inline descriptor has no build step, and `install()` cannot do it either: mcpp compiles a package's sources at CONSUMER-BUILD time, so no package binary exists while another package installs. `build.mcpp` is the mechanism, and it only exists for a real mcpp project. **Why four packages**: `libwayland-client.so.0` and `libwayland-server.so.0` are distinct SONAMEs that Mesa's libEGL_mesa needs BOTH of, and mcpp links every library target against ALL of a package's sources — measured: a feature-gated second target still receives the feature's objects — so one package cannot emit two libraries with disjoint contents. mcpp's own diagnostic names the remedy: "split into a workspace member". **The module layer ships with the library, not beside it**: each package carries its C library AND its `.cppm`, so there is one package per library rather than a C one and a module one. The wrappers add no API — every exported name is upstream's, and the lists are generated from the public headers so a version bump cannot silently drop one. **Macros are the one thing that cannot cross**: `export` names entities and a macro is not one, so `wayland-util` maps each to what it actually is — `WL_MARSHAL_FLAG_DESTROY` to a constexpr, `wl_container_of` to a function template, the six `*_for_each` loops to ranges — and its test instantiates all of them including the `_safe` removal guarantee) |
| Source-built library sharing a soname with the payload | [`compat.libdrm`](../pkgs/c/compat.libdrm.lua) (libdrm 2.4.134 — five TUs plus an inlined `generated_static_table_fourcc.h`, and zero dependencies. It carries the same `libdrm.so.2` the ecosystem's Mesa payload does, and that is **not** a reason to bind: a DT_NEEDED soname already in the link map is REUSED, ld.so never searches again, so Mesa's `libgbm.so.1` binds to the copy the consumer linked — measured: one mapping in the process, and Mesa's GBM allocated a buffer through it. It holds only for `kind = "shared"` with the right soname: as the default `kind = "lib"` there is no `.so` to reuse, the payload's loads for Mesa, the consumer keeps its own merged one, and libdrm's file-static state (`drmHashTable`, `nr_fds`, `connection`) exists twice over one set of fds. The test asserts with `dladdr` that the loaded library is this package's. **Two include roots**: the public headers sit at the source root and the uapi headers under `include/drm/`, and `xf86drm.h` line 40 is a bare `#include <drm.h>`) · [`compat.libffi`](../pkgs/c/compat.libffi.lua) (3.4.8. The x86 assembly **gates itself** — `ffi.c`/`ffiw64.c`/`unix64.S`/`sysv.S`/`win64.S` each open with `#ifdef __x86_64__` or `__i386__` — so all of them are listed and the preprocessor selects. `fficonfig.h` is configure's record of what it probed and cannot be derived, so it is inlined; `ffi.h` CAN be derived, so install() performs configure's four substitutions on `ffi.h.in` and stays honest across a version bump) · [`compat.expat`](../pkgs/c/compat.expat.lua) (2.7.1, three TUs — `xmltok_impl.c` and `xmltok_ns.c` are `#include`d BY `xmltok.c`, five times between them, so listing them would produce duplicate symbols) |
| Always-on interface define | `CURL_STATICLIB` in [`compat.curl`](../pkgs/c/compat.curl.lua): `cflags` is always on but package-private, while a feature's `defines` reaches consumers yet has to be named — `default = { implies = … }` applies unconditionally and happens to give both |
| Multiple majors in one package (shape switches with the version) | [`compat.catch2`](../pkgs/c/compat.catch2.lua) (3.x compiles `src/catch2/` into a static library; 2.x goes header-only through `single_include/`) |
Expand Down
2 changes: 1 addition & 1 deletion docs/package-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ combined as needed.
| **A. C-source compat** | plain C or a handful of sources; the user writes `#include <foo.h>` | `pkgs/c/compat.cjson.lua`, `compat.zlib.lua`, `compat.gtest.lua` | `sources` and `c_standard` |
| **B. header-only** | headers only, nothing to compile | `pkgs/c/compat.eigen.lua`, `compat.opengl.lua`, `compat.khrplatform.lua` | `include_dirs` and an anchor source |
| **C. C++23 module** | exposes `import x.y;` | `pkgs/n/nlohmann.json.lua` | `modules` plus `generated_files` or a source `.cppm` |
| **D. External Form-A module repo** | upstream ships its own mcpp descriptor in a separate repository — or the build needs something an inline descriptor cannot express (`build.mcpp`, a workspace, a code generator that must be compiled first) | `pkgs/i/imgui.lua`, `pkgs/m/mcpplibs.*`, `pkgs/g/grpc.lua` + `grpcgen.lua` + `grpc-plugin.lua` (three entries out of one fork) | `mcpp = "<repo path>"` (Form A) |
| **D. External Form-A module repo** | upstream ships its own mcpp descriptor in a separate repository — or the build needs something an inline descriptor cannot express (`build.mcpp`, a workspace, a code generator that must be compiled first) | `pkgs/i/imgui.lua`, `pkgs/m/mcpplibs.*`, `pkgs/f/freedesktop.wayland*.lua` (four entries out of one fork) | `mcpp = "<repo path>"` (Form A) |
| **E. Whole-source direct build with a generated config** | upstream generates its config header through configure/CMake; here a snapshot of it lands in `generated_files` | `pkgs/c/compat.libpng.lua`, `compat.curl.lua`, `compat.sdl2.lua`, `compat.ffmpeg.lua` | `generated_files` + `include_dirs` |
| **F. Shared-library compat** | has to be the **only** copy of that `.so` in the process — either because third parties `dlopen` it, or because the ecosystem payload links the same soname | the X11 family such as `pkgs/c/compat.x11.lua`, `compat.vulkan.lua`, `compat.libdrm.lua`, `compat.libffi.lua`, `compat.expat.lua` | `targets = { kind = "shared", soname = … }` |
| **G. Host runtime adaptation** | things that cannot be vendored, such as drivers — only a symlink farm plus metadata | `pkgs/c/compat.glx-runtime.lua`, `compat.vulkan-runtime.lua` | `runtime.library_dirs` / `capabilities` |
Expand Down
Loading
Loading