Skip to content

Commit 1593afe

Browse files
committed
fix(pm): resolve namespaced local path index entries
1 parent 42dfab5 commit 1593afe

4 files changed

Lines changed: 104 additions & 10 deletions

File tree

.agents/docs/2026-05-30-package-owned-build-flags-plan.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ xlings 现在可以用 `mcpp 0.0.34` 构建,但工程文件里有大量 C 库
2525
- [x] 包级 include dirs 在编译该包源码时优先于全局 include dirs。
2626
- [x] build fingerprint / cache key 包含包级 flags,避免 flags 变化后误用缓存。
2727
- [x] Form B 描述支持 `generated_files`,让官方索引包可以生成少量包私有配置头。
28+
- [x] 本地 `path` 索引读取使用命名空间候选,支持 `pkgs/c/compat.foo.lua` 这类官方索引布局。
2829
- [x] 保持现有项目级 flags 兼容,不破坏已有 manifest。
2930
- [x] 用 xlings 当前项目验证 `mcpp build``mcpp build --target x86_64-linux-musl`
3031

@@ -65,6 +66,8 @@ cd /home/speak/workspace/github/openxlings/xlings
6566
- [x] package-owned generated support files implementation:
6667
- `tests/unit/test_manifest.cpp` 覆盖 Form B `generated_files` 解析。
6768
- `tests/e2e/51_package_generated_files.sh` 覆盖生成文件参与依赖包编译。
69+
- [x] local path index namespace lookup:
70+
- `tests/e2e/52_local_path_namespaced_index.sh` 覆盖 `compat` 命名空间文件名候选。
6871
- [x] xlings local validation:
6972
- `mcpp build` -> `target/x86_64-linux-gnu/ff952c89919589bb/bin/xlings --version` = `xlings 0.4.45`.
7073
- `mcpp build --target x86_64-linux-musl` -> `target/x86_64-linux-musl/7e48a312cd4dbb49/bin/xlings` static ELF.

src/cli.cppm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,7 @@ prepare_build(bool print_fingerprint,
16041604
if (idxSpec && idxSpec->is_local()) {
16051605
auto indexPath = mcpp::config::resolve_project_index_path(*root, *idxSpec);
16061606
auto luaCheck = mcpp::fetcher::Fetcher::read_xpkg_lua_from_path(
1607-
indexPath, shortName);
1607+
indexPath, ns, shortName);
16081608
if (!luaCheck) return std::unexpected(std::format(
16091609
"dependency '{}': not found in local index at '{}'",
16101610
depName, indexPath.string()));
@@ -1687,7 +1687,7 @@ prepare_build(bool print_fingerprint,
16871687
if (idxSpec && idxSpec->is_local()) {
16881688
auto indexPath = mcpp::config::resolve_project_index_path(*root, *idxSpec);
16891689
luaContent = mcpp::fetcher::Fetcher::read_xpkg_lua_from_path(
1690-
indexPath, shortName);
1690+
indexPath, ns, shortName);
16911691
} else if (idxSpec && !idxSpec->is_builtin()) {
16921692
luaContent = mcpp::fetcher::Fetcher::read_xpkg_lua_from_project_data(
16931693
*root, ns, shortName);

src/pm/package_fetcher.cppm

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ public:
113113
// Used for [indices] entries with `path = "/some/dir"`.
114114
static std::optional<std::string>
115115
read_xpkg_lua_from_path(const std::filesystem::path& indexPath,
116+
std::string_view ns,
116117
std::string_view shortName);
117118

118119
// Read xpkg .lua from a project-level xlings data directory.
@@ -451,21 +452,27 @@ Fetcher::read_xpkg_lua(std::string_view ns, std::string_view shortName) const
451452

452453
std::optional<std::string>
453454
Fetcher::read_xpkg_lua_from_path(const std::filesystem::path& indexPath,
455+
std::string_view ns,
454456
std::string_view shortName)
455457
{
456458
if (shortName.empty()) return std::nullopt;
457459

458460
auto pkgsDir = indexPath / "pkgs";
459461
if (!std::filesystem::exists(pkgsDir)) return std::nullopt;
460462

461-
char first = static_cast<char>(std::tolower(
462-
static_cast<unsigned char>(shortName.front())));
463-
auto candidate = pkgsDir / std::string(1, first) / (std::string(shortName) + ".lua");
464-
if (!std::filesystem::exists(candidate)) return std::nullopt;
465-
466-
std::ifstream is(candidate);
467-
std::stringstream ss; ss << is.rdbuf();
468-
return ss.str();
463+
auto filenames = mcpp::pm::compat::xpkg_lua_candidates(ns, shortName);
464+
for (auto& fname : filenames) {
465+
if (fname.empty()) continue;
466+
char first = static_cast<char>(std::tolower(
467+
static_cast<unsigned char>(fname.front())));
468+
auto candidate = pkgsDir / std::string(1, first) / fname;
469+
if (!std::filesystem::exists(candidate)) continue;
470+
471+
std::ifstream is(candidate);
472+
std::stringstream ss; ss << is.rdbuf();
473+
return ss.str();
474+
}
475+
return std::nullopt;
469476
}
470477

471478
// ─── read_xpkg_lua from project-level data dir ─────────────────────
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env bash
2+
# requires: gcc fresh-sandbox
3+
# Local path indices must use the same namespace-aware filename candidates
4+
# as cloned/builtin indices, e.g. pkgs/c/compat.foo.lua.
5+
set -e
6+
7+
TMP=$(mktemp -d)
8+
trap "rm -rf $TMP" EXIT
9+
10+
export MCPP_HOME="$TMP/mcpp-home"
11+
source "$(dirname "$0")/_inherit_toolchain.sh"
12+
13+
INDEX_DIR="$TMP/local-index"
14+
mkdir -p "$INDEX_DIR/pkgs/c"
15+
cat > "$INDEX_DIR/pkgs/c/compat.cfg.lua" <<'EOF'
16+
package = {
17+
spec = "1",
18+
namespace = "compat",
19+
name = "compat.cfg",
20+
description = "Namespaced local path index package",
21+
licenses = {"MIT"},
22+
type = "package",
23+
xpm = {
24+
linux = {
25+
["1.0.0"] = {
26+
url = "https://example.invalid/cfg-1.0.0.tar.gz",
27+
sha256 = "0000000000000000000000000000000000000000000000000000000000000000",
28+
},
29+
},
30+
},
31+
mcpp = {
32+
language = "c++23",
33+
import_std = false,
34+
sources = { "src/*.c" },
35+
targets = { ["cfg"] = { kind = "lib" } },
36+
deps = {},
37+
},
38+
}
39+
EOF
40+
41+
mkdir -p "$TMP/project/app/src" \
42+
"$TMP/project/app/.mcpp/.xlings/data/xpkgs/compat.cfg/1.0.0/src"
43+
cd "$TMP/project/app"
44+
45+
cat > .mcpp/.xlings/data/xpkgs/compat.cfg/1.0.0/src/cfg.c <<'EOF'
46+
int cfg_value(void) {
47+
return 42;
48+
}
49+
EOF
50+
51+
cat > src/main.cpp <<'EOF'
52+
extern "C" int cfg_value(void);
53+
int main() {
54+
return cfg_value() == 42 ? 0 : 1;
55+
}
56+
EOF
57+
58+
cat > mcpp.toml <<EOF
59+
[package]
60+
name = "app"
61+
version = "0.1.0"
62+
63+
[indices]
64+
compat = { path = "$INDEX_DIR" }
65+
66+
[dependencies.compat]
67+
cfg = "1.0.0"
68+
69+
[targets.app]
70+
kind = "bin"
71+
main = "src/main.cpp"
72+
EOF
73+
74+
"$MCPP" build > build.log 2>&1 || {
75+
cat build.log
76+
exit 1
77+
}
78+
79+
"$MCPP" run > run.log 2>&1 || {
80+
cat run.log
81+
exit 1
82+
}
83+
84+
echo "OK"

0 commit comments

Comments
 (0)