From 6de94f81c3d7c20461de734bc4e9deb1e9288217 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:19:49 +0800 Subject: [PATCH 01/11] docs: plan retiring compat asio package --- ...tire-compat-asio-and-bare-module-design.md | 302 ++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 .agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md new file mode 100644 index 0000000..b8f3313 --- /dev/null +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md @@ -0,0 +1,302 @@ +# Retire `compat.asio` and expose the Asio module through the bare package token + +Date: 2026-07-20 + +## 1. Decision + +Retire the transitional header-only package introduced by mcpplibs/mcpp-index +PR #73. The public Asio integration will be module-only: + +```cpp +import std; +import asio; +``` + +Keep one published package identity and one implementation descriptor: + +- package identity: `chriskohlhoff.asio@1.38.1`; +- qualified dependency token: `chriskohlhoff.asio@1.38.1`; +- bare dependency token: `asio@1.38.1`; +- C++ module name: `asio`. + +Both dependency tokens must resolve to the same descriptor and the same locked +package identity. No forwarding package, second recipe, or header-only feature +will remain. Achieving that contract requires a narrowly scoped mcpp resolver +fix before the index change is published; moving the descriptor alone is not +sufficient. + +## 2. Scope + +This change will: + +1. canonicalize peer-root descriptor hits in mcpp to their declared package + identity; +2. release that resolver behavior and adopt the release in mcpp-index; +3. revert the repository content introduced by PR #73; +4. preserve the module package introduced by PR #80; +5. move the module descriptor from + `pkgs/c/chriskohlhoff.asio.lua` to `pkgs/a/asio.lua`; +6. retain `package.namespace = "chriskohlhoff"` and + `package.name = "chriskohlhoff.asio"` inside that descriptor; +7. remove module documentation that still describes `compat.asio` as a + companion or fallback; +8. add consumer coverage for both qualified and bare dependency tokens. + +This change will not: + +- retain `#include ` as a supported package contract; +- add `features` for header-only/module selection; +- add a meta-package or forwarding dependency; +- change the Asio 1.38.1 source archives, mirrors, SHA-256 values, module + wrapper, supported platforms, or separate-compilation defines; +- add a general-purpose package alias schema or change qualified-selector + semantics unrelated to peer-root identity canonicalization. + +## 3. Revert boundary + +PR #73 was squash-merged as the single-parent commit +`b3ebdd15bc3b56dc61cb91ab5b592200f713709f`. The implementation must therefore +start with: + +```bash +git revert b3ebdd15bc3b56dc61cb91ab5b592200f713709f +``` + +It must not use `git revert -m 1`; `-m` is only for reverting a merge commit. + +The reverse patch removes: + +- `.agents/docs/2026-07-17-add-asio-plan.md`; +- `pkgs/c/compat.asio.lua`; +- `tests/examples/asio/mcpp.toml`; +- the six header-only tests under `tests/examples/asio/tests/`; +- the `tests/examples/asio` workspace member. + +Applying the revert to the current `origin/main` conflicts only in the root +`mcpp.toml`, because later PRs added adjacent workspace members. Resolve that +conflict by removing only `tests/examples/asio`; retain +`tests/examples/asio-module` and every later member. + +The implementation PR should keep the generated revert commit as the first +commit, then add the module-token migration as a second commit. This preserves +the provenance of the retired package while keeping the new behavior reviewable. + +## 4. Descriptor identity and lookup + +The descriptor moves as follows: + +```text +pkgs/c/chriskohlhoff.asio.lua + -> pkgs/a/asio.lua +``` + +Only the repository path changes. These descriptor fields remain unchanged: + +```lua +namespace = "chriskohlhoff" +name = "chriskohlhoff.asio" +``` + +The current mcpp resolver treats descriptor filenames as lookup hints and the +declared `(namespace, short name)` as the package identity. The new filename +lets the current lookup layer find both requested spellings: + +1. A bare `asio` selector produces default and peer-root candidates. The + peer-root lookup checks `asio.lua`, then accepts the descriptor by its + declared short name `asio`. +2. A qualified `chriskohlhoff.asio` selector first checks the qualified + filename and then the supported bare-filename fallback. It finds + `asio.lua` and verifies the declared namespace `chriskohlhoff`. +3. The selected dependency coordinate must then be canonicalized to the + descriptor identity before installation, graph deduplication, and lockfile + generation. + +Step 3 is not true in the current mcpp implementation. When the peer-root +candidate has an empty namespace, `selectDependencyCandidate` keeps that empty +namespace even after reading a descriptor that explicitly declares +`chriskohlhoff`. The immediate effects are: + +- the bare dependency is installed and locked as a root `asio` coordinate; +- the qualified dependency is installed and locked as + `chriskohlhoff.asio`; +- a graph containing both spellings can treat them as two package instances + and encounter duplicate exported module `asio` definitions. + +The mcpp prerequisite must fix the source of that divergence. When an empty +peer-root candidate matches a descriptor with an explicit namespace, +candidate selection must replace the selected coordinate with the descriptor's +canonical `(namespace, short name)`. For this package, both inputs then become +`(chriskohlhoff, asio)` before fetch, deduplication, and lock serialization. + +This rule is intentionally narrower than a general alias facility: + +- it applies only after an existing peer-root lookup has found and + identity-verified a descriptor; +- it does not add new filename candidates or scan arbitrary descriptors; +- root packages whose descriptors declare no namespace remain root packages; +- qualified selectors continue to require an exact declared namespace. + +`mcpp add` itself only writes the dependency token to `mcpp.toml`; resolution +happens during the subsequent build or test. Validation must therefore run a +consumer build and inspect the resulting lockfile rather than treating a +successful `mcpp add` command as proof. + +## 5. Compatibility lifetime + +The index-only solution intentionally uses mcpp's non-canonical descriptor +filename fallback. The current resolver source marks this compatibility path +for removal in mcpp 1.0.0. + +Consequences: + +- the design is valid for the current workflow-pinned mcpp and current index; +- a new mcpp release containing peer-root identity canonicalization is required + before the retirement PR can merge; +- `index.toml` and every active workflow pin must adopt that release together; +- before mcpp 1.0.0 removes the fallback, the ecosystem must either introduce + a first-class package alias mechanism or choose one canonical dependency + token; +- the retirement PR must state this migration obligation explicitly instead + of presenting the bare filename as a permanent alias contract. + +The descriptor must not omit or falsify its declared identity to make lookup +easier. Identity verification remains authoritative. + +## 6. Consumer tests + +Keep `tests/examples/asio-module` as the qualified-token consumer. It continues +to declare: + +```toml +[dependencies.chriskohlhoff] +asio = "1.38.1" +``` + +Add a small second workspace member, `tests/examples/asio-short`, for the bare +token. It redirects the default index to this checkout and declares: + +```toml +[indices] +default = { path = "../../.." } + +[dependencies] +asio = "1.38.1" +``` + +The short-token member needs one focused test that imports `std` and `asio`, +constructs an `asio::io_context`, runs a posted operation, and returns nonzero +if the operation did not execute. The existing `asio-module` member remains +the comprehensive module API suite; duplicating its five tests in the alias +member would add maintenance without increasing selector coverage. + +The regression contract is: + +| Consumer | Dependency spelling | Required result | +| --- | --- | --- | +| `asio-module` | `chriskohlhoff.asio@1.38.1` | imports and exercises module `asio` | +| `asio-short` | `asio@1.38.1` | imports and exercises the same module | +| both | generated `mcpp.lock` | namespace is `chriskohlhoff`; version is `1.38.1` | + +The implementation should first add the bare-token consumer while the +descriptor still has the qualified filename and record the expected lookup +failure. After moving the descriptor but before applying the mcpp fix, record +the namespace/duplicate-identity failure. The mcpp canonicalization change is +the Green condition for the complete two-token contract. + +## 7. Documentation cleanup + +The current module descriptor still calls `compat.asio` its header-only +companion and recommends it for unsupported module APIs. Those statements +become false once PR #73 is reverted. + +Update the descriptor comments to state: + +- the package is module-only; +- consumers use `import std; import asio;`; +- `mcpp add asio@1.38.1` and + `mcpp add chriskohlhoff.asio@1.38.1` currently select the same package; +- APIs not exported by the wrapper are unavailable through this package; +- `#include ` is outside the supported mcpp-index contract. + +Also remove comparison comments in `tests/examples/asio-module` that point to +the deleted header-only member. Do not rewrite unrelated package documentation. + +## 8. Delivery sequence + +Deliver the work in two repositories and do not merge the index change against +an unreleased mcpp commit. + +### Phase A: mcpp resolver + +1. Add a failing e2e case based on the existing custom-namespace, + non-canonical-filename fixture. Request the package once by its bare short + name and once by its qualified name in the same graph. +2. Assert that the current resolver produces different coordinates or a + duplicate-module failure. +3. Canonicalize an identity-verified empty peer-root hit to the descriptor's + declared identity. +4. Assert one resolved package instance, one exported module, and a lockfile + namespace matching the descriptor. +5. Run the relevant unit/e2e suites and the complete mcpp verification required + by its contribution workflow. +6. Merge and release mcpp through the normal release process. + +### Phase B: mcpp-index retirement + +1. Raise `index.toml`'s `min_mcpp` and every active validation pin to the new + release in the same commit. +2. Revert PR #73 and resolve only the root workspace conflict. +3. Move the module descriptor to `pkgs/a/asio.lua` without changing its recipe. +4. Add the bare-token member and update stale module comments. +5. Run targeted and workspace validation on all workflow platforms. +6. Open a focused revert/migration PR; maintainers merge it. + +## 9. Validation + +Use the newly released mcpp version after Phase A. Required index-side local +evidence, in order: + +1. `git diff --check`; +2. Lua syntax and repository descriptor lint for `pkgs/a/asio.lua`; +3. strict `mcpp xpkg parse pkgs/a/asio.lua`; +4. repository mirror validation, proving URL/SHA tables were not damaged by + the move; +5. preserved mcpp-side Red/Green evidence for peer-root canonicalization; +6. `mcpp test -p asio-short` after the move; +7. inspection of `tests/examples/asio-short/mcpp.lock` for + `namespace = "chriskohlhoff"` and `version = "1.38.1"`; +8. `mcpp test -p asio-module` to preserve qualified-token behavior; +9. the workspace scope selected by the current validation workflow. + +The PR must pass every Linux, macOS, and Windows job instantiated by the live +workflow. One local host is not evidence for all declared platforms. + +## 10. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| The revert deletes the module workspace member | Resolve `mcpp.toml` manually and review the final member list | +| Bare lookup keeps an empty namespace | Require the mcpp canonicalization release before raising the index floor | +| Both spellings produce duplicate module instances | Add a mixed-spelling graph test in mcpp and assert one resolved identity | +| Qualified lookup breaks after the filename move | Keep the existing qualified consumer unchanged and run it after the move | +| Stale comments advertise header-only support | Search the changed tree for `compat.asio`, `header-only`, and `#include ` | +| The fallback disappears in mcpp 1.0.0 | Record a release-blocking alias/canonical-name migration follow-up before 1.0.0 | +| Archive or platform behavior changes accidentally | Move the descriptor without changing its xpm, hashes, recipe, or platform blocks | + +## 11. Acceptance criteria + +- the prerequisite mcpp release canonicalizes an identity-verified peer-root + hit to the descriptor's declared namespace; +- `index.toml` and every active workflow use that release or newer; +- `pkgs/c/compat.asio.lua` and `tests/examples/asio` no longer exist; +- no header-only Asio package is published by this index; +- exactly one Asio 1.38.1 implementation descriptor exists at + `pkgs/a/asio.lua`; +- that descriptor still declares `chriskohlhoff.asio`; +- both dependency spellings build and import module `asio`; +- both lockfiles identify the package as `chriskohlhoff.asio@1.38.1`; +- existing module behavior and three-platform coverage remain green; +- the PR documents that bare-filename fallback is temporary through the + pre-1.0 compatibility window; +- no forwarding package, mirror upload, or unrelated resolver change is + included. From 657e48ffd0edb2db4306fc8d3b090cc19430ca0f Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:24:18 +0800 Subject: [PATCH 02/11] docs: simplify asio module package migration --- ...tire-compat-asio-and-bare-module-design.md | 374 ++++++++---------- 1 file changed, 169 insertions(+), 205 deletions(-) diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md index b8f3313..95be3a2 100644 --- a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md @@ -1,179 +1,130 @@ -# Retire `compat.asio` and expose the Asio module through the bare package token +# Retire `compat.asio` and make `asio@1.38.1` module-only Date: 2026-07-20 ## 1. Decision -Retire the transitional header-only package introduced by mcpplibs/mcpp-index -PR #73. The public Asio integration will be module-only: +Retire the transitional header-only Asio package introduced by +mcpplibs/mcpp-index PR #73. The index will publish one Asio 1.38.1 package, +consumed only as a C++23 module: + +```bash +mcpp add asio@1.38.1 +``` ```cpp import std; import asio; ``` -Keep one published package identity and one implementation descriptor: +The current module recipe introduced by PR #80 remains the implementation, but +its package identity changes from `chriskohlhoff.asio@1.38.1` to the default +root package `asio@1.38.1`. -- package identity: `chriskohlhoff.asio@1.38.1`; -- qualified dependency token: `chriskohlhoff.asio@1.38.1`; -- bare dependency token: `asio@1.38.1`; -- C++ module name: `asio`. +The old qualified token `mcpp add chriskohlhoff.asio@1.38.1` is not retained as +an alias and is not part of the new compatibility contract. -Both dependency tokens must resolve to the same descriptor and the same locked -package identity. No forwarding package, second recipe, or header-only feature -will remain. Achieving that contract requires a narrowly scoped mcpp resolver -fix before the index change is published; moving the descriptor alone is not -sufficient. +## 2. Goals and non-goals -## 2. Scope +Goals: -This change will: +- remove `compat.asio@1.38.1` and all header-only consumer coverage; +- preserve the existing `import asio;` module implementation and behavior; +- make `asio@1.38.1` the only supported dependency identity and CLI token; +- keep one descriptor, one package identity, one lockfile identity, and one + module test member; +- preserve the existing archives, mirrors, hashes, platforms, generated module + wrapper, and separate-compilation build configuration. -1. canonicalize peer-root descriptor hits in mcpp to their declared package - identity; -2. release that resolver behavior and adopt the release in mcpp-index; -3. revert the repository content introduced by PR #73; -4. preserve the module package introduced by PR #80; -5. move the module descriptor from - `pkgs/c/chriskohlhoff.asio.lua` to `pkgs/a/asio.lua`; -6. retain `package.namespace = "chriskohlhoff"` and - `package.name = "chriskohlhoff.asio"` inside that descriptor; -7. remove module documentation that still describes `compat.asio` as a - companion or fallback; -8. add consumer coverage for both qualified and bare dependency tokens. +Non-goals: -This change will not: +- supporting `#include ` through mcpp-index; +- selecting header-only/module behavior through `features`; +- retaining `chriskohlhoff.asio` through an alias, redirect, forwarding package, + or non-canonical filename fallback; +- changing mcpp core package resolution; +- publishing a new Asio upstream version or changing source bytes. -- retain `#include ` as a supported package contract; -- add `features` for header-only/module selection; -- add a meta-package or forwarding dependency; -- change the Asio 1.38.1 source archives, mirrors, SHA-256 values, module - wrapper, supported platforms, or separate-compilation defines; -- add a general-purpose package alias schema or change qualified-selector - semantics unrelated to peer-root identity canonicalization. - -## 3. Revert boundary +## 3. Revert PR #73 PR #73 was squash-merged as the single-parent commit -`b3ebdd15bc3b56dc61cb91ab5b592200f713709f`. The implementation must therefore -start with: +`b3ebdd15bc3b56dc61cb91ab5b592200f713709f`. Revert it with: ```bash git revert b3ebdd15bc3b56dc61cb91ab5b592200f713709f ``` -It must not use `git revert -m 1`; `-m` is only for reverting a merge commit. +Do not use `git revert -m 1`; the commit is not a merge commit. The reverse patch removes: - `.agents/docs/2026-07-17-add-asio-plan.md`; - `pkgs/c/compat.asio.lua`; - `tests/examples/asio/mcpp.toml`; -- the six header-only tests under `tests/examples/asio/tests/`; -- the `tests/examples/asio` workspace member. +- all six header-only tests under `tests/examples/asio/tests/`; +- `tests/examples/asio` from the root workspace. -Applying the revert to the current `origin/main` conflicts only in the root -`mcpp.toml`, because later PRs added adjacent workspace members. Resolve that -conflict by removing only `tests/examples/asio`; retain -`tests/examples/asio-module` and every later member. +On the current `origin/main`, the revert conflicts only in the root +`mcpp.toml`. Resolve it by removing only `tests/examples/asio`; retain +`tests/examples/asio-module` and every workspace member added after PR #73. -The implementation PR should keep the generated revert commit as the first -commit, then add the module-token migration as a second commit. This preserves -the provenance of the retired package while keeping the new behavior reviewable. +Keep the resolved revert as its own commit so the removal remains traceable to +PR #73. -## 4. Descriptor identity and lookup +## 4. Rename the module package identity -The descriptor moves as follows: +Move the descriptor: ```text pkgs/c/chriskohlhoff.asio.lua -> pkgs/a/asio.lua ``` -Only the repository path changes. These descriptor fields remain unchanged: +Change its identity fields from: ```lua namespace = "chriskohlhoff" name = "chriskohlhoff.asio" ``` -The current mcpp resolver treats descriptor filenames as lookup hints and the -declared `(namespace, short name)` as the package identity. The new filename -lets the current lookup layer find both requested spellings: - -1. A bare `asio` selector produces default and peer-root candidates. The - peer-root lookup checks `asio.lua`, then accepts the descriptor by its - declared short name `asio`. -2. A qualified `chriskohlhoff.asio` selector first checks the qualified - filename and then the supported bare-filename fallback. It finds - `asio.lua` and verifies the declared namespace `chriskohlhoff`. -3. The selected dependency coordinate must then be canonicalized to the - descriptor identity before installation, graph deduplication, and lockfile - generation. - -Step 3 is not true in the current mcpp implementation. When the peer-root -candidate has an empty namespace, `selectDependencyCandidate` keeps that empty -namespace even after reading a descriptor that explicitly declares -`chriskohlhoff`. The immediate effects are: - -- the bare dependency is installed and locked as a root `asio` coordinate; -- the qualified dependency is installed and locked as - `chriskohlhoff.asio`; -- a graph containing both spellings can treat them as two package instances - and encounter duplicate exported module `asio` definitions. - -The mcpp prerequisite must fix the source of that divergence. When an empty -peer-root candidate matches a descriptor with an explicit namespace, -candidate selection must replace the selected coordinate with the descriptor's -canonical `(namespace, short name)`. For this package, both inputs then become -`(chriskohlhoff, asio)` before fetch, deduplication, and lock serialization. - -This rule is intentionally narrower than a general alias facility: - -- it applies only after an existing peer-root lookup has found and - identity-verified a descriptor; -- it does not add new filename candidates or scan arbitrary descriptors; -- root packages whose descriptors declare no namespace remain root packages; -- qualified selectors continue to require an exact declared namespace. - -`mcpp add` itself only writes the dependency token to `mcpp.toml`; resolution -happens during the subsequent build or test. Validation must therefore run a -consumer build and inspect the resulting lockfile rather than treating a -successful `mcpp add` command as proof. - -## 5. Compatibility lifetime - -The index-only solution intentionally uses mcpp's non-canonical descriptor -filename fallback. The current resolver source marks this compatibility path -for removal in mcpp 1.0.0. - -Consequences: - -- the design is valid for the current workflow-pinned mcpp and current index; -- a new mcpp release containing peer-root identity canonicalization is required - before the retirement PR can merge; -- `index.toml` and every active workflow pin must adopt that release together; -- before mcpp 1.0.0 removes the fallback, the ecosystem must either introduce - a first-class package alias mechanism or choose one canonical dependency - token; -- the retirement PR must state this migration obligation explicitly instead - of presenting the bare filename as a permanent alias contract. - -The descriptor must not omit or falsify its declared identity to make lookup -easier. Identity verification remains authoritative. - -## 6. Consumer tests - -Keep `tests/examples/asio-module` as the qualified-token consumer. It continues -to declare: +to: + +```lua +namespace = "" +name = "asio" +``` + +This is a canonical default-root package shape already used by module packages +such as `imgui`, `ffmpeg`, and `opencv`. The descriptor filename, declared +identity, dependency key, install target, and lockfile identity all become the +same bare name. No package alias or compatibility fallback is involved. + +Do not change the following parts of the descriptor: + +- version `1.38.1`; +- Linux/macOS upstream archive and SHA-256; +- Windows symlink-free archive and SHA-256; +- GLOBAL/CN mirror tables; +- `generated_files` module wrapper; +- `modules = { "asio" }`; +- `*/src/asio.cpp` separate-compilation source; +- `ASIO_STANDALONE`, `ASIO_SEPARATE_COMPILATION`, + `ASIO_DISABLE_BOOST_CONTEXT_FIBER`, and `ASIO_HAS_THREADS`; +- platform link settings. + +## 5. Consumer contract + +Update `tests/examples/asio-module/mcpp.toml` from the qualified local index: ```toml +[indices] +chriskohlhoff = { path = "../../.." } + [dependencies.chriskohlhoff] asio = "1.38.1" ``` -Add a small second workspace member, `tests/examples/asio-short`, for the bare -token. It redirects the default index to this checkout and declares: +to the default-root local index: ```toml [indices] @@ -183,120 +134,133 @@ default = { path = "../../.." } asio = "1.38.1" ``` -The short-token member needs one focused test that imports `std` and `asio`, -constructs an `asio::io_context`, runs a posted operation, and returns nonzero -if the operation did not execute. The existing `asio-module` member remains -the comprehensive module API suite; duplicating its five tests in the alias -member would add maintenance without increasing selector coverage. +Keep the existing five module consumer tests. They already cover core runtime +behavior, coroutines, networking, experimental APIs, and the exported surface. +No second alias-specific member is needed because there is only one supported +package token. -The regression contract is: +The resulting lockfile contract is: -| Consumer | Dependency spelling | Required result | -| --- | --- | --- | -| `asio-module` | `chriskohlhoff.asio@1.38.1` | imports and exercises module `asio` | -| `asio-short` | `asio@1.38.1` | imports and exercises the same module | -| both | generated `mcpp.lock` | namespace is `chriskohlhoff`; version is `1.38.1` | +```toml +[package."asio"] +version = "1.38.1" +``` -The implementation should first add the bare-token consumer while the -descriptor still has the qualified filename and record the expected lookup -failure. After moving the descriptor but before applying the mcpp fix, record -the namespace/duplicate-identity failure. The mcpp canonicalization change is -the Green condition for the complete two-token contract. +It must not contain `namespace = "compat"` or +`namespace = "chriskohlhoff"` for Asio. -## 7. Documentation cleanup +## 6. Documentation cleanup -The current module descriptor still calls `compat.asio` its header-only -companion and recommends it for unsupported module APIs. Those statements -become false once PR #73 is reverted. +The module descriptor currently describes `compat.asio` as a header-only +companion and tells users to select it for APIs outside the wrapper. Remove or +rewrite those statements. -Update the descriptor comments to state: +The retained documentation must state: +- installation: `mcpp add asio@1.38.1`; +- consumption: `import std; import asio;`; - the package is module-only; -- consumers use `import std; import asio;`; -- `mcpp add asio@1.38.1` and - `mcpp add chriskohlhoff.asio@1.38.1` currently select the same package; - APIs not exported by the wrapper are unavailable through this package; -- `#include ` is outside the supported mcpp-index contract. +- textual inclusion with `#include ` is outside the supported + mcpp-index contract; +- `chriskohlhoff.asio@1.38.1` was the retired pre-rename package token and is + not a supported alias. -Also remove comparison comments in `tests/examples/asio-module` that point to -the deleted header-only member. Do not rewrite unrelated package documentation. +Remove comparison comments in `tests/examples/asio-module` that refer to the +deleted `tests/examples/asio` member. Do not rewrite unrelated package docs. -## 8. Delivery sequence +## 7. Compatibility impact -Deliver the work in two repositories and do not merge the index change against -an unreleased mcpp commit. +This is an intentional package-identity replacement: -### Phase A: mcpp resolver +| Old dependency | New state | +| --- | --- | +| `compat.asio@1.38.1` | removed; header-only consumption unsupported | +| `chriskohlhoff.asio@1.38.1` | removed; no alias retained | +| `asio@1.38.1` | canonical module package | -1. Add a failing e2e case based on the existing custom-namespace, - non-canonical-filename fixture. Request the package once by its bare short - name and once by its qualified name in the same graph. -2. Assert that the current resolver produces different coordinates or a - duplicate-module failure. -3. Canonicalize an identity-verified empty peer-root hit to the descriptor's - declared identity. -4. Assert one resolved package instance, one exported module, and a lockfile - namespace matching the descriptor. -5. Run the relevant unit/e2e suites and the complete mcpp verification required - by its contribution workflow. -6. Merge and release mcpp through the normal release process. +Existing module consumers migrate with: -### Phase B: mcpp-index retirement +```bash +mcpp remove chriskohlhoff.asio +mcpp add asio@1.38.1 +``` + +Their C++ source remains `import std; import asio;`. They must regenerate the +lockfile/build state so the retired namespace does not remain pinned. + +Historical index artifacts remain historical; do not rewrite or manually +republish them. The new rolling index simply stops advertising the two retired +identities. -1. Raise `index.toml`'s `min_mcpp` and every active validation pin to the new - release in the same commit. +## 8. Test-first implementation sequence + +1. Create a topic branch from the latest `origin/main`. 2. Revert PR #73 and resolve only the root workspace conflict. -3. Move the module descriptor to `pkgs/a/asio.lua` without changing its recipe. -4. Add the bare-token member and update stale module comments. -5. Run targeted and workspace validation on all workflow platforms. -6. Open a focused revert/migration PR; maintainers merge it. +3. Change `tests/examples/asio-module` to the bare dependency while the module + descriptor still has the qualified identity. Run the targeted test and + record the expected package-not-found failure. +4. Move the descriptor to `pkgs/a/asio.lua` and change its declared identity to + root `asio`. +5. Update stale descriptor and test comments. +6. Run the targeted test again and inspect its generated lockfile. +7. Run descriptor, mirror, workspace, and diff validation. +8. Commit the module identity migration separately from the PR #73 revert. +9. Push a topic branch and open a focused PR only after explicit authorization. + +The Red/Green boundary is the dependency identity: the same module test must +fail before the descriptor rename and pass after it. Do not weaken the module +behavior assertions to make the migration pass. ## 9. Validation -Use the newly released mcpp version after Phase A. Required index-side local -evidence, in order: +Use the mcpp version pinned by the live `origin/main` workflow. The descriptor +uses existing grammar, so this change does not raise `index.toml`'s client floor +or the workflow pin. + +Required local evidence, in order: 1. `git diff --check`; 2. Lua syntax and repository descriptor lint for `pkgs/a/asio.lua`; 3. strict `mcpp xpkg parse pkgs/a/asio.lua`; -4. repository mirror validation, proving URL/SHA tables were not damaged by - the move; -5. preserved mcpp-side Red/Green evidence for peer-root canonicalization; -6. `mcpp test -p asio-short` after the move; -7. inspection of `tests/examples/asio-short/mcpp.lock` for - `namespace = "chriskohlhoff"` and `version = "1.38.1"`; -8. `mcpp test -p asio-module` to preserve qualified-token behavior; +4. repository mirror validation, confirming the move did not alter URL/SHA + tables; +5. the recorded bare-dependency Red before the identity change; +6. `mcpp test -p asio-module` after the identity change; +7. inspection of `tests/examples/asio-module/mcpp.lock`, confirming root package + `asio` at version `1.38.1` and no retired namespace; +8. a search proving that no active descriptor, workspace dependency, or + consumer instruction still advertises `compat.asio` or + `chriskohlhoff.asio`; 9. the workspace scope selected by the current validation workflow. -The PR must pass every Linux, macOS, and Windows job instantiated by the live -workflow. One local host is not evidence for all declared platforms. +The implementation PR must pass every Linux, macOS, and Windows job created by +the live workflow. One local platform is not evidence for all declared +platforms. ## 10. Risks and mitigations | Risk | Mitigation | | --- | --- | -| The revert deletes the module workspace member | Resolve `mcpp.toml` manually and review the final member list | -| Bare lookup keeps an empty namespace | Require the mcpp canonicalization release before raising the index floor | -| Both spellings produce duplicate module instances | Add a mixed-spelling graph test in mcpp and assert one resolved identity | -| Qualified lookup breaks after the filename move | Keep the existing qualified consumer unchanged and run it after the move | -| Stale comments advertise header-only support | Search the changed tree for `compat.asio`, `header-only`, and `#include ` | -| The fallback disappears in mcpp 1.0.0 | Record a release-blocking alias/canonical-name migration follow-up before 1.0.0 | -| Archive or platform behavior changes accidentally | Move the descriptor without changing its xpm, hashes, recipe, or platform blocks | +| The revert removes later workspace members | Resolve `mcpp.toml` manually and review the complete final member list | +| The recipe changes during the identity move | Review the move with whitespace-insensitive diff and compare archive/hash/build blocks | +| A stale qualified dependency survives | Search active manifests and inspect the generated lockfile | +| Header-only support is accidentally retained | Require both the descriptor and `tests/examples/asio` tree to be absent | +| Existing qualified-token consumers break unexpectedly | State the breaking migration explicitly in the PR and package comments | +| Module behavior regresses | Keep and run all five existing module tests on the three-platform CI matrix | ## 11. Acceptance criteria -- the prerequisite mcpp release canonicalizes an identity-verified peer-root - hit to the descriptor's declared namespace; -- `index.toml` and every active workflow use that release or newer; - `pkgs/c/compat.asio.lua` and `tests/examples/asio` no longer exist; -- no header-only Asio package is published by this index; -- exactly one Asio 1.38.1 implementation descriptor exists at - `pkgs/a/asio.lua`; -- that descriptor still declares `chriskohlhoff.asio`; -- both dependency spellings build and import module `asio`; -- both lockfiles identify the package as `chriskohlhoff.asio@1.38.1`; -- existing module behavior and three-platform coverage remain green; -- the PR documents that bare-filename fallback is temporary through the - pre-1.0 compatibility window; -- no forwarding package, mirror upload, or unrelated resolver change is - included. +- `pkgs/c/chriskohlhoff.asio.lua` no longer exists; +- exactly one Asio descriptor exists at `pkgs/a/asio.lua`; +- that descriptor declares root package `asio@1.38.1`; +- `mcpp add asio@1.38.1` followed by a build imports module `asio`; +- `mcpp add chriskohlhoff.asio@1.38.1` is not claimed or tested as supported; +- the generated lockfile contains only the root Asio identity; +- all five existing module tests pass without reduced assertions; +- all active `compat.asio` and qualified-token instructions are removed; +- archives, hashes, mirrors, platforms, module wrapper, and build defines are + unchanged; +- no mcpp core change, alias package, forwarding package, feature split, mirror + upload, or manual index publication is included. From 06f970048ecba296dfa32ce477fb249afb92ed0b Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 21:03:57 +0800 Subject: [PATCH 03/11] docs: add asio module migration plan --- ...retire-compat-asio-and-bare-module-plan.md | 564 ++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 .agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md new file mode 100644 index 0000000..efad626 --- /dev/null +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md @@ -0,0 +1,564 @@ +# Asio Module-Only Package Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 删除 `compat.asio` header-only 包,将现有 Asio module recipe 改为唯一根包 `asio@1.38.1`,并通过 `mcpp add asio@1.38.1` 消费。 + +**Architecture:** 先精确 revert PR #73 的 squash commit,再把 PR #80 的 Form B descriptor 从 `chriskohlhoff.asio` 身份迁移为默认根身份 `asio`。保留原 module wrapper、archive、mirror、hash、三平台配置和五个 module 行为测试;不保留旧全名 alias,不修改 mcpp core。 + +**Tech Stack:** Git, Lua xpkg descriptor, workflow-pinned mcpp (currently 0.0.101), C++23 modules, GitHub Actions workspace validation. + +--- + +**Design reference:** `.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md` + +**External-action boundary:** 本计划只产生本地提交。不要执行 `git push`、`gh pr create`、mirror 上传、tag、release 或手工 index 发布。完成后停止并等待用户审批。 + +## File map + +| Path | Action | Responsibility | +| --- | --- | --- | +| `.agents/docs/2026-07-17-add-asio-plan.md` | Delete via revert | PR #73 的 header-only 设计记录 | +| `pkgs/c/compat.asio.lua` | Delete via revert | 退役的 header-only package | +| `tests/examples/asio/` | Delete via revert | 退役的六项 header-only consumer tests | +| `mcpp.toml` | Modify via revert conflict resolution | 删除 `tests/examples/asio`,保留 `asio-module` 和所有后续 members | +| `pkgs/c/chriskohlhoff.asio.lua` | Rename/delete | PR #80 的旧 namespaced module descriptor | +| `pkgs/a/asio.lua` | Create by `git mv`, then modify | 唯一 canonical `asio@1.38.1` module descriptor | +| `tests/examples/asio-module/mcpp.toml` | Modify | 使用 default local index 和 bare `asio` dependency | +| `tests/examples/asio-module/tests/experimental.cpp` | Modify comments only | 删除指向已退役 header test 的说明 | +| `tests/examples/asio-module/tests/network.cpp` | Modify comments only | 删除指向已退役 header test 的说明 | + +### Task 1: Refresh the baseline and prove the current module package is green + +**Files:** +- Read: `.github/workflows/validate.yml` +- Read: `index.toml` +- Test: `tests/examples/asio-module/` + +- [ ] **Step 1: Confirm branch and worktree state** + +Run: + +```bash +git branch --show-current +git status --short --branch +``` + +Expected: + +```text +refactor/asio-module +## refactor/asio-module...origin/main [ahead 3] +``` + +The exact ahead count may increase only by approved plan/doc commits. There must be no unstaged or staged implementation files. + +- [ ] **Step 2: Refresh `origin/main` and check for duplicate Asio work** + +Run: + +```bash +git fetch origin main +git log --oneline HEAD..origin/main +gh pr list --repo mcpplibs/mcpp-index --state open --search "asio in:title" --json number,title,headRefName,url +``` + +Expected: no unreviewed upstream Asio change and no duplicate open Asio PR. If `HEAD..origin/main` contains only unrelated commits, rebase the unpushed branch with the one-shot repository identity: + +```bash +git -c user.name=wellwei \ + -c user.email=96378453+wellwei@users.noreply.github.com \ + -c core.editor=true \ + rebase origin/main +``` + +If upstream changes any Asio path, `mcpp.toml`, `index.toml`, or the validation contract, stop and update this plan before implementation. + +- [ ] **Step 3: Obtain the exact workflow-pinned mcpp client** + +On the current macOS arm64 workspace, run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +TOOLS="/private/tmp/mcpp-index-asio-tools-${PIN}" +mkdir -p "$TOOLS" +curl -L -fsS -o "$TOOLS/mcpp.tar.gz" \ + "https://github.com/mcpp-community/mcpp/releases/download/v${PIN}/mcpp-${PIN}-macosx-arm64.tar.gz" +tar -xzf "$TOOLS/mcpp.tar.gz" -C "$TOOLS" +MCPP="$TOOLS/mcpp-${PIN}-macosx-arm64/bin/mcpp" +"$MCPP" --version +``` + +Expected: the printed mcpp version exactly equals `PIN` (currently `0.0.101`). Do not use the host's older `mcpp 0.0.96` binary. + +- [ ] **Step 4: Run the current qualified-token baseline** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +git clean -fdX tests/examples/asio-module +MCPP_INDEX_MIRROR=GLOBAL "$MCPP" test -p asio-module +``` + +Expected: `5 passed; 0 failed`. The network test must remain enabled. If sandboxed loopback fails with `bind: Operation not permitted`, rerun this same command with local-network permission; do not weaken or remove the test. + +### Task 2: Revert the header-only package from PR #73 + +**Files:** +- Delete: `.agents/docs/2026-07-17-add-asio-plan.md` +- Delete: `pkgs/c/compat.asio.lua` +- Delete: `tests/examples/asio/mcpp.toml` +- Delete: `tests/examples/asio/tests/core.cpp` +- Delete: `tests/examples/asio/tests/coroutine.cpp` +- Delete: `tests/examples/asio/tests/experimental.cpp` +- Delete: `tests/examples/asio/tests/network.cpp` +- Delete: `tests/examples/asio/tests/platform.cpp` +- Delete: `tests/examples/asio/tests/surface.cpp` +- Modify: `mcpp.toml:9` + +- [ ] **Step 1: Verify the revert target is the single-parent squash commit** + +Run: + +```bash +git show -s --format='%H%n%P%n%s' b3ebdd15bc3b56dc61cb91ab5b592200f713709f +``` + +Expected: commit `b3ebdd15...`, exactly one parent, subject `feat(pkgs): add standalone asio 1.38.1 (#73)`. + +- [ ] **Step 2: Start the revert and confirm the only conflict** + +Run: + +```bash +git revert --no-edit b3ebdd15bc3b56dc61cb91ab5b592200f713709f +``` + +Expected: nonzero exit with one content conflict in `mcpp.toml`. + +Run: + +```bash +git diff --name-only --diff-filter=U +``` + +Expected: + +```text +mcpp.toml +``` + +If any other file conflicts, stop and re-evaluate the current upstream baseline. + +- [ ] **Step 3: Resolve `mcpp.toml` to the exact member list** + +Use `apply_patch` to replace the conflicted `[workspace]` block with: + +```toml +[workspace] +members = [ + "tests/examples/archive", + "tests/examples/asio-module", + "tests/examples/build-mcpp", + "tests/examples/cjson", + "tests/examples/core", + "tests/examples/eigen", + "tests/examples/ffmpeg", + "tests/examples/ffmpeg-module", + "tests/examples/fmtlib.fmt", + "tests/examples/gui-stack", + "tests/examples/imgui", + "tests/examples/imgui-module", + "tests/examples/imgui-window", + "tests/examples/marzer.tomlplusplus", + "tests/examples/nlohmann.json", + "tests/examples/openblas", + "tests/examples/opencv", + "tests/examples/opencv-win", + "tests/examples/opencv-unifont", + "tests/examples/opencv-dnn", + "tests/examples/opencv-module", + "tests/examples/opencv-module-dnn", + "tests/examples/opencv-module-unifont", + "tests/examples/spdlog", + "tests/examples/spdlog-compiled", + "tests/examples/tinyhttps", +] +``` + +Before continuing, compare this block with the latest `origin/main:mcpp.toml`. The only removed member must be `tests/examples/asio`. + +- [ ] **Step 4: Complete the revert commit** + +Run: + +```bash +git add mcpp.toml +git -c user.name=wellwei \ + -c user.email=96378453+wellwei@users.noreply.github.com \ + -c core.editor=true \ + revert --continue +``` + +Expected: one new revert commit. + +- [ ] **Step 5: Verify the removal boundary** + +Run: + +```bash +test ! -e pkgs/c/compat.asio.lua +test ! -e tests/examples/asio +test ! -e .agents/docs/2026-07-17-add-asio-plan.md +test -e pkgs/c/chriskohlhoff.asio.lua +test -e tests/examples/asio-module/mcpp.toml +git show --stat --oneline HEAD +``` + +Expected: only PR #73 content is removed; PR #80 module files remain. + +### Task 3: Create the bare-token Red through the real `mcpp add` command + +**Files:** +- Modify: `tests/examples/asio-module/mcpp.toml` +- Test: `tests/examples/asio-module/tests/*.cpp` + +- [ ] **Step 1: Change only the local index routing and remove the old dependency** + +Use `apply_patch` to make `tests/examples/asio-module/mcpp.toml` exactly: + +```toml +# Asio C++23-module consumer test project: `import std; import asio;`. +# The public package is the default-root module-only `asio@1.38.1` package. +[package] +name = "asio-module-tests" +version = "0.1.0" + +[indices] +default = { path = "../../.." } +``` + +- [ ] **Step 2: Add the dependency through the requested CLI surface** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +cd tests/examples/asio-module +"$MCPP" add asio@1.38.1 +cd ../../.. +``` + +Expected: `mcpp add` reports `Adding asio v1.38.1 to dependencies`, and the manifest ends with: + +```toml +[dependencies] +asio = "1.38.1" +``` + +- [ ] **Step 3: Run the consumer test and verify the expected Red** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +git clean -fdX tests/examples/asio-module +set +e +MCPP_INDEX_MIRROR=GLOBAL "$MCPP" test -p asio-module \ + > /private/tmp/asio-module-bare-red.log 2>&1 +rc=$? +set -e +test "$rc" -ne 0 +rg -n "asio|not found" /private/tmp/asio-module-bare-red.log +``` + +Expected: failure because the local index has neither `pkgs/a/asio.lua` nor a remaining `compat.asio` fallback. Do not commit the failing state yet. + +### Task 4: Make the descriptor identity canonical and restore Green + +**Files:** +- Rename: `pkgs/c/chriskohlhoff.asio.lua` -> `pkgs/a/asio.lua` +- Modify: `pkgs/a/asio.lua:1` +- Modify: `tests/examples/asio-module/tests/experimental.cpp:1` +- Modify: `tests/examples/asio-module/tests/network.cpp:1` + +- [ ] **Step 1: Move the descriptor to its canonical root-package path** + +Run: + +```bash +git mv pkgs/c/chriskohlhoff.asio.lua pkgs/a/asio.lua +``` + +- [ ] **Step 2: Replace the stale descriptor preamble and package identity** + +Use `apply_patch` to replace everything before `package = {` with this exact preamble: + +```lua +-- asio -- standalone Asio 1.38.1 exposed as the C++23 module `asio` +-- (Form B inline descriptor, separate-compilation mode). +-- +-- Install and consume: +-- mcpp add asio@1.38.1 +-- import std; +-- import asio; +-- +-- The upstream 1.38.x release has no module interface unit. This descriptor +-- generates a reviewed `asio.cppm` wrapper and compiles upstream `src/asio.cpp` +-- with ASIO_SEPARATE_COMPILATION. `import std;` is required because this package +-- does not inject the standard library through the module boundary. +-- +-- This package is module-only. Textual `#include ` consumption and +-- APIs not exported by the wrapper are outside its mcpp-index contract. The +-- wrapper intentionally excludes SSL/TLS, local/POSIX/Windows handle APIs, +-- serial ports, pipes, file I/O, stackful spawn, and other surfaces listed by +-- headers that it does not include. +-- +-- ASIO_STANDALONE and ASIO_SEPARATE_COMPILATION are public build defines, but +-- preprocessor macros do not cross `import asio;`. Consumers should use C++ or +-- operating-system facilities instead of testing ASIO_HAS_* macros. +``` + +Then make the package table begin exactly: + +```lua +package = { + spec = "1", + namespace = "", + name = "asio", + description = "Standalone asio exposed as the C++23 module `asio` (separate compilation)", + licenses = {"BSL-1.0"}, + repo = "https://github.com/chriskohlhoff/asio", + type = "package", +``` + +Preserve the complete `xpm` and `mcpp` tables after this header. + +- [ ] **Step 3: Make the two remaining recipe comments self-contained** + +Replace the Windows archive comment with: + +```lua + -- Upstream tag archives carry two POSIX symlinks + -- (asio/include -> ../include, asio/src -> ../src) that tar.exe + -- cannot materialize on the Windows runner. This uses the existing + -- symlink-free repack documented by xlings-res/asio. +``` + +Replace the `ASIO_HAS_THREADS` comment with: + +```lua + -- ASIO_HAS_THREADS: asio's detection keys off CRT macros + -- (_MT/_REENTRANT/_POSIX_THREADS) that the workspace's llvm-on-Windows + -- toolchain does not define, otherwise silently selecting null_thread. + -- Pin the known multithreaded package contract; POSIX pthread selection + -- still runs beneath this define where applicable. +``` + +Do not change the associated URLs, hashes, sources, features, or flags. + +- [ ] **Step 4: Remove stale header-test comparisons from module tests** + +Make the opening of `tests/examples/asio-module/tests/experimental.cpp` exactly: + +```cpp +// Experimental channel/concurrent_channel/use_promise over the module surface. +import std; +import asio; +``` + +Make the opening of `tests/examples/asio-module/tests/network.cpp` exactly: + +```cpp +// TCP (acceptor/socket, async_read/async_write) and UDP (datagram send/receive) +// over the imported module surface. +import std; +import asio; +``` + +- [ ] **Step 5: Prove the recipe body did not change** + +Run both commands and compare the hashes: + +```bash +git show HEAD:pkgs/c/chriskohlhoff.asio.lua \ + | sed -E '/^[[:space:]]*--/d;/^[[:space:]]*$/d;/^[[:space:]]*namespace[[:space:]]*=/d;/^[[:space:]]*name[[:space:]]*=/d' \ + | shasum -a 256 +sed -E '/^[[:space:]]*--/d;/^[[:space:]]*$/d;/^[[:space:]]*namespace[[:space:]]*=/d;/^[[:space:]]*name[[:space:]]*=/d' pkgs/a/asio.lua \ + | shasum -a 256 +``` + +Expected: identical SHA-256 values. A mismatch means a non-comment recipe field changed; inspect and restore it before continuing. + +- [ ] **Step 6: Parse the descriptor and run the Green test** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +lua -e "assert(loadfile('pkgs/a/asio.lua', 't'))" +lua tests/check_mirror_urls.lua pkgs/a/asio.lua +"$MCPP" xpkg parse pkgs/a/asio.lua +git clean -fdX tests/examples/asio-module +MCPP_INDEX_MIRROR=GLOBAL "$MCPP" test -p asio-module +``` + +Expected: Lua syntax success, mirror check success, strict parse success, and `5 passed; 0 failed`. + +- [ ] **Step 7: Inspect the generated lock identity** + +Run: + +```bash +LOCK=tests/examples/asio-module/mcpp.lock +test -f "$LOCK" +rg -n '^\[package\."asio"\]$|^namespace[[:space:]]*=|^version[[:space:]]*=' "$LOCK" +``` + +Expected: `[package."asio"]` with version `1.38.1`; there must be no Asio namespace line for `compat` or `chriskohlhoff`. + +### Task 5: Validate the complete local change + +**Files:** +- Test: `pkgs/a/asio.lua` +- Test: `tests/examples/asio-module/` +- Test: root workspace + +- [ ] **Step 1: Verify the active-tree cleanup** + +Run: + +```bash +test ! -e pkgs/c/compat.asio.lua +test ! -e pkgs/c/chriskohlhoff.asio.lua +test ! -e tests/examples/asio +test -e pkgs/a/asio.lua +set +e +rg -n "compat\.asio|chriskohlhoff\.asio|tests/examples/asio([^\-]|$)" \ + mcpp.toml pkgs tests README.md +rc=$? +set -e +test "$rc" -eq 1 +``` + +Expected: the three absence checks pass and `rg` exits 1 because it finds no active package, workspace, test, or user-instruction references. The upstream repository URL `github.com/chriskohlhoff/asio` is allowed because it is not a package token. + +- [ ] **Step 2: Run whitespace, descriptor, and mirror checks** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +git diff --check +lua -e "assert(loadfile('pkgs/a/asio.lua', 't'))" +lua tests/check_mirror_urls.lua pkgs/a/asio.lua +"$MCPP" xpkg parse pkgs/a/asio.lua +``` + +Expected: all commands exit 0. + +- [ ] **Step 3: Re-run the targeted module suite from clean member state** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +git clean -fdX tests/examples/asio-module +MCPP_INDEX_MIRROR=GLOBAL "$MCPP" test -p asio-module +``` + +Expected: `5 passed; 0 failed`. + +- [ ] **Step 4: Run the full local workspace suite** + +Run: + +```bash +PIN=$(sed -n 's/^[[:space:]]*MCPP_VERSION: "\([^"]*\)"/\1/p' .github/workflows/validate.yml | head -1) +MCPP="/private/tmp/mcpp-index-asio-tools-${PIN}/mcpp-${PIN}-macosx-arm64/bin/mcpp" +MCPP_INDEX_MIRROR=GLOBAL "$MCPP" test --workspace +``` + +Expected: every member selected for macOS passes. Record the exact passed/failed totals. Linux and Windows matrix validation remains unverified until the user authorizes a push/PR; do not claim three-platform completion locally. + +### Task 6: Commit the module identity migration + +**Files:** +- Add: `pkgs/a/asio.lua` +- Delete: `pkgs/c/chriskohlhoff.asio.lua` +- Modify: `tests/examples/asio-module/mcpp.toml` +- Modify: `tests/examples/asio-module/tests/experimental.cpp` +- Modify: `tests/examples/asio-module/tests/network.cpp` + +- [ ] **Step 1: Review the exact implementation diff** + +Run: + +```bash +git status --short +git diff --find-renames --stat +git diff --find-renames -- \ + pkgs/a/asio.lua \ + pkgs/c/chriskohlhoff.asio.lua \ + tests/examples/asio-module +git diff --check +``` + +Expected: one descriptor rename with comment/identity changes, one manifest change, and two comment-only test changes. No archive, hash, generated wrapper, source, feature, or platform flag change. + +- [ ] **Step 2: Commit the Green implementation** + +Run: + +```bash +git add \ + pkgs/a/asio.lua \ + pkgs/c/chriskohlhoff.asio.lua \ + tests/examples/asio-module/mcpp.toml \ + tests/examples/asio-module/tests/experimental.cpp \ + tests/examples/asio-module/tests/network.cpp +git diff --cached --check +git -c user.name=wellwei \ + -c user.email=96378453+wellwei@users.noreply.github.com \ + commit -m "refactor(asio): make module package canonical" +``` + +Expected: one focused implementation commit after the separate PR #73 revert commit. + +### Task 7: Prepare the local approval handoff and stop + +**Files:** +- Read: all branch changes against `origin/main` + +- [ ] **Step 1: Verify final repository state** + +Run: + +```bash +git status --short --branch +git log --oneline --decorate origin/main..HEAD +git diff --stat origin/main...HEAD +git diff origin/main...HEAD --check +``` + +Expected: clean worktree; design/plan commits, one PR #73 revert commit, and one module migration commit. No uncommitted files. + +- [ ] **Step 2: Report evidence without external actions** + +Report to the user: + +- local branch name and commit list; +- deleted package/test paths; +- final descriptor identity and path; +- Red failure summary and Green targeted/full-workspace totals; +- descriptor/mirror/lockfile verification; +- Linux/Windows CI still pending because no PR was created. + +Stop here. Do not push the branch and do not create a PR until the user explicitly approves the reviewed local diff and verification evidence. From 98c53f32533c5e138e6bb461c119549ca4d3faa8 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 21:24:00 +0800 Subject: [PATCH 04/11] docs: adopt fork contribution workflow --- ...tire-compat-asio-and-bare-module-design.md | 6 ++-- ...retire-compat-asio-and-bare-module-plan.md | 28 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md index 95be3a2..1832e66 100644 --- a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md @@ -64,7 +64,7 @@ The reverse patch removes: - all six header-only tests under `tests/examples/asio/tests/`; - `tests/examples/asio` from the root workspace. -On the current `origin/main`, the revert conflicts only in the root +On the current `upstream/main`, the revert conflicts only in the root `mcpp.toml`. Resolve it by removing only `tests/examples/asio`; retain `tests/examples/asio-module` and every workspace member added after PR #73. @@ -195,7 +195,7 @@ identities. ## 8. Test-first implementation sequence -1. Create a topic branch from the latest `origin/main`. +1. Create a topic branch from the latest `upstream/main`. 2. Revert PR #73 and resolve only the root workspace conflict. 3. Change `tests/examples/asio-module` to the bare dependency while the module descriptor still has the qualified identity. Run the targeted test and @@ -214,7 +214,7 @@ behavior assertions to make the migration pass. ## 9. Validation -Use the mcpp version pinned by the live `origin/main` workflow. The descriptor +Use the mcpp version pinned by the live `upstream/main` workflow. The descriptor uses existing grammar, so this change does not raise `index.toml`'s client floor or the workflow pin. diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md index efad626..e70cd48 100644 --- a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md @@ -12,7 +12,9 @@ **Design reference:** `.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-design.md` -**External-action boundary:** 本计划只产生本地提交。不要执行 `git push`、`gh pr create`、mirror 上传、tag、release 或手工 index 发布。完成后停止并等待用户审批。 +**Remote topology:** `origin` is the writable fork `wellwei/mcpp-index`; `upstream` is the canonical `mcpplibs/mcpp-index`. Refresh and diff against `upstream/main`; publish the topic branch to `origin` only after local approval. + +**External-action boundary:** 本计划实施阶段只产生本地提交。不要执行 `git push`、`gh pr create`、mirror 上传、tag、release 或手工 index 发布。完成后停止并等待用户审批;获批后才把 `refactor/asio-module` 推到 `origin`,并从 `wellwei:refactor/asio-module` 向 `mcpplibs:main` 创建 PR。 ## File map @@ -48,28 +50,28 @@ Expected: ```text refactor/asio-module -## refactor/asio-module...origin/main [ahead 3] +## refactor/asio-module...upstream/main [ahead 4] ``` The exact ahead count may increase only by approved plan/doc commits. There must be no unstaged or staged implementation files. -- [ ] **Step 2: Refresh `origin/main` and check for duplicate Asio work** +- [ ] **Step 2: Refresh `upstream/main` and check for duplicate Asio work** Run: ```bash -git fetch origin main -git log --oneline HEAD..origin/main +git fetch upstream main +git log --oneline HEAD..upstream/main gh pr list --repo mcpplibs/mcpp-index --state open --search "asio in:title" --json number,title,headRefName,url ``` -Expected: no unreviewed upstream Asio change and no duplicate open Asio PR. If `HEAD..origin/main` contains only unrelated commits, rebase the unpushed branch with the one-shot repository identity: +Expected: no unreviewed upstream Asio change and no duplicate open Asio PR. If `HEAD..upstream/main` contains only unrelated commits, rebase the unpushed branch with the one-shot repository identity: ```bash git -c user.name=wellwei \ -c user.email=96378453+wellwei@users.noreply.github.com \ -c core.editor=true \ - rebase origin/main + rebase upstream/main ``` If upstream changes any Asio path, `mcpp.toml`, `index.toml`, or the validation contract, stop and update this plan before implementation. @@ -188,7 +190,7 @@ members = [ ] ``` -Before continuing, compare this block with the latest `origin/main:mcpp.toml`. The only removed member must be `tests/examples/asio`. +Before continuing, compare this block with the latest `upstream/main:mcpp.toml`. The only removed member must be `tests/examples/asio`. - [ ] **Step 4: Complete the revert commit** @@ -535,7 +537,7 @@ Expected: one focused implementation commit after the separate PR #73 revert com ### Task 7: Prepare the local approval handoff and stop **Files:** -- Read: all branch changes against `origin/main` +- Read: all branch changes against `upstream/main` - [ ] **Step 1: Verify final repository state** @@ -543,9 +545,9 @@ Run: ```bash git status --short --branch -git log --oneline --decorate origin/main..HEAD -git diff --stat origin/main...HEAD -git diff origin/main...HEAD --check +git log --oneline --decorate upstream/main..HEAD +git diff --stat upstream/main...HEAD +git diff upstream/main...HEAD --check ``` Expected: clean worktree; design/plan commits, one PR #73 revert commit, and one module migration commit. No uncommitted files. @@ -561,4 +563,4 @@ Report to the user: - descriptor/mirror/lockfile verification; - Linux/Windows CI still pending because no PR was created. -Stop here. Do not push the branch and do not create a PR until the user explicitly approves the reviewed local diff and verification evidence. +Stop here. Do not push the branch and do not create a PR until the user explicitly approves the reviewed local diff and verification evidence. After that approval, publish with `git push -u origin refactor/asio-module` and create the PR against `mcpplibs/mcpp-index:main`; required checks must pass before maintainers merge it. From 61e50532f8ffa61ac3ea6f01ba3630a21f15b7ca Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 21:37:04 +0800 Subject: [PATCH 05/11] Revert "feat(pkgs): add standalone asio 1.38.1 (#73)" This reverts commit b3ebdd15bc3b56dc61cb91ab5b592200f713709f. --- .agents/docs/2026-07-17-add-asio-plan.md | 183 --------------------- mcpp.toml | 1 - pkgs/c/compat.asio.lua | 95 ----------- tests/examples/asio/mcpp.toml | 10 -- tests/examples/asio/tests/core.cpp | 72 -------- tests/examples/asio/tests/coroutine.cpp | 34 ---- tests/examples/asio/tests/experimental.cpp | 42 ----- tests/examples/asio/tests/network.cpp | 103 ------------ tests/examples/asio/tests/platform.cpp | 42 ----- tests/examples/asio/tests/surface.cpp | 84 ---------- 10 files changed, 666 deletions(-) delete mode 100644 .agents/docs/2026-07-17-add-asio-plan.md delete mode 100644 pkgs/c/compat.asio.lua delete mode 100644 tests/examples/asio/mcpp.toml delete mode 100644 tests/examples/asio/tests/core.cpp delete mode 100644 tests/examples/asio/tests/coroutine.cpp delete mode 100644 tests/examples/asio/tests/experimental.cpp delete mode 100644 tests/examples/asio/tests/network.cpp delete mode 100644 tests/examples/asio/tests/platform.cpp delete mode 100644 tests/examples/asio/tests/surface.cpp diff --git a/.agents/docs/2026-07-17-add-asio-plan.md b/.agents/docs/2026-07-17-add-asio-plan.md deleted file mode 100644 index 8087396..0000000 --- a/.agents/docs/2026-07-17-add-asio-plan.md +++ /dev/null @@ -1,183 +0,0 @@ -# Add standalone Asio 1.38.1 as a header-only package - -Date: 2026-07-17 - -This document defines the contribution scope for `compat.asio@1.38.1`. It is -based on the current `origin/main`, its active validation workflow, and mcpp -0.0.94. Dated repository guidance is treated as historical when it conflicts -with those live contracts. - -## 1. Scope - -This contribution adds only the upstream standalone, header-only Asio package. -Consumers use `#include ` and related upstream headers. - -The following work is intentionally excluded: - -- a native C++ module or `import asio;` interface; -- OpenSSL or wolfSSL integration; -- Boost.Context, Boost.Regex, or Boost.Date_Time integration; -- liburing integration; -- changes to repository contribution guidance or README content. - -Native module adaptation remains separate because it has a different build and -consumer contract and requires its own compatibility evidence. - -## 2. Upstream identity and archive evidence - -- Canonical repository: `https://github.com/chriskohlhoff/asio`. -- Release tag: `asio-1-38-1`, the latest numeric Asio tag observed on - 2026-07-17. -- Tag commit: `bbecff21a23b97c34641f0f1f08b28c91b9c77cf`. -- License: Boost Software License 1.0 (`BSL-1.0`), confirmed from upstream - `COPYING` and `LICENSE_1_0.txt` at the tag. -- Linux/macOS archive: tag tarball, SHA-256 - `2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc`, - CN-mirrored byte-identically at - `https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz`. -- Windows archive: `asio-1.38.1-nosymlinks.tar.gz`, SHA-256 - `77f74094bb12cd867a6edbf5736bbed816c6ce0906e880de8573097a81714d89`, hosted at - `https://github.com/xlings-res/asio/releases/download/1.38.1/` (GLOBAL) and - `https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/` (CN). - -Two independent downloads of the upstream tarball produced the same SHA-256. -All archives are wrapped in `asio-asio-1-38-1/`, and their public entry header -is `asio-asio-1-38-1/include/asio.hpp`. Therefore `*/include` is the required -consumer include root. - -Both upstream tag archive encodings (tar.gz and zip) contain -`asio/include -> ../include` and `asio/src -> ../src` POSIX symlink entries. -The Windows extraction path (`tar.exe` via xlings) cannot materialize them, so -both encodings fail on the Windows runner, and upstream publishes no -symlink-free asset for 1.38.x (GitHub has no release assets; SourceForge stops -at 1.36.0). The Windows entry therefore uses a repackaged variant of the -upstream tag tarball with only those two symlink entries removed -(`tar --delete` + `gzip -n -9`); all 1544 regular files are byte-identical to -upstream. Provenance is documented in the `xlings-res/asio` repository README. - -The upstream tag is annotated but not cryptographically signed. Reproducibility -is enforced by the descriptor's pinned archive digest. - -## 3. Package shape and descriptor contract - -Asio is a third-party project without an mcpp manifest in the selected release, -so the package uses an inline Form B descriptor at -`pkgs/c/compat.asio.lua`: - -- namespace: `compat`; -- full package name: `compat.asio`; -- published version: bare version `1.38.1`; -- platforms: Linux and macOS use the tag tarball; Windows uses the repackaged - symlink-free tarball to avoid the POSIX symlink extraction failure; -- include root: `*/include`; -- build target: a generated C anchor provides the buildable library target - required by the current package resolver; -- Linux link interface: `-pthread`; -- `import_std = false` because this package is consumed through textual headers. - -The intended post-publication CLI token is `compat:asio@1.38.1`, which maps to -the consumer declaration `[dependencies.compat] asio = "1.38.1"`. Before the -replacement PR is opened, that token must be exercised with the current mcpp -CLI in an isolated project rather than inferred only from the descriptor name. - -The default `standalone` feature contributes these public preprocessor defines: - -- `ASIO_STANDALONE`; -- `ASIO_HEADER_ONLY`; -- `ASIO_DISABLE_BOOST_CONTEXT_FIBER`; -- `ASIO_HAS_THREADS` — asio's own thread detection keys off CRT macros - (`_MT`/`_REENTRANT`/`_POSIX_THREADS`) that the workspace's llvm-on-Windows - toolchain does not define. Without the pin asio silently selects - `null_thread` and every internal-thread operation (notably the - waitable-timer wait thread behind `steady_timer`) throws - `operation_not_supported` (10045) at runtime — observed as the core, - coroutine, and network consumer tests failing on the Windows runner while - the thread-free tests passed. asio only ever tests - `defined(ASIO_HAS_THREADS)`, and the POSIX pthread selection still runs - beneath it, so the pin is a no-op on platforms where detection already - works (re-verified by the Linux consumer suite). - -mcpp 0.0.94 accepts feature `defines` in the current xpkg parser and propagates -them to consumers. The Asio surface test rejects builds where any of these -defines is absent, and generated compile commands are inspected during local -verification to confirm that the flags reach every consumer translation unit. - -The descriptor uses grammar already accepted by the live index contract. This -contribution does not change `index.toml` (`min_mcpp = "0.0.87"`) or the active -workflow pin (`MCPP_VERSION = "0.0.94"`). - -## 4. URL and mirror decision - -Linux/macOS keep the canonical upstream GitHub tarball as GLOBAL; a -byte-identical copy of that tarball is uploaded to -`gitcode.com/mcpp-res/asio` as the CN mirror (same SHA-256, verified after -upload). - -Windows cannot use either upstream tag archive encoding (both carry the POSIX -symlinks), so its GLOBAL asset is the repackaged symlink-free tarball hosted -in the ecosystem's resource org `github.com/xlings-res/asio`, with a -byte-identical CN copy on `gitcode.com/mcpp-res/asio`. Both hosts were -sha256-verified after upload against the descriptor's pinned digest. - -## 5. Consumer and test design - -The consumer project is `tests/examples/asio`, registered in the root workspace -and resolved through the local `compat` index. The current repository workflow -uses `mcpp test --workspace`, so the example follows the active `tests/*.cpp` -layout instead of the historical `src/main.cpp` runner layout. - -Six executable tests provide failure-capable assertions: - -- `core`: timers, executor work, dispatch, defer, and post behavior; -- `coroutine`: `co_spawn`, `use_awaitable`, and completion behavior; -- `experimental`: experimental channel send/receive behavior; -- `network`: loopback TCP accept/connect/read/write behavior; -- `platform`: platform-specific public types guarded by target macros; -- `surface`: representative public headers, public types, and required package - defines. - -The tests do not include or exercise the separate native module adapter. - -## 6. Validation contract - -The active workflow pins mcpp 0.0.94. Before opening the replacement PR, the -branch must provide fresh evidence for all locally available checks: - -1. run the descriptor syntax and mirror lint with the available local Lua 5.5; -2. parse `pkgs/c/compat.asio.lua` with mcpp 0.0.94; -3. run the targeted Asio consumer tests from isolated build state with - `MCPP_INDEX_MIRROR=GLOBAL`; -4. inspect the generated compile commands for all three public defines; -5. exercise `mcpp add compat:asio@1.38.1` in an isolated consumer project; -6. run `git diff --check` and confirm README is identical to `origin/main`. - -The replacement PR must then pass every check instantiated by the live -workflow, including the Linux, macOS, and Windows workspace matrix. Local macOS -success is not evidence for the other declared platforms. - -## 7. Documentation and change boundary - -README remains byte-identical to `origin/main`. This package contribution does -not update historical contribution instructions, even where they describe old -CI job names or old feature limitations. Any correction to those documents -requires a separate, evidence-backed audit and a separately scoped change. - -The replacement PR is limited to: - -- this design record; -- `pkgs/c/compat.asio.lua`; -- the root workspace registration; -- `tests/examples/asio` consumer configuration and tests. - -## 8. Acceptance criteria - -- upstream version, license, layout, and repeated archive digest are recorded; -- local descriptor lint passes with Lua 5.5, and the workflow's Lua 5.4 lint - passes in GitHub Actions; -- the CLI dependency token is verified through an isolated `mcpp add`; -- the six targeted consumer tests pass from isolated build state; -- the Windows workspace job downloads the ZIP and completes the Asio tests; -- README has no diff; -- the replacement PR contains no native module adaptation; -- all required GitHub Actions jobs pass before maintainer merge; -- publication remains the repository's automatic post-merge responsibility. diff --git a/mcpp.toml b/mcpp.toml index 0ed6250..6ca8a67 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -9,7 +9,6 @@ [workspace] members = [ "tests/examples/archive", - "tests/examples/asio", "tests/examples/asio-module", "tests/examples/build-mcpp", "tests/examples/cjson", diff --git a/pkgs/c/compat.asio.lua b/pkgs/c/compat.asio.lua deleted file mode 100644 index 1f0bc63..0000000 --- a/pkgs/c/compat.asio.lua +++ /dev/null @@ -1,95 +0,0 @@ --- compat.asio — standalone Asio 1.38.1, exposed in upstream's default --- header-only mode. The package intentionally does not provide optional --- OpenSSL/wolfSSL, Boost.Context/Regex/Date_Time, or liburing dependencies. -package = { - spec = "1", - namespace = "compat", - name = "compat.asio", - description = "Standalone asynchronous I/O and networking library (header-only)", - licenses = {"BSL-1.0"}, - repo = "https://github.com/chriskohlhoff/asio", - type = "package", - - xpm = { - linux = { - ["1.38.1"] = { - url = { - GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", - }, - sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", - }, - }, - macosx = { - ["1.38.1"] = { - url = { - GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", - }, - sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", - }, - }, - windows = { - ["1.38.1"] = { - -- Upstream's tag archives (tar.gz AND zip) both carry two POSIX - -- symlinks (asio/include -> ../include, asio/src -> ../src) that - -- tar.exe cannot materialize on the Windows runner, and upstream - -- publishes no symlink-free asset for 1.38.x. This asset is the - -- upstream tag tarball with only those two symlink entries - -- removed (tar --delete); all 1544 regular files are - -- byte-identical to upstream. Provenance: xlings-res/asio README. - url = { - GLOBAL = "https://github.com/xlings-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", - }, - sha256 = "77f74094bb12cd867a6edbf5736bbed816c6ce0906e880de8573097a81714d89", - }, - }, - }, - - mcpp = { - language = "c++23", - import_std = false, - c_standard = "c11", - -- GitHub wraps the tag as asio-asio-1-38-1/; expose its public include root. - include_dirs = { "*/include" }, - -- Header-only packages still need a buildable target in mcpp. - generated_files = { - ["mcpp_generated/asio_anchor.c"] = [==[ -int mcpp_compat_asio_headers_anchor(void) { return 0; } -]==], - }, - sources = { "mcpp_generated/asio_anchor.c" }, - targets = { ["asio"] = { kind = "lib" } }, - -- Explicitly pin the package's public configuration. `standalone` is a - -- default feature so its defines propagate to every consumer TU. - -- - -- ASIO_HAS_THREADS: asio's own thread detection keys off CRT macros - -- (_MT/_REENTRANT/_POSIX_THREADS) that the workspace's llvm-on-Windows - -- toolchain does not define, so asio silently selects null_thread and - -- every internal-thread operation (e.g. the waitable-timer wait thread) - -- throws operation_not_supported (10045) at runtime. All supported - -- targets are multithreaded; pin the detection result. asio only ever - -- tests defined(ASIO_HAS_THREADS), and on POSIX the pthread selection - -- below it still runs, so this is a no-op where detection already works. - features = { - ["default"] = { implies = { "standalone" } }, - ["standalone"] = { - defines = { - "ASIO_STANDALONE", - "ASIO_HEADER_ONLY", - "ASIO_DISABLE_BOOST_CONTEXT_FIBER", - "ASIO_HAS_THREADS", - }, - }, - }, - deps = {}, - -- POSIX threading is detected by Asio from unistd.h feature macros; - -- retain the portable driver-level thread link contract on Linux. - linux = { - ldflags = { "-pthread" }, - }, - -- On the supported desktop MSVC-ABI route, Asio autolinks ws2_32.lib - -- and mswsock.lib. Do not inject GNU -l flags into native link.exe. - }, -} diff --git a/tests/examples/asio/mcpp.toml b/tests/examples/asio/mcpp.toml deleted file mode 100644 index ba10afc..0000000 --- a/tests/examples/asio/mcpp.toml +++ /dev/null @@ -1,10 +0,0 @@ -# Asio consumer test project: standalone, header-only, cross-platform behavior. -[package] -name = "asio-tests" -version = "0.1.0" - -[indices] -compat = { path = "../../.." } - -[dependencies.compat] -asio = "1.38.1" diff --git a/tests/examples/asio/tests/core.cpp b/tests/examples/asio/tests/core.cpp deleted file mode 100644 index 21f11fd..0000000 --- a/tests/examples/asio/tests/core.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include - -#include -#include -#include -#include - -#if !defined(_WIN32) -#ifndef ASIO_HAS_THREADS -#error "Asio must detect POSIX thread support" -#endif -#ifndef ASIO_HAS_PTHREADS -#error "Asio must select its pthread implementation on POSIX" -#endif -#endif - -int main() { - using namespace std::chrono_literals; - - asio::io_context io; - auto guard = asio::make_work_guard(io); - auto serial = asio::make_strand(io); - asio::steady_timer timer(io, 2ms); - - std::atomic posted{0}; - std::mutex order_mutex; - std::vector order; - bool timer_called = false; - - asio::post(serial, [&] { - std::lock_guard lock(order_mutex); - order.push_back(1); - ++posted; - }); - asio::post(serial, [&] { - std::lock_guard lock(order_mutex); - order.push_back(2); - ++posted; - }); - timer.async_wait([&](const asio::error_code& ec) { - timer_called = !ec; - guard.reset(); - }); - - asio::thread worker([&] { io.run(); }); - worker.join(); - - if (posted != 2 || !timer_called || order != std::vector{1, 2}) return 1; - - asio::thread_pool pool(2); - std::atomic pooled{0}; - asio::post(pool, [&] { ++pooled; }); - asio::post(pool, [&] { ++pooled; }); - pool.join(); - if (pooled != 2) return 2; - - asio::io_context cancel_io; - asio::steady_timer cancelled(cancel_io, 1h); - asio::cancellation_signal cancellation; - asio::error_code cancelled_ec; - bool cancelled_called = false; - cancelled.async_wait(asio::bind_cancellation_slot( - cancellation.slot(), - [&](const asio::error_code& ec) { - cancelled_ec = ec; - cancelled_called = true; - })); - cancellation.emit(asio::cancellation_type::all); - cancel_io.run(); - - return cancelled_called && cancelled_ec == asio::error::operation_aborted ? 0 : 3; -} diff --git a/tests/examples/asio/tests/coroutine.cpp b/tests/examples/asio/tests/coroutine.cpp deleted file mode 100644 index eb39ad4..0000000 --- a/tests/examples/asio/tests/coroutine.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include - -#ifndef ASIO_HAS_CO_AWAIT -#error "C++23 compat.asio consumers must have co_await support" -#endif -#ifndef ASIO_HAS_STD_COROUTINE -#error "C++23 compat.asio consumers must use the standard coroutine library" -#endif - -asio::awaitable timer_value() { - asio::steady_timer timer(co_await asio::this_coro::executor); - timer.expires_after(std::chrono::milliseconds(1)); - co_await timer.async_wait(asio::use_awaitable); - co_return 42; -} - -int main() { - asio::io_context io; - int result = 0; - bool completed = false; - - asio::co_spawn(io, timer_value(), - [&](std::exception_ptr error, int value) { - if (!error) { - result = value; - completed = true; - } - }); - - io.run(); - return completed && result == 42 ? 0 : 1; -} diff --git a/tests/examples/asio/tests/experimental.cpp b/tests/examples/asio/tests/experimental.cpp deleted file mode 100644 index 816f857..0000000 --- a/tests/examples/asio/tests/experimental.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -int main() { - asio::io_context io; - - asio::experimental::channel channel(io, 1); - if (!channel.try_send(asio::error_code{}, "channel")) return 1; - std::string channel_value; - asio::error_code channel_error; - channel.async_receive([&](asio::error_code ec, std::string value) { - channel_error = ec; - channel_value = std::move(value); - }); - - asio::experimental::concurrent_channel concurrent(io, 1); - if (!concurrent.try_send(asio::error_code{}, 42)) return 2; - int concurrent_value = 0; - asio::error_code concurrent_error; - concurrent.async_receive([&](asio::error_code ec, int value) { - concurrent_error = ec; - concurrent_value = value; - }); - - auto promised = asio::post(io, asio::experimental::use_promise); - bool promise_completed = false; - promised([&] { promise_completed = true; }); - - io.run(); - - return !channel_error && channel_value == "channel" - && !concurrent_error && concurrent_value == 42 - && promise_completed ? 0 : 3; -} diff --git a/tests/examples/asio/tests/network.cpp b/tests/examples/asio/tests/network.cpp deleted file mode 100644 index 2494945..0000000 --- a/tests/examples/asio/tests/network.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include - -#include -#include -#include - -int main() { - using asio::ip::tcp; - using asio::ip::udp; - using namespace std::chrono_literals; - - asio::io_context io; - tcp::acceptor acceptor(io, {asio::ip::address_v4::loopback(), 0}); - tcp::socket server(io); - tcp::socket client(io); - asio::steady_timer deadline(io, 5s); - - const std::string ping = "ping"; - const std::string pong = "pong"; - std::array server_data{}; - std::array client_data{}; - bool accepted = false; - bool connected = false; - bool tcp_done = false; - bool timed_out = false; - int failure = 0; - - auto fail = [&](int code) { - if (failure == 0) failure = code; - asio::error_code ignored; - acceptor.close(ignored); - server.close(ignored); - client.close(ignored); - deadline.cancel(); - }; - - deadline.async_wait([&](const asio::error_code& ec) { - if (!ec) { - timed_out = true; - fail(90); - } - }); - - acceptor.async_accept(server, [&](const asio::error_code& ec) { - if (ec) return fail(1); - accepted = true; - asio::async_read(server, asio::buffer(server_data), - [&](const asio::error_code& read_ec, std::size_t n) { - if (read_ec || n != ping.size() - || std::string(server_data.data(), n) != ping) return fail(2); - asio::async_write(server, asio::buffer(pong), - [&](const asio::error_code& write_ec, std::size_t written) { - if (write_ec || written != pong.size()) fail(3); - }); - }); - }); - - client.async_connect( - {asio::ip::address_v4::loopback(), acceptor.local_endpoint().port()}, - [&](const asio::error_code& ec) { - if (ec) return fail(4); - connected = true; - asio::async_write(client, asio::buffer(ping), - [&](const asio::error_code& write_ec, std::size_t written) { - if (write_ec || written != ping.size()) return fail(5); - asio::async_read(client, asio::buffer(client_data), - [&](const asio::error_code& read_ec, std::size_t n) { - if (read_ec || n != pong.size() - || std::string(client_data.data(), n) != pong) return fail(6); - tcp_done = true; - deadline.cancel(); - }); - }); - }); - - io.run(); - if (failure || timed_out || !accepted || !connected || !tcp_done) return failure ? failure : 7; - - asio::io_context udp_io; - udp::socket receiver(udp_io, {asio::ip::address_v4::loopback(), 0}); - udp::socket sender(udp_io, {asio::ip::address_v4::loopback(), 0}); - const std::string datagram = "asio-udp"; - std::array received{}; - udp::endpoint remote; - bool receive_done = false; - bool send_done = false; - asio::error_code udp_failure; - - receiver.async_receive_from(asio::buffer(received), remote, - [&](const asio::error_code& ec, std::size_t n) { - udp_failure = ec; - receive_done = !ec && n == datagram.size() - && std::string(received.data(), n) == datagram; - }); - sender.async_send_to(asio::buffer(datagram), receiver.local_endpoint(), - [&](const asio::error_code& ec, std::size_t n) { - if (ec) udp_failure = ec; - send_done = !ec && n == datagram.size(); - }); - - udp_io.run(); - return !udp_failure && receive_done && send_done ? 0 : 8; -} diff --git a/tests/examples/asio/tests/platform.cpp b/tests/examples/asio/tests/platform.cpp deleted file mode 100644 index eadbcd9..0000000 --- a/tests/examples/asio/tests/platform.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include -#include - -int main() { -#if defined(ASIO_HAS_PIPE) - asio::io_context io; - asio::readable_pipe reader(io); - asio::writable_pipe writer(io); - asio::error_code ec; - asio::connect_pipe(reader, writer, ec); - if (ec) return 1; - - const std::string sent = "pipe"; - std::array received{}; - if (asio::write(writer, asio::buffer(sent), ec) != sent.size() || ec) return 2; - if (asio::read(reader, asio::buffer(received), ec) != sent.size() || ec) return 3; - if (std::string(received.data(), received.size()) != sent) return 4; -#endif - -#if defined(ASIO_HAS_LOCAL_SOCKETS) - static_assert(sizeof(asio::local::stream_protocol::endpoint) > 0); -#endif -#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - static_assert(sizeof(asio::posix::stream_descriptor::native_handle_type) > 0); -#endif -#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) - static_assert(sizeof(asio::windows::stream_handle::native_handle_type) > 0); -#endif -#if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) - static_assert(sizeof(asio::windows::object_handle::native_handle_type) > 0); -#endif -#if defined(ASIO_HAS_FILE) - static_assert(sizeof(asio::random_access_file::native_handle_type) > 0); -#endif -#if defined(ASIO_HAS_SERIAL_PORT) - static_assert(sizeof(asio::serial_port::native_handle_type) > 0); -#endif - - return 0; -} diff --git a/tests/examples/asio/tests/surface.cpp b/tests/examples/asio/tests/surface.cpp deleted file mode 100644 index ca8e927..0000000 --- a/tests/examples/asio/tests/surface.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef ASIO_STANDALONE -#error "compat.asio must expose standalone Asio to consumers" -#endif -#ifndef ASIO_HEADER_ONLY -#error "compat.asio must expose Asio's header-only configuration" -#endif -#ifndef ASIO_DISABLE_BOOST_CONTEXT_FIBER -#error "compat.asio must make the excluded Boost.Context spawn path explicit" -#endif -#ifdef ASIO_ENABLE_BOOST -#error "compat.asio must not enable Boost.Asio mode" -#endif -#ifdef ASIO_HAS_BOOST_CONFIG -#error "standalone Asio must not depend on Boost.Config" -#endif -#ifdef ASIO_HAS_BOOST_REGEX -#error "standalone Asio must not expose Boost.Regex overloads" -#endif -#ifdef ASIO_HAS_BOOST_DATE_TIME -#error "standalone Asio must not expose legacy Boost.Date_Time timers" -#endif -#ifdef ASIO_HAS_IO_URING -#error "compat.asio base package must not require liburing" -#endif - -#include - -int main() { - static_assert(std::is_class_v); - static_assert(std::is_class_v); - static_assert(std::is_class_v); - static_assert(std::is_class_v); - static_assert(std::is_class_v); - static_assert(std::is_class_v); - static_assert(std::is_class_v>); - static_assert(std::is_class_v>); - -#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_LOCAL_SOCKETS) - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_PIPE) - static_assert(std::is_class_v); - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_SERIAL_PORT) - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) - static_assert(std::is_class_v); -#endif -#if defined(ASIO_HAS_FILE) - static_assert(std::is_class_v); -#endif - - return 0; -} From 070de7465269bb879aa65a3db8fe218efc57b429 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Mon, 20 Jul 2026 23:03:54 +0800 Subject: [PATCH 06/11] refactor(asio): make module package canonical --- pkgs/a/asio.lua | 257 +++++++++++ pkgs/c/chriskohlhoff.asio.lua | 419 ------------------ tests/examples/asio-module/mcpp.toml | 10 +- .../asio-module/tests/experimental.cpp | 1 - tests/examples/asio-module/tests/network.cpp | 2 +- 5 files changed, 262 insertions(+), 427 deletions(-) create mode 100644 pkgs/a/asio.lua delete mode 100644 pkgs/c/chriskohlhoff.asio.lua diff --git a/pkgs/a/asio.lua b/pkgs/a/asio.lua new file mode 100644 index 0000000..b065195 --- /dev/null +++ b/pkgs/a/asio.lua @@ -0,0 +1,257 @@ +-- asio -- standalone Asio 1.38.1 exposed as the C++23 module `asio` +-- (Form B inline descriptor, separate-compilation mode). +-- +-- Install and consume: +-- mcpp add asio@1.38.1 +-- import std; +-- import asio; +-- +-- The upstream 1.38.x release has no module interface unit. This descriptor +-- generates a reviewed `asio.cppm` wrapper and compiles upstream `src/asio.cpp` +-- with ASIO_SEPARATE_COMPILATION. `import std;` is required because this package +-- does not inject the standard library through the module boundary. +-- +-- This package is module-only. Textual `#include ` consumption and +-- APIs not exported by the wrapper are outside its mcpp-index contract. The +-- wrapper intentionally excludes SSL/TLS, local/POSIX/Windows handle APIs, +-- serial ports, pipes, file I/O, stackful spawn, and other surfaces listed by +-- headers that it does not include. +-- +-- ASIO_STANDALONE and ASIO_SEPARATE_COMPILATION are public build defines, but +-- preprocessor macros do not cross `import asio;`. Consumers should use C++ or +-- operating-system facilities instead of testing ASIO_HAS_* macros. +package = { + spec = "1", + namespace = "", + name = "asio", + description = "Standalone asio exposed as the C++23 module `asio` (separate compilation)", + licenses = {"BSL-1.0"}, + repo = "https://github.com/chriskohlhoff/asio", + type = "package", + + xpm = { + linux = { + ["1.38.1"] = { + url = { + GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", + CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", + }, + sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", + }, + }, + macosx = { + ["1.38.1"] = { + url = { + GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", + CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", + }, + sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", + }, + }, + windows = { + -- Upstream tag archives carry two POSIX symlinks + -- (asio/include -> ../include, asio/src -> ../src) that tar.exe + -- cannot materialize on the Windows runner. This uses the existing + -- symlink-free repack documented by xlings-res/asio. + ["1.38.1"] = { + url = { + GLOBAL = "https://github.com/xlings-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", + CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", + }, + sha256 = "77f74094bb12cd867a6edbf5736bbed816c6ce0906e880de8573097a81714d89", + }, + }, + }, + + mcpp = { + schema = "0.1", + language = "c++23", + import_std = false, + modules = { "asio" }, + -- GitHub wraps the tag as asio-asio-1-38-1/; expose its include root + -- so the wrapper's `#include ` resolve. + include_dirs = { "*/include" }, + generated_files = { + ["mcpp_generated/asio.cppm"] = [==[ +module; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +export module asio; + +export namespace asio::detail { +using ::std::chrono::operator==; +using ::std::chrono::operator<; +using ::std::chrono::operator>=; +using ::std::chrono::operator+; +using ::std::chrono::operator-; +using ::std::coroutine_traits; +} + +export namespace asio::error { +using ::asio::error::make_error_code; +using ::asio::error::operation_aborted; +} + +export namespace asio { +using ::asio::io_context; +using ::asio::post; +using ::asio::make_work_guard; +using ::asio::dispatch; +using ::asio::defer; +using ::asio::steady_timer; +using ::asio::thread_pool; +using ::asio::make_strand; +using ::asio::mutable_buffer; +using ::asio::const_buffer; +using ::asio::buffer; +using ::asio::awaitable; +using ::asio::use_awaitable; +using ::asio::co_spawn; +using ::asio::cancellation_signal; +using ::asio::cancellation_type; +using ::asio::bind_cancellation_slot; +using ::asio::execution_context; +using ::asio::any_io_executor; +using ::asio::system_executor; +using ::asio::system_context; +using ::asio::associated_executor; +using ::asio::associated_allocator; +using ::asio::associated_cancellation_slot; +using ::asio::error_code; +using ::asio::detached; +using ::asio::detached_t; +using ::asio::use_future; +using ::asio::deferred; +using ::asio::deferred_t; +using ::asio::redirect_error; +using ::asio::bind_executor; +using ::asio::signal_set; +using ::asio::system_timer; +using ::asio::bind_allocator; +using ::asio::append; +using ::asio::prepend; +using ::asio::consign; +using ::asio::as_tuple; +using ::asio::socket_base; +using ::asio::connect; +using ::asio::async_read; +using ::asio::async_write; +using ::asio::read; +using ::asio::write; +using ::asio::read_until; +} + +export namespace asio::experimental { +using ::asio::experimental::channel; +using ::asio::experimental::concurrent_channel; +using ::asio::experimental::use_promise; +} + +export namespace asio::experimental::error { +using ::asio::experimental::error::make_error_code; +} + +export namespace asio::ip { +using ::asio::ip::tcp; +using ::asio::ip::udp; +using ::asio::ip::address; +using ::asio::ip::address_v4; +using ::asio::ip::address_v6; +} + +export namespace asio::this_coro { +using ::asio::this_coro::executor; +using ::asio::this_coro::cancellation_state; +using ::asio::this_coro::throw_if_cancelled; +using ::asio::this_coro::reset_cancellation_state; +} + +]==], + }, + sources = { + "mcpp_generated/asio.cppm", + "*/src/asio.cpp", + }, + targets = { ["asio"] = { kind = "lib" } }, + -- `separate-compilation` is a default feature so its defines propagate + -- to every consumer TU (the module BMI and the consumer must agree on + -- ASIO_SEPARATE_COMPILATION or the inline/extern split miscompiles). + -- + -- ASIO_HAS_THREADS: asio's detection keys off CRT macros + -- (_MT/_REENTRANT/_POSIX_THREADS) that the workspace's llvm-on-Windows + -- toolchain does not define, otherwise silently selecting null_thread. + -- Pin the known multithreaded package contract; POSIX pthread selection + -- still runs beneath this define where applicable. + features = { + ["default"] = { implies = { "separate-compilation" } }, + ["separate-compilation"] = { + defines = { + "ASIO_STANDALONE", + "ASIO_SEPARATE_COMPILATION", + "ASIO_DISABLE_BOOST_CONTEXT_FIBER", + "ASIO_HAS_THREADS", + }, + }, + }, + deps = {}, + -- POSIX threading is detected by asio from unistd.h feature macros; + -- retain the portable driver-level thread link contract on Linux. + linux = { + ldflags = { "-pthread" }, + }, + -- On the supported desktop MSVC-ABI route, asio autolinks ws2_32.lib + -- and mswsock.lib. Do not inject GNU -l flags into native link.exe. + }, +} diff --git a/pkgs/c/chriskohlhoff.asio.lua b/pkgs/c/chriskohlhoff.asio.lua deleted file mode 100644 index ad183a8..0000000 --- a/pkgs/c/chriskohlhoff.asio.lua +++ /dev/null @@ -1,419 +0,0 @@ --- chriskohlhoff.asio -- Asio 1.38.1 暴露为 C++23 模块 `asio` (Form B inline) --- --- 消费者引入: --- mcpp add chriskohlhoff.asio@1.38.1 --- --- 注意: 不要使用简写 mcpp add asio@1.38.1。 --- 简写 "asio" 已在默认注册表中匹配多个包 (compat.asio, mcpplibs.asio 等), --- 会导致解析冲突或解析到错误的包。 --- --- 本包是 compat.asio (header-only: #include ) 的模块伴侣包。 --- 采用 ASIO_SEPARATE_COMPILATION 模式 (编译 */src/asio.cpp), --- 上层叠加生成的模块接口单元 (.cppm wrapper), 使用者只需: --- import std; import asio; --- --- 为何用 generated_files: upstream 1.38.x 未提供模块接口单元, --- wrapper 在 mcpp-index 内手工编写, 先以 docs/asio.lua 本地验证。 --- --- ========== 基本用法 ========== --- import std; -- 必须, 模块版不会自动拉入标准库 --- import asio; --- --- using namespace std::chrono_literals; --- asio::io_context io; --- auto strand = asio::make_strand(io); --- asio::steady_timer timer(io, 100ms); --- asio::co_spawn(io, my_coro(), asio::detached); --- --- ========== 必须写 import std; ========== --- 与 header-only 的 compat.asio 不同, 本模块不会隐式拉入任何标准库头文件。 --- 要使用 std::vector, std::error_code, std::thread, std::mutex, --- std::chrono 等, 必须写 `import std;`。省略则标准库不可见。 --- --- ========== 与 compat.asio(header-only) 的主要差异 ========== --- --- 1. 构建模型 (HEADER_ONLY -> SEPARATE_COMPILATION) --- compat.asio: ASIO_HEADER_ONLY -- asio 模板在每个消费者 TU 中实例化, --- 编译系统只需一个锚定 .c 文件。 --- chriskohlhoff.asio: ASIO_SEPARATE_COMPILATION -- 每次构建只编译一次 --- */src/asio.cpp; BMI (模块) 缓存模板实例化。 --- 首次构建较慢 (编译 asio 实现), 增量构建更快 --- (消费者 TU 变更时无需重解析 asio 头文件)。 --- --- 2. 宏 (宏定义) 不可见 --- `import asio;` 后, 模块边界隔离了预处理状态。使用者不能写: --- #ifdef ASIO_HAS_THREADS -- 不可见 --- #ifndef ASIO_HEADER_ONLY -- 不可见 --- #ifdef ASIO_HAS_PTHREADS -- 不可见 --- #ifdef ASIO_HAS_PIPE -- 不可见 --- #ifdef ASIO_HAS_FILE -- 不可见 --- #ifdef ASIO_HAS_SERIAL_PORT -- 不可见 --- #ifdef ASIO_HAS_BOOST_* -- 不可见 --- 只有 ASIO_STANDALONE 和 ASIO_SEPARATE_COMPILATION 通过 feature defines --- 暴露 (见下方 "features" 块)。需要平台检测时, 请使用 C++ 标准宏或 --- 操作系统级宏 (#ifdef __linux__ 等)。 --- --- 3. error_code 类型一致性 --- asio::error_code = std::error_code。模块导出了类型别名, 两者可互换。 --- 定时器回调签名 (const std::error_code&) 和 asio::error::* 枚举值 --- 均正常工作。 --- --- 4. 完成令牌 (Completion Token) 的模板类型 --- 模块使用者可以写 asio::detached / asio::detached_t / asio::deferred / --- asio::deferred_t 作为类型。但 asio::use_future_t 是类模板, --- 未导出。请直接使用 asio::use_future 变量, 无需命名其类型。 --- --- 5. 禁止混合 #include 和 import --- 不要在同一个 TU 中混用 #include 和 import asio; -- --- 头文件的 inline 实例化与模块 BMI 之间可能存在 ODR 差异。选一种。 --- 需要 #include 方式时, 请依赖 compat.asio。同理, 不要在同一 TU 中 --- 混合 #include 和 import std;。 --- --- 6. import_std = false --- mcpp schema "0.1" 要求自身提供模块接口的包必须设置 import_std = false --- (由使用者显式写 `import std; import asio;`)。chriskohlhoff.asio 不会 --- 在包级别自动引入 import std;。 --- --- ========== 本模块不可用的 API 组件 ========== --- --- 以下组件在 compat.asio (header-only) 中可用, 但本模块未导出: --- --- 组件 头文件 / 路径 原因 / 替代方案 --- ------------------------+----------------------------+---------------------- --- SSL/TLS asio/ssl/*.hpp 需 OpenSSL/wolfSSL --- (ssl::context, (外部依赖), 本包不包含 --- ssl::stream, --- ssl::host_name_verify) --- Unix 域套接字 asio/local/*.hpp 未导出。改用 TCP loopback, --- (local::stream_protocol, 或在你的代码中 #include --- local::datagram_proto) --- POSIX 流描述符 asio/posix/*.hpp 未导出。 --- (posix::stream_descriptor, --- posix::descriptor_base) --- Windows 句柄 asio/windows/*.hpp Windows 专用, 未导出。 --- (stream_handle, object_handle, --- overlapped_ptr) --- 串口 asio/serial_port.hpp 平台相关 --- (ASIO_HAS_SERIAL_PORT)。 --- 未导出。 --- Pipe (管道) asio/*able_pipe.hpp 需 ASIO_HAS_PIPE。 --- (readable_pipe, writable_pipe) 未导出。 --- 文件 I/O asio/stream_file.hpp 需 ASIO_HAS_FILE。 --- asio/random_access_file 未导出。 --- spawn() 有栈协程 asio/spawn.hpp 需 Boost.Context --- (spawn, yield_context) (ASIO_HAS_BOOST_CONTEXT --- _FIBER)。我们定义了 --- ASIO_DISABLE_BOOST_ --- CONTEXT_FIBER, 因此 --- spawn() 给出编译期 --- #error。 --- -> 改用 co_spawn + --- awaitable (C++20 --- 无栈协程) --- Boost.Date_Time 定时器 asio/deadline_timer.hpp 已废弃。改用 --- steady_timer / --- system_timer --- (使用 std::chrono) --- 通用套接字协议 asio/generic/*.hpp 较少使用, 未导出。 --- 执行器属性框架 asio/execution/*.hpp 高级执行器框架, 暂未导出。 --- 自定义点检测特质 asio/traits/*.hpp 检测特质, 最终用户 --- 价值较低, 未导出。 --- 遗留宏式协程 已过时。改用 awaitable。 --- --- asio::streambuf asio/streambuf.hpp 改用 mutable_buffer + --- asio::buffer()。 --- --- ========== Boost 淘汰说明 ========== --- --- 独立版 asio (定义了 ASIO_STANDALONE) 已从所有核心和网络 API 中移除 --- Boost 依赖: --- --- * Boost.DateTime -- 已完全移除。ASIO_STANDALONE 在 config.hpp 中设置 --- ASIO_DISABLE_BOOST_DATE_TIME, 导致 deadline_timer (依赖 --- boost::posix_time) 完全不可编译。所有现代 asio 定时器 --- (steady_timer, system_timer, high_resolution_timer) 直接使用 --- std::chrono。 --- --- * Boost.Context -- 已从核心库移除, 但 spawn() 仍需要。 --- spawn() / basic_yield_context API 使用 boost::context::fiber 实现 --- 有栈协程。由于我们定义了 ASIO_DISABLE_BOOST_CONTEXT_FIBER, --- 任何使用 spawn() 的代码都会产生编译期 #error。 --- -> 改用 C++20 无栈协程, 功能完全等价: --- // 之前 (Boost.Context 有栈): --- asio::spawn(io, [](asio::yield_context yield) { --- timer.async_wait(yield); --- }); --- // 之后 (C++20 无栈, 零 Boost): --- asio::co_spawn(io, coro(), asio::detached); --- asio::awaitable coro() { --- co_await timer.async_wait(asio::use_awaitable); --- } --- --- * Boost.Regex -- ASIO_STANDALONE 禁用了 ASIO_HAS_BOOST_REGEX。 --- * Boost.Config, Boost.Array, Boost.Bind, Boost.Limits, Boost.Chrono, --- Boost.ThrowException 等 -- 全部已禁用。 --- --- * 陷阱提示: ASIO_HAS_BOOST_CONTEXT_FIBER 会针对任意 C++11 兼容编译器 --- (clang/GCC/MSVC) 自动检测并设置自身, 即使你从未要求过 Boost。 --- 如果 Boost 头文件碰巧在 include path 中, spawn() 看起来能编译, --- 但会在链接时报错 (除非链接了 libboost_context)。 --- ASIO_DISABLE_BOOST_CONTEXT_FIBER 防护了这一点: 我们主动抑制自动检测, --- 使结果是明确的编译期错误, 而非运行时崩溃。 --- --- ========== 迁移指南 (header-only -> 模块) ========== --- --- 将项目从 compat.asio (#include ) 切换到 --- chriskohlhoff.asio (import asio;) 时, 请检查以下断点: --- --- [ ] 在每一个使用 asio 的 TU 顶部添加 import std; --- (标准库类型不再隐式可用) --- [ ] 删除所有 #include -- 替换为 import asio; --- [ ] 删除 #include (如果有) --- [ ] 检查 #ifdef ASIO_HAS_THREADS / ASIO_HAS_PIPE / 等 --- -> 替换为操作系统级宏或 if-constexpr 检测 --- [ ] 检查 asio::spawn() / yield_context 用法 --- -> 重写为 co_spawn + awaitable + use_awaitable --- [ ] 检查 deadline_timer -> 替换为 steady_timer --- [ ] 检查 asio::ssl::* -> 需要单独的 OpenSSL 集成包 --- [ ] 检查 asio::local::* / posix::* -> 如确实需要, 添加 #include --- (但同一 TU 中混用 #include 和 import 有风险; 要么对这类文件 --- 继续使用 compat.asio, 要么在 .cppm 文件的模块前导区 --- 仅添加全局性 #include) --- [ ] 构建时间: 首次构建较慢 (编译 asio.cpp), 增量构建更快 --- (BMI 缓存)。总体上更大的目标文件被跨 TU 更少的模板实例化抵消。 -package = { - spec = "1", - namespace = "chriskohlhoff", - name = "chriskohlhoff.asio", - description = "Standalone asio exposed as the C++23 module `asio` (separate compilation)", - licenses = {"BSL-1.0"}, - repo = "https://github.com/chriskohlhoff/asio", - type = "package", - - xpm = { - linux = { - ["1.38.1"] = { - url = { - GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", - }, - sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", - }, - }, - macosx = { - ["1.38.1"] = { - url = { - GLOBAL = "https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-38-1.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1.tar.gz", - }, - sha256 = "2827b229972be80cdb14e5497962fa393d1adf036b5869e2b9c99f644daadacc", - }, - }, - windows = { - -- Same symlink-free repack as compat.asio: upstream's tag archives - -- carry two POSIX symlinks (asio/include -> ../include, - -- asio/src -> ../src) that tar.exe cannot materialize on the - -- Windows runner. Provenance: xlings-res/asio README. - ["1.38.1"] = { - url = { - GLOBAL = "https://github.com/xlings-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", - CN = "https://gitcode.com/mcpp-res/asio/releases/download/1.38.1/asio-1.38.1-nosymlinks.tar.gz", - }, - sha256 = "77f74094bb12cd867a6edbf5736bbed816c6ce0906e880de8573097a81714d89", - }, - }, - }, - - mcpp = { - schema = "0.1", - language = "c++23", - import_std = false, - modules = { "asio" }, - -- GitHub wraps the tag as asio-asio-1-38-1/; expose its include root - -- so the wrapper's `#include ` resolve. - include_dirs = { "*/include" }, - generated_files = { - ["mcpp_generated/asio.cppm"] = [==[ -module; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -export module asio; - -export namespace asio::detail { -using ::std::chrono::operator==; -using ::std::chrono::operator<; -using ::std::chrono::operator>=; -using ::std::chrono::operator+; -using ::std::chrono::operator-; -using ::std::coroutine_traits; -} - -export namespace asio::error { -using ::asio::error::make_error_code; -using ::asio::error::operation_aborted; -} - -export namespace asio { -using ::asio::io_context; -using ::asio::post; -using ::asio::make_work_guard; -using ::asio::dispatch; -using ::asio::defer; -using ::asio::steady_timer; -using ::asio::thread_pool; -using ::asio::make_strand; -using ::asio::mutable_buffer; -using ::asio::const_buffer; -using ::asio::buffer; -using ::asio::awaitable; -using ::asio::use_awaitable; -using ::asio::co_spawn; -using ::asio::cancellation_signal; -using ::asio::cancellation_type; -using ::asio::bind_cancellation_slot; -using ::asio::execution_context; -using ::asio::any_io_executor; -using ::asio::system_executor; -using ::asio::system_context; -using ::asio::associated_executor; -using ::asio::associated_allocator; -using ::asio::associated_cancellation_slot; -using ::asio::error_code; -using ::asio::detached; -using ::asio::detached_t; -using ::asio::use_future; -using ::asio::deferred; -using ::asio::deferred_t; -using ::asio::redirect_error; -using ::asio::bind_executor; -using ::asio::signal_set; -using ::asio::system_timer; -using ::asio::bind_allocator; -using ::asio::append; -using ::asio::prepend; -using ::asio::consign; -using ::asio::as_tuple; -using ::asio::socket_base; -using ::asio::connect; -using ::asio::async_read; -using ::asio::async_write; -using ::asio::read; -using ::asio::write; -using ::asio::read_until; -} - -export namespace asio::experimental { -using ::asio::experimental::channel; -using ::asio::experimental::concurrent_channel; -using ::asio::experimental::use_promise; -} - -export namespace asio::experimental::error { -using ::asio::experimental::error::make_error_code; -} - -export namespace asio::ip { -using ::asio::ip::tcp; -using ::asio::ip::udp; -using ::asio::ip::address; -using ::asio::ip::address_v4; -using ::asio::ip::address_v6; -} - -export namespace asio::this_coro { -using ::asio::this_coro::executor; -using ::asio::this_coro::cancellation_state; -using ::asio::this_coro::throw_if_cancelled; -using ::asio::this_coro::reset_cancellation_state; -} - -]==], - }, - sources = { - "mcpp_generated/asio.cppm", - "*/src/asio.cpp", - }, - targets = { ["asio"] = { kind = "lib" } }, - -- `separate-compilation` is a default feature so its defines propagate - -- to every consumer TU (the module BMI and the consumer must agree on - -- ASIO_SEPARATE_COMPILATION or the inline/extern split miscompiles). - -- - -- ASIO_HAS_THREADS: same rationale as compat.asio -- asio's thread - -- detection keys off CRT macros (_MT/_REENTRANT/_POSIX_THREADS) the - -- workspace's llvm-on-Windows toolchain does not define, silently - -- selecting null_thread; pin the detection result. asio only ever - -- tests defined(ASIO_HAS_THREADS), and on POSIX the pthread selection - -- beneath it still runs, so this is a no-op where detection works. - features = { - ["default"] = { implies = { "separate-compilation" } }, - ["separate-compilation"] = { - defines = { - "ASIO_STANDALONE", - "ASIO_SEPARATE_COMPILATION", - "ASIO_DISABLE_BOOST_CONTEXT_FIBER", - "ASIO_HAS_THREADS", - }, - }, - }, - deps = {}, - -- POSIX threading is detected by asio from unistd.h feature macros; - -- retain the portable driver-level thread link contract on Linux. - linux = { - ldflags = { "-pthread" }, - }, - -- On the supported desktop MSVC-ABI route, asio autolinks ws2_32.lib - -- and mswsock.lib. Do not inject GNU -l flags into native link.exe. - }, -} diff --git a/tests/examples/asio-module/mcpp.toml b/tests/examples/asio-module/mcpp.toml index 75e359f..cc13ac3 100644 --- a/tests/examples/asio-module/mcpp.toml +++ b/tests/examples/asio-module/mcpp.toml @@ -1,13 +1,11 @@ -# Asio C++23-module consumer test project: `import asio;` (chriskohlhoff.asio, -# Form B inline descriptor, separate-compilation mode). Complements -# tests/examples/asio, which exercises the same upstream in header-only -# `#include ` form. +# Asio C++23-module consumer test project: `import std; import asio;`. +# The public package is the default-root module-only `asio@1.38.1` package. [package] name = "asio-module-tests" version = "0.1.0" [indices] -chriskohlhoff = { path = "../../.." } +default = { path = "../../.." } -[dependencies.chriskohlhoff] +[dependencies] asio = "1.38.1" diff --git a/tests/examples/asio-module/tests/experimental.cpp b/tests/examples/asio-module/tests/experimental.cpp index c7d66fd..aa1480b 100644 --- a/tests/examples/asio-module/tests/experimental.cpp +++ b/tests/examples/asio-module/tests/experimental.cpp @@ -1,5 +1,4 @@ // Experimental channel/concurrent_channel/use_promise over the module surface. -// Mirrors tests/examples/asio/tests/experimental.cpp. import std; import asio; diff --git a/tests/examples/asio-module/tests/network.cpp b/tests/examples/asio-module/tests/network.cpp index 381fd3a..c8d72f2 100644 --- a/tests/examples/asio-module/tests/network.cpp +++ b/tests/examples/asio-module/tests/network.cpp @@ -1,5 +1,5 @@ // TCP (acceptor/socket, async_read/async_write) and UDP (datagram send/receive) -// over the module surface. Mirrors tests/examples/asio/tests/network.cpp. +// over the imported module surface. import std; import asio; From db86ec57f75ceb0adc27977b62fd6a72e82b302f Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:21:52 +0800 Subject: [PATCH 07/11] docs: mark asio migration plan executed --- .../2026-07-20-retire-compat-asio-and-bare-module-plan.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md index e70cd48..b86e5ae 100644 --- a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md @@ -1,6 +1,12 @@ # Asio Module-Only Package Migration Implementation Plan -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. +> **Historical execution record — completed locally on 2026-07-20** +> +> This plan was executed locally on branch `refactor/asio-module`. The implementation commits are `6dc11f3` (PR #73 revert) and `cab87d6` (canonical root module migration). +> +> Do not rerun this plan against the completed branch. The commands and checklists below are retained as a historical execution record. +> +> Validation was narrowed by the user to Asio-only: isolated macOS arm64 with pinned mcpp 0.0.101 passed 5/5. Full workspace/OpenCV validation was intentionally stopped; Linux/Windows remain unverified. **Goal:** 删除 `compat.asio` header-only 包,将现有 Asio module recipe 改为唯一根包 `asio@1.38.1`,并通过 `mcpp add asio@1.38.1` 消费。 From 118049bccc8fbfe0a2529e91ef316595afbbf314 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:37:43 +0800 Subject: [PATCH 08/11] docs: refresh asio migration commit references --- .../docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md index b86e5ae..eeec534 100644 --- a/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md +++ b/.agents/docs/2026-07-20-retire-compat-asio-and-bare-module-plan.md @@ -2,7 +2,7 @@ > **Historical execution record — completed locally on 2026-07-20** > -> This plan was executed locally on branch `refactor/asio-module`. The implementation commits are `6dc11f3` (PR #73 revert) and `cab87d6` (canonical root module migration). +> This plan was executed locally on branch `refactor/asio-module`. After rebasing onto `upstream/main`, the implementation commits are `a65002d` (PR #73 revert) and `4ff03bd` (canonical root module migration). > > Do not rerun this plan against the completed branch. The commands and checklists below are retained as a historical execution record. > From 9de1f7589554eca68d293e8c6d1d46bbb00553a8 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:08:16 +0800 Subject: [PATCH 09/11] docs: design asio adaptation comment merge --- ...6-07-21-asio-adaptation-comments-design.md | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md diff --git a/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md b/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md new file mode 100644 index 0000000..c23fc5a --- /dev/null +++ b/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md @@ -0,0 +1,42 @@ +# Asio Adaptation Comments Design + +## Goal + +Restore the detailed adaptation notes from the retired +`chriskohlhoff.asio@1.38.1` descriptor in the canonical +`pkgs/a/asio.lua` descriptor, updated for the current package identity. + +## Scope + +Only the leading comment block before `package = {` changes. The package +identity, archives, hashes, mirrors, generated module wrapper, sources, +features, defines, platform flags, and tests remain unchanged. + +The merged comments will document: + +- installation with `mcpp add asio@1.38.1` and consumption with + `import std; import asio;`; +- why mcpp-index generates `asio.cppm` and compiles upstream `src/asio.cpp` + with `ASIO_SEPARATE_COMPILATION`; +- the explicit `import std;` contract, macro boundary, `error_code` identity, + completion-token limitations, and the rule against mixing header inclusion + with module import in one translation unit; +- API areas intentionally absent from the generated wrapper and their + alternatives; +- the standalone package's Boost exclusions and the `co_spawn` migration from + stackful `spawn`; +- a migration checklist from header-only Asio to the canonical module package. + +## Stale References + +The comments will not restore the retired `compat.asio` package as a usable +dependency or the old `chriskohlhoff.asio` package name. Historical comparisons +will use generic "header-only Asio" wording. The obsolete warning against bare +`mcpp add asio@1.38.1` will be replaced by the canonical install command. + +## Validation + +Run Lua syntax validation, the repository mirror-table check, strict parsing +with the workflow-pinned mcpp, `git diff --check`, and the targeted +`asio-module` consumer suite. No full workspace or OpenCV test is required for +this comment-only change. From b74cafe4716c24f1b52b3b3d1ee9c9f4a54d0880 Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:29:25 +0800 Subject: [PATCH 10/11] docs: plan asio adaptation comment merge --- .../2026-07-21-asio-adaptation-comments.md | 75 +++++++++++++++++++ ...6-07-21-asio-adaptation-comments-design.md | 42 +++-------- 2 files changed, 87 insertions(+), 30 deletions(-) create mode 100644 docs/superpowers/plans/2026-07-21-asio-adaptation-comments.md diff --git a/docs/superpowers/plans/2026-07-21-asio-adaptation-comments.md b/docs/superpowers/plans/2026-07-21-asio-adaptation-comments.md new file mode 100644 index 0000000..8ba1251 --- /dev/null +++ b/docs/superpowers/plans/2026-07-21-asio-adaptation-comments.md @@ -0,0 +1,75 @@ +# Asio Adaptation Comments Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add concise Asio module cautions, differences/limitations, and unexported-component notes without changing the descriptor table. + +**Architecture:** Replace only the leading comments in `pkgs/a/asio.lua`, compare the table from `package = {` byte-for-byte, and run only Asio validation. + +**Tech Stack:** Lua xpkg descriptor, C++23 modules, mcpp 0.0.101, Git. + +--- + +### Task 1: Replace The Leading Comment Block + +**Files:** +- Modify: `pkgs/a/asio.lua:1` + +- [ ] Save the current table beginning at `package = {` to `/tmp/asio-package-table.before`. +- [ ] Replace the leading comments with this exact block: + +```lua +-- asio -- 将独立版 Asio 1.38.1 暴露为 C++23 模块 `asio` +-- (Form B inline descriptor, separate-compilation mode)。 +-- +-- 注意事项 +-- * 使用 `mcpp add asio@1.38.1` 引入;消费者需显式写 +-- `import std; import asio;`,因为本包设置 import_std = false。 +-- * 本包只支持模块方式消费。同一 translation unit 不要混用 +-- `#include ` 和 `import asio;`,避免 inline 定义与模块 BMI +-- 的 separate-compilation 定义产生 ODR 差异。 +-- * 默认 feature 显式传播 ASIO_STANDALONE、ASIO_SEPARATE_COMPILATION、 +-- ASIO_DISABLE_BOOST_CONTEXT_FIBER 和 ASIO_HAS_THREADS。Asio 头文件内部 +-- 自动检测的其他 ASIO_HAS_* 宏不会由 `import asio;` 导出。 +-- +-- 与 header-only Asio 的区别/限制 +-- * 上游 1.38.x 没有模块接口单元。本描述生成 `asio.cppm`,并只编译一次 +-- `*/src/asio.cpp` 中的非模板实现;首次构建需生成 BMI,增量构建可避免 +-- 每个消费者 translation unit 重复解析整组 Asio 头文件。 +-- * 模块只暴露 wrapper 中明确 export 的声明,不等同于 +-- `#include ` 的完整 API 表面。 +-- * asio::error_code 是 std::error_code 的别名;wrapper 导出 +-- asio::use_future 变量,但未导出 asio::use_future_t 类模板。 +-- * 依赖未导出 ASIO_HAS_* 宏、平台专用头文件或 Boost 扩展的代码,需要 +-- 改用标准/操作系统能力检测或另行扩展模块 wrapper。 +-- +-- 未导出的组件 +-- * SSL/TLS (`asio/ssl/*.hpp`):需要 OpenSSL/wolfSSL 等外部依赖。 +-- * Unix 域套接字、POSIX 描述符和 Windows 句柄: +-- `asio/local/*.hpp`、`asio/posix/*.hpp`、`asio/windows/*.hpp`。 +-- * 串口、pipe 和文件 I/O:`asio/serial_port.hpp`、 +-- `asio/*able_pipe.hpp`、`asio/stream_file.hpp`、 +-- `asio/random_access_file.hpp`。 +-- * spawn()/yield_context 有栈协程:需要 Boost.Context;本包禁用其自动 +-- 检测,应改用 co_spawn + awaitable + use_awaitable。 +-- * deadline_timer、generic protocol、execution、traits、遗留宏式协程和 +-- streambuf:对应 `asio/deadline_timer.hpp`、`asio/generic/*.hpp`、 +-- `asio/execution/*.hpp`、`asio/traits/*.hpp`、`asio/yield.hpp`、 +-- `asio/coroutine.hpp`、`asio/streambuf.hpp`。 +``` + +- [ ] Compare the table after `package = {` with the saved baseline; expect no diff. +- [ ] Confirm the comment contains no `compat.asio`, `chriskohlhoff.asio`, or obsolete short-name warning. + +### Task 2: Validate And Commit + +**Files:** +- Validate: `pkgs/a/asio.lua` +- Test: `tests/examples/asio-module/**` + +- [ ] Run `lua -e "assert(loadfile('pkgs/a/asio.lua', 't'))"`. +- [ ] Run `lua tests/check_mirror_urls.lua pkgs/a/asio.lua`. +- [ ] Confirm `mcpp --version` reports `0.0.101` and run `mcpp xpkg parse pkgs/a/asio.lua`. +- [ ] Run `MCPP_HOME= MCPP_INDEX_MIRROR=GLOBAL mcpp test -p asio-module`; expect 5 passed and 0 failed. +- [ ] Run `git diff --check` and confirm only the leading `asio.lua` comments changed. +- [ ] Commit `pkgs/a/asio.lua` as `docs(asio): restore module adaptation notes`. diff --git a/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md b/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md index c23fc5a..2a39f12 100644 --- a/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md +++ b/docs/superpowers/specs/2026-07-21-asio-adaptation-comments-design.md @@ -2,41 +2,23 @@ ## Goal -Restore the detailed adaptation notes from the retired -`chriskohlhoff.asio@1.38.1` descriptor in the canonical -`pkgs/a/asio.lua` descriptor, updated for the current package identity. +Merge the useful notes from the retired `chriskohlhoff.asio@1.38.1` +descriptor into canonical `pkgs/a/asio.lua` without changing package behavior. ## Scope -Only the leading comment block before `package = {` changes. The package -identity, archives, hashes, mirrors, generated module wrapper, sources, -features, defines, platform flags, and tests remain unchanged. +Replace only the comment block before `package = {`. Keep three concise +sections: -The merged comments will document: +- usage cautions for `mcpp add`, `import std`, module-only consumption, and + propagated build defines; +- differences and limitations compared with header-only Asio; +- API component groups not exported by the generated wrapper. -- installation with `mcpp add asio@1.38.1` and consumption with - `import std; import asio;`; -- why mcpp-index generates `asio.cppm` and compiles upstream `src/asio.cpp` - with `ASIO_SEPARATE_COMPILATION`; -- the explicit `import std;` contract, macro boundary, `error_code` identity, - completion-token limitations, and the rule against mixing header inclusion - with module import in one translation unit; -- API areas intentionally absent from the generated wrapper and their - alternatives; -- the standalone package's Boost exclusions and the `co_spawn` migration from - stackful `spawn`; -- a migration checklist from header-only Asio to the canonical module package. - -## Stale References - -The comments will not restore the retired `compat.asio` package as a usable -dependency or the old `chriskohlhoff.asio` package name. Historical comparisons -will use generic "header-only Asio" wording. The obsolete warning against bare -`mcpp add asio@1.38.1` will be replaced by the canonical install command. +Do not include a tutorial, detailed Boost history, or a migration checklist. +Do not restore `compat.asio` or `chriskohlhoff.asio` as usable package names. ## Validation -Run Lua syntax validation, the repository mirror-table check, strict parsing -with the workflow-pinned mcpp, `git diff --check`, and the targeted -`asio-module` consumer suite. No full workspace or OpenCV test is required for -this comment-only change. +Prove the executable Lua table is unchanged, then run Lua syntax, mirror, +workflow-pinned parser, whitespace, and targeted `asio-module` checks only. From a3d953f6d38fcbd8d227983489955e873b77b11a Mon Sep 17 00:00:00 2001 From: wellwei <96378453+wellwei@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:42:06 +0800 Subject: [PATCH 11/11] docs(asio): restore module adaptation notes --- pkgs/a/asio.lua | 53 +++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/pkgs/a/asio.lua b/pkgs/a/asio.lua index b065195..b4671de 100644 --- a/pkgs/a/asio.lua +++ b/pkgs/a/asio.lua @@ -1,25 +1,40 @@ --- asio -- standalone Asio 1.38.1 exposed as the C++23 module `asio` --- (Form B inline descriptor, separate-compilation mode). +-- asio -- 将独立版 Asio 1.38.1 暴露为 C++23 模块 `asio` +-- (Form B inline descriptor, separate-compilation mode)。 -- --- Install and consume: --- mcpp add asio@1.38.1 --- import std; --- import asio; +-- 注意事项 +-- * 使用 `mcpp add asio@1.38.1` 引入;消费者需显式写 +-- `import std; import asio;`,因为本包设置 import_std = false。 +-- * 本包只支持模块方式消费。同一 translation unit 不要混用 +-- `#include ` 和 `import asio;`,避免 inline 定义与模块 BMI +-- 的 separate-compilation 定义产生 ODR 差异。 +-- * 默认 feature 显式传播 ASIO_STANDALONE、ASIO_SEPARATE_COMPILATION、 +-- ASIO_DISABLE_BOOST_CONTEXT_FIBER 和 ASIO_HAS_THREADS。Asio 头文件内部 +-- 自动检测的其他 ASIO_HAS_* 宏不会由 `import asio;` 导出。 -- --- The upstream 1.38.x release has no module interface unit. This descriptor --- generates a reviewed `asio.cppm` wrapper and compiles upstream `src/asio.cpp` --- with ASIO_SEPARATE_COMPILATION. `import std;` is required because this package --- does not inject the standard library through the module boundary. +-- 与 header-only Asio 的区别/限制 +-- * 上游 1.38.x 没有模块接口单元。本描述生成 `asio.cppm`,并只编译一次 +-- `*/src/asio.cpp` 中的非模板实现;首次构建需生成 BMI,增量构建可避免 +-- 每个消费者 translation unit 重复解析整组 Asio 头文件。 +-- * 模块只暴露 wrapper 中明确 export 的声明,不等同于 +-- `#include ` 的完整 API 表面。 +-- * asio::error_code 是 std::error_code 的别名;wrapper 导出 +-- asio::use_future 变量,但未导出 asio::use_future_t 类模板。 +-- * 依赖未导出 ASIO_HAS_* 宏、平台专用头文件或 Boost 扩展的代码,需要 +-- 改用标准/操作系统能力检测或另行扩展模块 wrapper。 -- --- This package is module-only. Textual `#include ` consumption and --- APIs not exported by the wrapper are outside its mcpp-index contract. The --- wrapper intentionally excludes SSL/TLS, local/POSIX/Windows handle APIs, --- serial ports, pipes, file I/O, stackful spawn, and other surfaces listed by --- headers that it does not include. --- --- ASIO_STANDALONE and ASIO_SEPARATE_COMPILATION are public build defines, but --- preprocessor macros do not cross `import asio;`. Consumers should use C++ or --- operating-system facilities instead of testing ASIO_HAS_* macros. +-- 未导出的组件 +-- * SSL/TLS (`asio/ssl/*.hpp`):需要 OpenSSL/wolfSSL 等外部依赖。 +-- * Unix 域套接字、POSIX 描述符和 Windows 句柄: +-- `asio/local/*.hpp`、`asio/posix/*.hpp`、`asio/windows/*.hpp`。 +-- * 串口、pipe 和文件 I/O:`asio/serial_port.hpp`、 +-- `asio/*able_pipe.hpp`、`asio/stream_file.hpp`、 +-- `asio/random_access_file.hpp`。 +-- * spawn()/yield_context 有栈协程:需要 Boost.Context;本包禁用其自动 +-- 检测,应改用 co_spawn + awaitable + use_awaitable。 +-- * deadline_timer、generic protocol、execution、traits、遗留宏式协程和 +-- streambuf:对应 `asio/deadline_timer.hpp`、`asio/generic/*.hpp`、 +-- `asio/execution/*.hpp`、`asio/traits/*.hpp`、`asio/yield.hpp`、 +-- `asio/coroutine.hpp`、`asio/streambuf.hpp`。 package = { spec = "1", namespace = "",