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
58 changes: 58 additions & 0 deletions .agents/docs/2026-10-28-add-dr_libs-mwrap-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Add mcpplibs.mwrap.dr_libs (dr_libs-m 2026.03.03)

## Form

- Third-party upstream [mackron/dr_libs](https://github.com/mackron/dr_libs), a choice of Unlicense or MIT-0. Upstream
tags each header on its own; compat.dr_libs 2026.03.03 (the parent change) pins the commit archive of `wav-0.14.5`
(fa931f3, `b56be593…bb7e`), whose `dr_flac.h` and `dr_mp3.h` are byte-identical to `flac-0.13.3` and `mp3-0.7.3`.
- Form A external mwrap module repository [mcpplibs/dr_libs-m](https://github.com/mcpplibs/dr_libs-m), package
`mcpplibs.mwrap.dr_libs`, version 2026.03.03 (compat.dr_libs' date version; the three header versions and the commit
in `[package.metadata.mwrap]`), tag series `mwrap-${version}`, tagged on the merged main commit (0d4c72e); release
asset `dr_libs-m-2026.03.03.tar.gz` (`0dc7ac0e…dbe2`), CN mirror `gitcode.com/mcpp-res/mwrap-dr_libs` with identical
bytes.
- One package, as compat.nanosvg packages its two stb-style headers: the three headers share one commit and one
implementation TU, and a program using one usually uses another (miniaudio embeds all three). Each header is still
its own module.
- Implementation ownership: the library is compat.dr_libs'. The wrapper vendors no upstream code; it retains
upstream's README.md and LICENSE under `upstream/dr_libs/` (checksums in `upstream/documents.json`) and deploys them
with its own LICENSE/NOTICE (`runtime.deploy`).

## Modules

- `mcpplibs.mwrap.dr_libs.wav` / `.flac` / `.mp3`: every type, enumerator and `*_API` function of the header's public
part by `export using` (wav 42 / 48 / 94, flac 32 / 6 / 31, mp3 28 / 8 / 29), generated from the pinned headers; each
re-exports `.macros` and is complete on its own. Every enum is named by its typedef, so the enumerators have linkage
and are exported as they are. The root `mcpplibs.mwrap.dr_libs` re-exports all four.
- `mcpplibs.mwrap.dr_libs.macros`: the 171 object-like macros as `inline constexpr` of the type of their expansion (the
version strings as references to constexpr char arrays). The headers define no computation macro.
- Stay macros, in `<mwrap/dr_libs/macros.hpp>` (= the three headers): `*_API`, `*_PRIVATE`, `*_DLL_*`,
`DRFLAC_DEPRECATED`, `DRMP3_INLINE`, `DRMP3_GNUC_INLINE_HINT`, `*_STRINGIFY` / `*_XSTRINGIFY`, `DRFLAC_64BIT`,
`DRFLAC_X64`, `DRFLAC_X86`, `DRFLAC_ARM` (28). Not mapped: the 3 include guards.

`tools/check_exports.py` fails when the generated sources are stale, a declaration is not exported by its submodule, or
a macro is neither mapped nor listed; every mapping is checked against the raw header in a header-mixing test.

## Verification

Wrapper CI (Linux x86_64 GCC 16.1 and LLVM 23.1.3, Linux arm64 GCC 16.1, macOS LLVM, Windows LLVM, all required): build,
eight test programs (the API through the module — WAV round trips in RIFF / Wave64 / RF64, IEEE float, A-law, mu-law,
a hand-written AIFF, cue metadata, narrow and wide paths; a FLAC fixture sample-exact against the signal of its
STREAMINFO MD5; an MP3 fixture to its LAME-gapless length; each submodule alone; the macros against the headers; header
mixing; compat.miniaudio in the same program decoding the fixtures to identical samples), the export audit, and the
example tool on the fixtures. The templates job scaffolds the default `tone` template as an installed package and runs
it. Until compat.dr_libs is on this index's main, the wrapper's CI resolves the compat namespace from the parent
change's branch (`tools/candidate_index.py`, a no-op once published).

Here, with the CI-pinned mcpp 2026.10.26.1:

- `bash tests/run_members.sh dr_libs-audio`: the real release archive through the candidate index; a WAV written and
read back, a FLAC stream built in the test (CONSTANT subframes, CRC-8/16) decoded and seeked, the MP3 to 4410 frames
with its 440 Hz tone, the `.flac` module alone, and the side header beside the import: `test result ok`.
- `python3 tests/mwrap/check_installed_template.py --package mcpplibs.mwrap.dr_libs@2026.03.03 --deploy`: the
unmodified template from the real archive, then a relocated self-contained bundle whose `licenses/dr_libs/` holds the
wrapper's LICENSE/NOTICE and dr_libs' README and LICENSE byte for byte.

## Motivation

openmui's coming audio engine (media.audio) decodes WAV, FLAC and MP3 assets; these permissively licensed decoders,
through modules, fit its statically linked framework, beside miniaudio for playback.
5 changes: 5 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,11 @@ jobs:
shell: bash
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.sheenbidi@3.0.0 --deploy

- name: Installed dr_libs wrapper archive, actual default tone template and its relocated notices
if: contains(format(' {0} ', env.MEMBERS), ' dr_libs-audio ') && matrix.toolchain == 'default'
shell: bash
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.dr_libs@2026.03.03 --deploy

- name: Installed Opus wrapper archive, actual default tone template and its relocated BSD notices
if: contains(format(' {0} ', env.MEMBERS), ' opus-ogg ') && matrix.toolchain == 'default'
shell: bash
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@

### Added

- **mcpplibs.mwrap.dr_libs 2026.03.03(新包)。** dr_libs-m:以 C++23 模块(`import mcpplibs.mwrap.dr_libs;`)使用
compat.dr_libs 2026.03.03(dr_wav 0.14.5、dr_flac 0.13.3、dr_mp3 0.7.3)。每个头文件各一个模块且可单独导入:
`mcpplibs.mwrap.dr_libs.wav`(42 个类型、48 个枚举值、94 个函数)、`.flac`(32、6、31)、`.mp3`(28、8、29),全部以
`export using` 导出上游全局名;每个枚举都由 typedef 命名,枚举值按原样导出。`mcpplibs.mwrap.dr_libs.macros` 把 171 个
对象式宏映射为其自身类型的常量;`*_API` 等属性、字符串化宏与 dr_flac 的平台检测宏共 28 个留在
`<mwrap/dr_libs/macros.hpp>`。包装仓库的 CI(Linux x86_64 GCC/LLVM、Linux arm64、macOS、Windows)逐样本核对 FLAC
解码、按 LAME 标签的无缝长度解码 MP3、在各容器中往返 WAV,并与 compat.miniaudio 链接在同一程序中解码出相同样本。
GLOBAL 为 `mwrap-2026.03.03` 发布资产,CN 为 GitCode `mcpp-res/mwrap-dr_libs` 镜像,sha256 一致。新增测试成员
`tests/mwrap/dr_libs-audio` 与已安装模板及其许可文件的部署检查。
- **compat.dr_libs 2026.03.03(新包)。** dr_libs:单文件的 WAV/AIFF、FLAC 与 MP3 解码器(以及 WAV 编码器),C 实现,
无依赖,许可为 MIT-0 或 Unlicense 二选一。上游按头文件分别打标签(`wav-*`、`flac-*`、`mp3-*`),没有同时覆盖三者的标签;
本包固定 `wav-0.14.5` 的提交 `fa931f3`(2026-03-03)的归档,其中 `dr_flac.h`、`dr_mp3.h` 与 `flac-0.13.3`、`mp3-0.7.3`
Expand Down
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ members = [
"tests/mwrap/concurrentqueue-mpmc",
"tests/mwrap/fribidi-bidi",
"tests/mwrap/sheenbidi-bidi",
"tests/mwrap/dr_libs-audio",
"tests/mwrap/opus-ogg",
"tests/mwrap/box2d-physics",
"tests/mwrap/miniaudio-engine",
Expand Down
52 changes: 52 additions & 0 deletions pkgs/mwrap/dr_libs.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-- Immutable upstream-aligned mwrap source release (dr_libs-m mwrap-2026.03.03);
-- GLOBAL and CN bytes are identical.
--
-- The wrapper is Apache-2.0; the library it links, compat.dr_libs 2026.03.03
-- (dr_wav 0.14.5, dr_flac 0.13.3, dr_mp3 0.7.3 from upstream commit fa931f3),
-- is a choice of Unlicense or MIT-0, linked statically: the package deploys
-- dr_libs' README and LICENSE beside programs (runtime.deploy) with its own
-- LICENSE and NOTICE.
package = {
spec = "1",
namespace = "mcpplibs.mwrap",
name = "dr_libs",
description = "dr_libs-m: dr_wav, dr_flac and dr_mp3 (WAV/AIFF, FLAC and MP3 decoding, WAV writing) as C++23 modules",
licenses = { "Apache-2.0" },
repo = "https://github.com/mcpplibs/dr_libs-m",
type = "package",
extensions = {
autoupdate = {
tag = "mwrap-${version}",
url = "https://github.com/mcpplibs/dr_libs-m/releases/download/${tag}/dr_libs-m-${version}.tar.gz",
},
},
xpm = {
linux = {
["2026.03.03"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/dr_libs-m/releases/download/mwrap-2026.03.03/dr_libs-m-2026.03.03.tar.gz",
CN = "https://gitcode.com/mcpp-res/mwrap-dr_libs/releases/download/2026.03.03/dr_libs-m-2026.03.03.tar.gz",
},
sha256 = "0dc7ac0ea3cfbbf8fe57eca3cb5290757597ae2268e1e308082a34f241edbbe2",
},
},
macosx = {
["2026.03.03"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/dr_libs-m/releases/download/mwrap-2026.03.03/dr_libs-m-2026.03.03.tar.gz",
CN = "https://gitcode.com/mcpp-res/mwrap-dr_libs/releases/download/2026.03.03/dr_libs-m-2026.03.03.tar.gz",
},
sha256 = "0dc7ac0ea3cfbbf8fe57eca3cb5290757597ae2268e1e308082a34f241edbbe2",
},
},
windows = {
["2026.03.03"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/dr_libs-m/releases/download/mwrap-2026.03.03/dr_libs-m-2026.03.03.tar.gz",
CN = "https://gitcode.com/mcpp-res/mwrap-dr_libs/releases/download/2026.03.03/dr_libs-m-2026.03.03.tar.gz",
},
sha256 = "0dc7ac0ea3cfbbf8fe57eca3cb5290757597ae2268e1e308082a34f241edbbe2",
},
},
},
}
20 changes: 20 additions & 0 deletions tests/mwrap/check_installed_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,26 @@ def main():
notice = (roots[0] / "NOTICE").read_bytes()
assert b"mcpp-community" in notice and b"Muhammad Tayyab Akram" in notice
print(f"Verified {len(declared)} byte-identical wrapper/SheenBidi license files", flush=True)
elif identity == "mcpplibs.mwrap.dr_libs":
# dr_libs (Unlicense OR MIT-0) is linked statically: its README
# and LICENSE travel with the program beside the wrapper's.
sources = [path for store in (home / "xpkgs", home / "registry/data/xpkgs")
for path in store.glob(f"mcpplibs.mwrap-x-dr_libs/{version}/*/src/dr_libs.cppm")]
assert len(sources) == 1, sources
source = sources[0].parent.parent
declared = tomllib.loads((source / "mcpp.toml").read_text(encoding="utf-8"))["runtime"]["deploy"]
roots = list(relocated.rglob("licenses/dr_libs"))
assert len(roots) == 1, f"Missing dr_libs runtime license tree: {roots}"
for entry in declared:
notice = source / entry["from"]
copied = roots[0].parent.parent / entry["to"] / notice.name
assert copied.is_file() and copied.read_bytes() == notice.read_bytes(), copied
upstream = (roots[0] / "upstream/dr_libs/LICENSE").read_bytes()
assert b"unlicense.org" in upstream and b"MIT No Attribution" in upstream
assert b"Apache License" in (roots[0] / "LICENSE").read_bytes()
notice = (roots[0] / "NOTICE").read_bytes()
assert b"mcpp-community" in notice and b"David Reid" in notice
print(f"Verified {len(declared)} byte-identical wrapper/dr_libs license files", flush=True)
elif identity == "mcpplibs.mwrap.opus":
# libopus, opusfile and libogg are BSD-3-Clause and linked
# statically: each one's README and COPYING (libopus's with its
Expand Down
11 changes: 11 additions & 0 deletions tests/mwrap/dr_libs-audio/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "dr_libs-audio"
version = "2026.03.03"
description = "Consume the immutable dr_libs wrapper: a WAV written and read back, a FLAC stream built here decoded and seeked, an MP3 decoded to its gapless length, each header's module alone, the mapped macros, the side header beside the import"

[indices]
# Use the complete candidate built-in index prepared by tests/run_members.sh.
# An explicit empty table overrides the legacy workspace redirect.

[dependencies]
"mcpplibs.mwrap.dr_libs" = "2026.03.03"
Loading
Loading