English | 简体中文
The complete catalog of .lua descriptors in this index, grouped by the shape of the problem each one solves. It is
meant to be read the way you would read a case book: find the row whose situation matches yours, open that descriptor,
and reuse its reasoning. Every entry records not just what the package compiles but what it deliberately does not,
which is usually the part worth copying.
For the templates behind each shape see package-types.md; the short list of starting points lives in the root README.
| Shape | Examples |
|---|---|
| Native module library (Form A) | mcpplibs.xpkg · mcpplibs.tinyhttps · tensorvia-cpu · ffmpeg (module layer; sources compiled directly through compat.ffmpeg) · opencv (single repository: the module layer and the full OpenCV 5 source build both live in the package, and only this descriptor stays on the index side) · mcpplibs.grpc (gRPC 1.83.0 — the one library here that CANNOT be a compat descriptor: upstream publishes no self-contained source artifact, its tag archive carrying abseil/protobuf/re2/boringssl/zlib as empty submodule placeholders, so grpc-m's release tarball IS that artifact. It vendors only gRPC's own source and takes the five dependencies from this index, so a consumer that also uses protobuf links one copy rather than two) |
| Native multi-module library with feature-scoped sources | gzj-creator.galay (Galay 5.0.2 — the upstream Form-A manifest exposes galay.utils and galay.kernel by default, while SSL, HTTP, database, RPC, MCP, and tracing modules stay behind named features and their corresponding dependencies. The index keeps the upstream manifest intact and tests the default module surface on Unix.) |
C-source compat (with features) |
compat.cjson · compat.zlib · compat.hiredis (the classic 1.2.0 — a 7-TU C build whose flat tarball headers get hiredis/-prefixed wrapper headers via generated_files, so consumers write #include <hiredis/hiredis.h> exactly like upstream's install layout) · compat.sqlite3 (plain C-source, no features: the single sqlite3.c amalgamation; 3.45.3, the final maintenance release of the most widely deployed 3.45.x line) · compat.libuv (libuv 1.48.0 — the per-OS source sets transcribed from upstream's CMakeLists, because a src/unix/*.c glob would compile every OS's backend at once; linux/macos get explicit unix subsets, windows globs src/win/*.c) |
| C-source compat whose sources are chosen by ARCHITECTURE | compat.wamr (WAMR 2.4.5 — the descriptor schema varies sources and cflags per OS but has no per-architecture hook, and archs is package metadata rather than a selector. WAMR needs both: one of BUILD_TARGET_X86_64/BUILD_TARGET_AARCH64 must be defined or wasm_runtime_common.c compiles its whole invoke-native section away and the link fails on invokeNative, and the implementation of that symbol is a hand-written assembly file per architecture. Both halves are handed to the preprocessor instead: a generated_files config header maps __x86_64__/__aarch64__ to the matching BUILD_TARGET_* and reaches every TU through -include, and a generated .S — .S, because upstream's arch/invokeNative_*.s are lowercase and clang assembles those WITHOUT the preprocessor, so unlike libffi's .S files they cannot guard themselves — #includes the chosen one as text. Two further notes worth copying: -std=gnu11 arrives through cflags because c_standard = "c11" defines __STRICT_ANSI__, under which the bare asm in platform_internal.h is not a keyword; and the POSIX files upstream drops when WASI is off are carried unconditionally rather than !-excluded and re-added by the libc-wasi feature, because an exclusion glob is global and wins over the feature's own entry for the same file) |
| C-source compat where the library IS a kernel ABI | compat.libaio (libaio 0.3.113 — twelve syscall-wrapper TUs, and the only xpm section is linux, because there is no port to declare: struct iocb is the kernel's and every TU is syscall(__NR_io_*, …). Consumers gate it with [target.'cfg(linux)'.dependencies], the mirror image of compat.wil. Three things it teaches. One public header out of a source dir: upstream installs exactly one, libaio.h, but the tarball keeps it in src/ beside the private headers — one of which is named syscall.h and would SHADOW glibc's for every consumer TU — so include_dirs names a generated_files forwarder and nothing else; the package's own sources reach the real header through it while their quote-form #include "syscall.h" still resolves next to the including .c, so no -I into src/ is needed at all. A c_standard that is a trap: -std=c11 sets __STRICT_ANSI__, which hides syscall() and sigset_t, and the public header then fails to parse at io_pgetevents; declaring c_standard = "gnu11" LOOKS like the fix but mcpp 2026.8.27.2 accepts the string and still emits -std=c11 (visible in the emitted compile_commands.json), so -D_GNU_SOURCE in cflags is the spelling that takes effect. Symbol versioning in a static package: io_getevents and io_cancel have no ordinary definitions upstream — the functions are io_getevents_0_4 etc. publishing short names through .symver … @@LIBAIO_0.4 — which resolves for an executable under both ld.bfd and lld, but not when a consumer builds a .so straight out of these objects; that needs upstream's src/libaio.map, exactly as upstream's own libaio.a does) |
| C++-source compat, one depending on the other | compat.abseil (151 TUs; a wildcard over absl/** trimmed by upstream's test/benchmark naming conventions) · compat.protobuf (the libprotobuf runtime, 79 TUs transcribed from upstream's own src/file_lists.cmake; declares compat.abseil as a dependency because protobuf's public headers include absl/…, and its gzip feature defines HAVE_ZLIB and pulls compat.zlib, while upb adds protobuf's 64-TU C runtime out of the same tarball. It also exposes protoc as a kind = "bin" target, so a consumer writing tools = ["protoc"] gets the compiler built for its own machine out of the same package it links — making a generator/runtime version mismatch inexpressible) · compat.re2 (22 TUs, upstream's own RE2_SOURCES) · compat.redis-plus-plus (redis++ 1.3.13 — the sync client, 17 TUs + patterns/redlock.cpp, depends on compat.hiredis; the one header CMake would generate, hiredis_features.h, is snapshotted via generated_files, and the async/TLS TUs are left out so the base build stays a two-package pair. An async feature adds the libuv-backed AsyncRedis interface (the 9 async TUs + compat.libuv; event_loop.cpp runs uv_run on a background thread, and <hiredis/adapters/libuv.h> arrives through compat.hiredis' wrapper headers). Two versions, one on each side of the source-structure watershed, share this ONE source list: 1.3.13 (modern 17-TU layout) and 1.3.3 (pre-redis_uri.cpp/redlock 15-TU layout) — the union works because 1.3.3's TUs are a strict subset, so exactly two globs match nothing there (a warning, not an error; same trick as compat.catch2)) |
| C transport + the header-only C++ server on top of it | compat.usockets · compat.uwebsockets (uSockets picks ONE event loop for all three platforms — libuv, via compat.libuv — because the alternative makes us_loop_t a different struct per platform for no gain; SSL and QUIC are left out so the base package's only dependency is that loop. The pair's real lesson is that LIBUS_USE_LIBUV / LIBUS_NO_SSL / UWS_NO_ZLIB are INTERFACE facts: libusockets.h changes the layout of us_loop_t under the first and gates its SSL declarations on the second, and uWS is header-only so its templates are instantiated in the CONSUMER's translation unit. An index descriptor's cflags reach only the package's own TUs, so every consumer must declare all three — a mismatch does not fail to build, it corrupts. The usockets test therefore writes to loop-attached extension memory from a timer callback and reads it back, which is exactly the assertion a layout disagreement breaks) |
| C++-source compat, zero-dep client + optional components | compat.websocket (IXWebSocket 12.0.1 — a pure RFC 6455 client compiled from upstream's IXWEBSOCKET_SOURCES minus the four server TUs, so the base build has zero external dependencies: TLS off (the OpenSSL/MbedTLS/AppleSSL TUs aren't built) and IXWEBSOCKET_USE_ZLIB unset, so the gzip codec compiles to a no-op. Two optional features add on top: server (the four server TUs — IXWebSocketServer, IXSocketServer, IXHttpServer, IXWebSocketProxyServer — needing nothing external, and it implies zlib because upstream's server advertises permessage-deflate by default, which the transport negotiates regardless of the define) and zlib (deps compat.zlib and turns the codec into real per-message-deflate compression). The default-feature test brings its own minimal RFC 6455 echo server on loopback sockets (handshake, masking, fragmentation and close all exercised offline); a second member, websocket-features, runs a real ix::WebSocketServer and asserts the compression is observable on the wire — a 64 KiB repeated payload round-trips with wireSize = 80) |
| Database client + the driver manager it needs, built from source | compat.nanodbc (nanodbc 2.14.0, frozen upstream — one TU over the platform ODBC driver manager. Two fixes make the four-year-old source compile and RUN here: a force-included char_traits<unsigned char> shim for libc++ (the standard's own customization point, guarded on _LIBCPP_VERSION so libstdc++/MSVC are untouched; and note -include reaches C++ TUs only through cxxflags, never cflags), and a per-platform answer to the manager itself — windows links the SDK's odbc32, macOS the OS's iODBC, while linux takes compat.unixodbc because mcpp's runtime closure rejects a NEEDED libodbc.so.2 that only the host has. The test asserts the manager's own diagnostics surface through the wrapper — including nanodbc's frozen off-by-one that drops the last SQL-state character) · compat.unixodbc (unixODBC 2.3.14, Shape E over A — DM + odbcinst + ini/log/lst + libltdl compiled statically into one odbc target, exactly upstream's libodbc.a symbol set, so the consumer carries no libodbc.so.2 NEEDED at all. The one non-obvious piece is libtool-free ltdl wiring: -DLTDLOPEN=libltdlc plus a generated lt_libltdlc_LTX_preloaded_symbols table (reconstructed from the libtool object's relocations) registers the dlopen loader. The frozen config.h merges ltdl's own configure output into the top-level one — ltdl sources never read the clashing identification macros, and the merge sidesteps a quoted -DLT_CONFIG_H that does not survive the pipeline. Verified against the libtool build of the same tarball: identical IM002 error path and identical lt_dlopen behaviour) |
| C-source compat, an ISA tier turned off through the GENERATED config | compat.libwebp (117 TUs as five directory globs rather than a transcribed file list, and one real decision. libwebp's SSE4.1 gate is `(SSE4_1 |
header-only (with features) |
compat.eigen · compat.concurrentqueue (moodycamel's lock-free MPMC queue 1.0.5 — three public headers at the tarball root, so * plus an anchor TU is the package. The ONE compilable optional component, c_api/'s two extern "C" wrapper TUs, sits behind a c-api feature, and the Windows story is why the descriptor carries cxxflags = {"-DMOODYCAMEL_STATIC"} beside the feature's defines: the header defaults to __declspec(dllimport) unless told otherwise, which is wrong for both the package's own TUs (they DEFINE the functions — and cflags would never reach a .cpp) and a static-archive consumer; the macro is read only inside #ifdef _WIN32, so defining it everywhere is inert on linux/macos. Everything else upstream ships outside the library is either header-only (nothing to gate) or carries a main()/benchmarks, which a lib target cannot take — its objects enter the consumer's link eagerly) |
| header-only, nothing to gate | compat.CLI11 (a command line parser whose every definition is CLI11_INLINE, so the package is */include plus an anchor TU. Upstream's two extras stay out: src/Precompile.cpp only means anything when CLI11_COMPILE also reaches the CONSUMER's translation units — an interface define, not a sources-only gate — and src/modules/CLI11.cppm is a module layer, which is a package shape of its own rather than a feature of the compat package) · compat.gtl (Greg's Template Library — the Swiss-table flat_hash_map family plus btrees and a bit_vector. */include exactly, not the tarball root: tests/ and examples/ carry headers of their own, and naming include/ is what upstream's INTERFACE target exposes, so a consumer cannot accidentally resolve into test code) · compat.plf-hive (the reference implementation of the proposed std::hive; the whole library is one file at the tarball root, so * plus an anchor TU is the entire package. Untagged upstream, so the version is a DATE over a commit archive — the compat.khrplatform precedent) · compat.wil (the Windows Implementation Library — RAII over Win32 handles, COM pointers and HRESULT. Windows-ONLY in an unusual sense: not a portable library with a Windows backend, but a library ABOUT Win32, so there are no other platform sections to declare and consumers gate the dependency with [target.'cfg(windows)'.dependencies] — compat.x11 and the gui-stack member in the other direction. Nothing is pre-configured: WIL's knobs (WIL_ENABLE_EXCEPTIONS, RESULT_DIAGNOSTICS_LEVEL, WIL_USE_STL) are macros the CONSUMER defines before including, and a header-only package has no compiled artifact for such a choice to be baked into anyway — pre-setting one would pick an error model on its consumers' behalf) |
| single-header library + a GENERATED implementation TU | compat.nanosvg (two stb-style headers where the implementation hides behind NANOSVG_IMPLEMENTATION / NANOSVGRAST_IMPLEMENTATION. Upstream ships no .c — its examples define the macros inline — so the package generates one that instantiates BOTH halves once. That is what turns a header drop into something linkable, and it moves the duplicate-symbol hazard from every consumer to a single place: consumers must NOT define those macros again, and the test links nsvgParse and nsvgRasterize together precisely so a package that instantiated only one half fails here rather than downstream) · compat.vulkan-memory-allocator (VMA 3.4.0, same shape but the generated TU also has to make a POLICY choice. VMA defaults to VMA_STATIC_VULKAN_FUNCTIONS 1, which references vkBindBufferMemory2 and seven siblings by name — eight undefined symbols against a headers-only dep. Pulling compat.vulkan to satisfy them would force a Vulkan loader on every consumer of a memory allocator and fight anyone dispatching through volk, so the generated TU selects the dynamic path instead and VMA resolves everything through VmaVulkanFunctions. Note the implementation is C++ despite the C-shaped API, so the generated file is .cpp) |
| Runtime loader compat (pure sources, sidestepping upstream codegen/asm) | compat.vulkan (the Khronos loader: loader/generated/ is checked in, and the assembly path degrades to plain C through UNKNOWN_FUNCTIONS_SUPPORTED, so no CMake/Python/assembler is needed; windows deferred) · compat.vulkan-headers |
| Whole-source direct build + generated config (only where a platform lacks one) | compat.curl (win32 uses upstream's checked-in config, unix generates one) · compat.sdl2 (win/mac use upstream's checked-in config; linux generates one and enables X11 by hand) · compat.c-ares (91 TUs; the release tarball already ships ares_build.h and a Windows config, so only ares_config.h is snapshotted per OS) · compat.msdfgen (msdfgen 1.13 — the config is not optional here: core/base.h opens with #include <msdfgen/msdfgen-config.h>, so without generating it nothing compiles, not even core/. Generating it rather than passing -D flags is also what makes the library and its consumers agree BY CONSTRUCTION — base.h is reached from every public header, so the file is the single place that says which of SVG/PNG/Skia exist. Of the four ext/ units only import-font.cpp is built; the other three each need a library this index does not carry, and their declarations disappear through the same generated config. MSDFGEN_USE_CPP11 is left off on purpose: it adds move constructors to Bitmap, so it changes the layout of a type that crosses the library boundary, and a package cannot guarantee every consumer defines it identically) |
| Upstream amalgamation (one TU is the whole library) | compat.harfbuzz (HarfBuzz 14.3.0 — upstream builds with meson, and reproducing that here would mean tracking ~137 .cc files plus a generated config. src/harfbuzz.cc is upstream's own supported "compile one file" path, so sources is a single line that cannot drift out of sync with a release. The amalgamation also #includes the CoreText/DirectWrite/GDI/GLib/Graphite2 backends, each behind its own HAVE_* gate, so naming only HAVE_FREETYPE selects the FreeType bridge and compiles the rest to nothing. HB_NO_MT is deliberately NOT set: it removes HarfBuzz's atomics, which is only sound under a single-threading promise a shared package cannot make for its consumers) · compat.mimalloc (mimalloc 3.4.5 — the opposite lesson: it also ships an amalgamation (src/static.c), and using it would be wrong. A src/*.c glob is wrong three ways, each a LINK error rather than a compile error — static.c duplicates every symbol, and free.c/alloc-override.c are #included by alloc.c rather than being TUs — so the source list is upstream's own mi_sources. MI_MALLOC_OVERRIDE stays off: a dependency silently taking over the process allocator is not a package's call) · compat.miniaudio (miniaudio 0.11.25 — miniaudio.c is upstream's own two-line MINIAUDIO_IMPLEMENTATION driver and its CMake library target, so sources is one line that tracks the release. The Linux link line is -ldl -lpthread -lm and deliberately NOT -lasound/-lpulse: miniaudio dlopens its backends, so the package builds on a machine that has neither) · compat.spirv-reflect (Khronos' SPIR-V reflection library; spirv_reflect.c is exactly upstream's spirv-reflect-static target. Both * and */include are exposed so the default "./include/spirv/unified1/spirv.h" and the SPIRV_REFLECT_USE_SYSTEM_SPIRV_H spelling resolve to the SAME bundled grammar header — a consumer that defines that macro cannot silently get a different SPIR-V revision than this .c was written against. Versioned by SDK line to stay in step with compat.vulkan-headers) |
| Upstream codegen frozen into the mirror archive | compat.godot-cpp (two versions: 4.5.0 = the godot-4.5-stable bindings, 10.0.0-rc1 = godot-cpp's own 10.x line, whose bindings target Godot 4.6. The ~1000 GDExtension classes under gen/ exist in no upstream tag archive — upstream's binding_generator.py emits them at build time. Running it once offline and publishing upstream's tree byte-for-byte plus gen/ keeps Python off the consumer side entirely; tools/godot-cpp/repack.sh reproduces the archive deterministically and refuses to publish if any upstream file differs) |
| Header package filling a gap in the index | compat.glx-headers (libglvnd's GL/glx.h, absent from the Khronos registry and required by SDL's X11 backend) |
| C++ application framework compat (dependencies reuse packages already in the index) | compat.eui-neo (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: 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 · compat.vulkan-runtime (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 (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) (EGL used to sit on this row as compat.egl, bound to xim:libglvnd. Its own comment recorded why that was wrong — "libglvnd is a separable project, so by the criterion this should be a source build; it is still a binding for effort alone" — and effort is not the criterion, so it moved to the row below as freedesktop.egl) |
| Source build that needs a real project (Form A fork) | freedesktop.wayland · freedesktop.wayland-server · freedesktop.wayland-scanner · freedesktop.wayland-util (wayland 1.26.0, four entries out of one tarball — 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. A module is named for the organization that owns the INTERFACE, which is why these are freedesktop.wayland.{client,server,util}: freedesktop owns the wayland protocol. The index's older convention was to drop the namespace entirely (chriskohlhoff.asio → import asio, compat.opencv → import opencv.cv); this is that rule made specific, because a module name is global and permanent in a way a package name is not. mcpplibs.openkal paid for the lesson — its 0.1.0 was withdrawn rather than kept because it "placed the module a consumer imports under the control of the implementation, which contradicts what the specification is for". 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) · freedesktop.egl (libglvnd 1.7.0 — mcpplibs/libglvnd, and the entry that replaced the compat.egl binding on the row above. The generated code is checked in rather than generated: upstream drives ~1000 lines of Python over a 2.7 MB gl.xml to emit the dispatch tables, and that output is deterministic from a pinned registry — so it lives in mcpp/generated/ and NO generator runs at build time, with CI regenerating and diffing it instead. mcpp build is the whole toolchain. The per-architecture choice lives in build.mcpp, not in the manifest: GLdispatch's entry stubs are per-arch and per-thread-storage-model, and unlike libffi's they carry no guards of their own, so hard-coding x86_64 in sources would make the package x86_64-only and say so nowhere; build.mcpp makes upstream's own gl_dispatch_type choice from mcpp::target_arch(). The module is khronos.egl, not freedesktop.egl, and the package/module mismatch is the point: freedesktop ships this code, but EGL is a Khronos specification with several implementations. Naming the module after the implementation would force every consumer to edit its imports the day a different libEGL is used — defeating a wrapper whose whole promise is that it changes nothing but the include line. It also makes two EGL providers in one build a hard conflict rather than silent coexistence, which is what GLVND wants anyway. One index entry, two libraries: libGLdispatch.so.0 is a sibling workspace member reached by a PATH dependency — being the one dispatch point in a process is GLVND's whole purpose, and a second index entry would let a consumer name both and resolve two instances, with soname reuse mapping one and silently discarding the other. The compiled-in vendor path is deliberately EMPTY: upstream bakes in <prefix>/share/glvnd/egl_vendor.d, which after relocation means the HOST's directory, so an empty fallback makes a missing ecosystem declaration surface as "no vendor found" rather than as silently loading the host's driver — the same stance compat.libgbm takes with GBM_BACKENDS_PATH) |
| Source-built library sharing a soname with the payload | compat.libdrm (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 (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 (2.7.1, three TUs — xmltok_impl.c and xmltok_ns.c are #included BY xmltok.c, five times between them, so listing them would produce duplicate symbols) |
| Always-on interface define | CURL_STATICLIB in compat.curl: 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 (3.x compiles src/catch2/ into a static library; 2.x goes header-only through single_include/) |
External build system (install() builds from source) |
compat.openblas (Make) · compat.openssl (Perl Configure + Make, static libssl/libcrypto) |
| Whole-source direct build (config snapshot + source list, no external build system) | compat.ffmpeg (2281 TUs including NASM assembly, declared through 28 directory globs) |
| Build-time generator output vendored into the descriptor | compat.gmp (516 TUs, all three platforms. GMP's build COMPILES AND RUNS seven table generators and substitutes gmp.h from gmp-h.in — all of it a pure function of limb=64/nail=0, so the outputs are produced once by upstream's own generators and shipped in generated_files (~270 KB, of which trialdivtab.h is 109 KB). That is what removes the install() hook, autotools, and the host compiler its probes needed — and with them the reason windows was deferred, since GMP's generic C only ever needed a GCC-compatible compiler. generated_files also carries a one-line forwarding header per source directory, so the package compiles with no -I at all and include_dirs exposes gmp.h + gmpxx.h rather than GMP's private headers. Verified against a --disable-assembly autotools build of the same tarball: identical 598-symbol export set, and GMP's own make check passes 177/178 against it) |
| Module layer over a compat source build (external Form-A repo) | godotengine.godot-cpp-m (two versions tracking upstream: 10.0.0-rc1 = Godot 4.6, 4.5.0 = Godot 4.5. import godot_cpp; re-exports the whole godot namespace, ~1800 names GENERATED from the headers rather than curated; the 1022-TU build stays in compat.godot-cpp, so the index carries only this descriptor. Macros — GDCLASS, GDREGISTER_CLASS, memnew, ERR_* — are the one thing a named module cannot export, so the package ships a side header to include next to the import. It also ships a generated hashfuncs.hpp shim — upstream's header minus static on two functions whose bodies declare an unnamed union — without which GCC refuses the module interface outright, a hard error no -W flag reaches) |
| C++23 module wrapper | nlohmann.json · marzer.tomlplusplus · neargye.magic_enum · boost-ext.ut (upstream's own include/boost/ut.cppm reproduced verbatim but for one __argc/__argv shim that Clang-on-MSVC needs; namespace boost-ext since it is NOT an official Boost library) |