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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
directory as `engineModules`.
- Read a unit that imports `mcpp.core` as a build-plugin unit (SPEC-007 §10). A
plugin's `[dependencies]` are compiled with it for the build program, so a
plugin may build on plugins and libraries; `mcpp build` and `mcpp test` in a
plugin may build on plugins and libraries, and one it marks `reexport = true`
is importable by its consumers' build programs; `mcpp build` and `mcpp test` in a
plugin plan it in the build-program configuration. A plugin reached through
a target's `[dependencies]`, a program target that imports `mcpp`, `--target`
for another machine on a plugin, and `mcpp pack` of a plugin are refused,
Expand Down
8 changes: 5 additions & 3 deletions docs/31-authoring-a-rule-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,11 @@ the build-program configuration only. Three consequences follow for its author.
- **What the rule's library imports is in its `[dependencies]`.** A rule built
on another rule (`mcpp:plugins`' `plugins-core`, say) or on an ordinary
library (a TOML parser) names it there. When a consumer's build program uses
the rule, those dependencies are compiled for the build program with it. The
rule's `[build-dependencies]` serve the rule package's own `build.mcpp`, as
any package's do.
the rule, those dependencies are compiled for the build program with it. A
dependency the consumers' build programs import themselves is handed on with
`reexport = true` on its entry; without it the import is refused, naming the
key. The rule's `[build-dependencies]` serve the rule package's own
`build.mcpp`, as any package's do.
- **The package builds and tests as the root of a build.** `mcpp build` in the
package compiles its library for this machine, with the engine interface, and
`mcpp test` runs its tests under `tests/` the same way: a test may import the
Expand Down
5 changes: 3 additions & 2 deletions docs/zh/31-authoring-a-rule-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,9 @@ bool compile(options opt = {});

- **规则的库所导入的东西写在它的 `[dependencies]` 中。** 基于另一条规则(例如
`mcpp:plugins` 的 `plugins-core`)或普通库(例如 TOML 解析器)的规则在那里写出它。消费方的
构建程序使用这条规则时,这些依赖与它一起为构建程序编译。规则的 `[build-dependencies]`
服务规则包自己的 `build.mcpp`,与任何包相同。
构建程序使用这条规则时,这些依赖与它一起为构建程序编译。消费方的构建程序自己也导入的依赖,
在其条目上写 `reexport = true` 交出;不写时该导入被拒绝,诊断写出这个键。规则的
`[build-dependencies]` 服务规则包自己的 `build.mcpp`,与任何包相同。
- **规则包可以作为构建的根构建与测试。** 在包中执行 `mcpp build` 会为本机编译它的库并带上
引擎接口,`mcpp test` 以同样的方式运行 `tests/` 下的测试:测试可以导入规则的模块与 `mcpp`,
在没有消费方工程的情况下检查规则的逻辑。
Expand Down
11 changes: 10 additions & 1 deletion src/build/prepare/host_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,16 @@ std::expected<void, std::string> check_program_imports(PrepareState& state, std:
}
const auto wants = mcpp::pm::imported_module_names(text);
if (wants.empty()) return {};
const auto libs = program_libraries(state, i);
auto libs = program_libraries(state, i);
// What a library hands on: a dependency on a `reexport = true` edge of its
// own `[dependencies]` is importable by the programs that use the library,
// as a `[build-dependencies]` entry it re-exports is (provisions).
for (std::size_t k = 0; k < libs.size(); ++k)
for (auto const& e : state.dependencyEdges)
if (e.consumerPackageIndex == libs[k] && !e.buildTable && e.reexport
&& e.dependencyPackageIndex < state.packages.size()
&& std::ranges::find(libs, e.dependencyPackageIndex) == libs.end())
libs.push_back(e.dependencyPackageIndex);
std::set<std::string> available{"std", "std.compat", "mcpp", "mcpp.core"};
std::map<std::string, std::size_t> providerOf;
for (auto d : libs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
# D P1: a plugin reached through [dependencies] of a target is refused,
# naming the chain and [build-dependencies];
# E P4: a program target importing mcpp is refused;
# F P5: `mcpp pack` refuses a plugin.
# F P5: `mcpp pack` refuses a plugin;
# G a library a plugin depends on is importable by the plugin's consumers'
# build programs when the plugin hands it on (`reexport = true` on its
# [dependencies] edge), and refused, naming `reexport`, when it does not.
set -e
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
Expand Down Expand Up @@ -95,4 +98,12 @@ grep -q "exists only in a build" e.log || fail "E: the refusal does not say why"
cd "$TMP/rule"
"$MCPP" pack > f.log 2>&1 && fail "F: mcpp pack accepted a plugin" f.log
grep -q "is a build plugin" f.log || fail "F: the refusal does not say why" f.log
# G
cd "$TMP/app"
printf 'import acme.rule;\nimport acme.util;\nint main() { if (util_base() == 40) acme::rule::go(); }\n' > build.mcpp
"$MCPP" build > g1.log 2>&1 && fail "G: a library the plugin does not hand on was importable" g1.log
grep -q "reexport = true" g1.log || fail "G: the refusal does not name reexport" g1.log
sed -i 's|util = { path = "../util" }|util = { path = "../util", reexport = true }|' "$TMP/rule/mcpp.toml"
"$MCPP" build > g2.log 2>&1 || fail "G: a library the plugin hands on was refused" g2.log
[ "$("$MCPP" run 2>/dev/null | grep '^V=' | tail -1)" = "V=42" ] || fail "G: value" g2.log
echo "PASS: 910_a_build_plugin_is_a_package_of_the_build_program"
Loading