@@ -67,50 +67,113 @@ This is the chapter for a project that wants its own tool rather than the one th
6767plugin declares, stated in the build program and nowhere else -- no
6868` [xlings.overrides] ` , no environment variable. Chapter 4 covers those.
6969
70- ### 3.1 The four spellings
70+ ### 3.1 Four ways, each a whole build program
7171
72- Four spellings, all in ` build.mcpp ` , none of which downloads the payload. The
73- example is ` deps-vcpkg ` , whose option is ` options::vcpkg ` ; every member that
74- drives a tool has the same shape, with its own option name (section 3.6).
72+ Every example here is a complete ` build.mcpp ` that compiles. A member reads one
73+ option (section 3.6 is the index); what differs is what the project states.
74+
75+ ** A program this machine already has.** The plainest form: a string assigns to the
76+ option, so a project written before 0.19.0 keeps compiling unchanged.
7577
7678``` cpp
77- // build.mcpp
79+ // build.mcpp -- features = ["deps-vcpkg"]
7880import std;
7981import mcpp;
8082import mcpp.deps.vcpkg;
81- import mcpp.plugins.tool; // for `tool::root` and `tool::on_path` below
8283
8384int main () {
8485 mcpp::deps::vcpkg::options o;
85- o.libraries = { "fmt", "spdlog" };
86+ o.libraries = { "fmt" };
87+ o.vcpkg = "/opt/vcpkg/vcpkg";
88+ return mcpp::deps::vcpkg::use(o) ? 0 : 1;
89+ }
90+ ```
8691
87- // 1. the program itself -- a string assigns, so code written before 0.19.0
88- // keeps compiling
89- o.vcpkg = "/opt/vcpkg/vcpkg";
92+ ** A tree, with the member looking inside it. ** ` tool::root ` states a directory and
93+ lets the member apply its own layout: ` deps-cmake ` looks for ` cmake ` in ` bin ` and
94+ in ` CMake.app/Contents/bin ` , ` deps-vcpkg ` directly under the root.
9095
91- // 2. a tree. Each member states where it looks under a root: `deps-vcpkg`
92- // expects `vcpkg` directly there, `deps-cmake` looks in `bin` and in
93- // `CMake.app/Contents/bin`
94- o.vcpkg = mcpp::plugins::tool::root("/opt/vcpkg");
96+ ``` cpp
97+ // build.mcpp -- features = ["deps-cmake"]
98+ import std;
99+ import mcpp;
100+ import mcpp.deps.cmake;
101+ import mcpp.plugins.tool;
95102
96- // 3. the first one on PATH. A fallback is a choice, stated here, rather
97- // than something a member does quietly
98- o.vcpkg = mcpp::plugins::tool::on_path();
103+ int main () {
104+ mcpp::deps::cmake::options o;
105+ o.source = "greet";
106+ o.libraries = { "greet" };
107+ o.cmake = mcpp::plugins::tool::root("/opt/cmake-3.31.6");
108+ return mcpp::deps::cmake::use(o) ? 0 : 1;
109+ }
110+ ```
99111
100- // 4. the spelling `deps-vcpkg` has had since 0.18.1, still read: the same
101- // statement as `tool::root(...)`
102- o.vcpkg_root = "/opt/vcpkg";
112+ ** Whatever is on PATH, as a stated choice. ** A member never falls back to PATH on
113+ its own; ` tool::on_path() ` is how a project asks for that, so the log records that
114+ the build depends on the machine.
103115
104- return mcpp::deps::vcpkg::use(o) ? 0 : 1;
116+ ``` cpp
117+ // build.mcpp -- features = ["rules-spirv"]
118+ import std;
119+ import mcpp;
120+ import mcpp.rules.spirv;
121+ import mcpp.plugins.tool;
122+
123+ int main () {
124+ mcpp::rules::spirv::options o;
125+ o.compiler = mcpp::plugins::tool::on_path();
126+ return mcpp::rules::spirv::compile(o) ? 0 : 1;
105127}
106128```
107129
108- ` mcpp.plugins.tool ` needs no extra feature: ` deps-vcpkg ` implies ` deps ` , which
109- implies ` plugins-core ` . It does need the ` import ` above, though -- a feature makes
110- a module available, not visible. Assigning a plain string (form 1) and
111- ` vcpkg_root ` (form 4) need no import; naming ` tool::root ` or ` tool::on_path ` does,
112- and without it the compiler says `declaration of 'root' must be imported from
113- module 'mcpp.plugins.tool' before it is required`.
130+ ** A root that is the whole toolkit.** ` rules-cuda ` takes one tree holding nvcc, the
131+ runtime, CCCL and cuRAND, rather than a program:
132+
133+ ``` cpp
134+ // build.mcpp -- features = ["rules-cuda"]
135+ import std;
136+ import mcpp;
137+ import mcpp.rules.cuda;
138+ import mcpp.plugins.tool;
139+
140+ int main () {
141+ mcpp::rules::cuda::options o;
142+ o.toolkit = mcpp::plugins::tool::root("/usr/local/cuda-12.9");
143+ return mcpp::rules::cuda::compile(o) ? 0 : 1;
144+ }
145+ ```
146+
147+ ` rules-qt ` , ` rules-ascendc ` and ` dist-apk ` state a root with a plain string,
148+ because their option has always been a directory:
149+
150+ ``` cpp
151+ // build.mcpp -- features = ["rules-qt"]
152+ import std;
153+ import mcpp;
154+ import mcpp.rules.qt;
155+
156+ int main () {
157+ mcpp::rules::qt::options o;
158+ o.modules = { "Core", "Widgets" };
159+ o.root = "/opt/Qt/6.11.1/gcc_64";
160+ return mcpp::rules::qt::compile(o) ? 0 : 1;
161+ }
162+ ```
163+
164+ ** The spelling ` deps-vcpkg ` has had since 0.18.1** states the same thing as
165+ ` tool::root ` , and is still read:
166+
167+ ``` cpp
168+ o.vcpkg_root = " /opt/vcpkg" ;
169+ ```
170+
171+ ` mcpp.plugins.tool ` needs no extra feature: each ` deps-* ` and ` rules-* ` feature
172+ implies ` plugins-core ` . It does need the ` import ` shown above, though -- a feature
173+ makes a module available, not visible. Assigning a plain string needs no import;
174+ naming ` tool::root ` or ` tool::on_path ` does, and without it the compiler says
175+ `declaration of 'root' must be imported from module 'mcpp.plugins.tool' before it
176+ is required`.
114177
115178### 3.2 Where a relative path points
116179
@@ -123,19 +186,37 @@ o.vcpkg = mcpp::plugins::tool::root("third_party/vcpkg");
123186
124187### 3.3 Deciding inside the build program
125188
126- ** The choice is a value, so the decision is ordinary code.** Register the variable
127- that informs it, and the build re-plans when it changes:
189+ ** The choice is a value, so the decision is ordinary code.** A project that ships a
190+ vendored copy and also honours what CI provides writes both, and registers the
191+ variable so the build re-plans when it changes:
128192
129193``` cpp
130- if (const char * r = std::getenv(" VCPKG_ROOT" ); r && *r) {
131- mcpp::rerun_if_env_changed ("VCPKG_ROOT");
132- o.vcpkg = mcpp::plugins::tool::root(r); // use it where CI provides one
194+ // build.mcpp -- features = ["deps-vcpkg"]
195+ import std;
196+ import mcpp;
197+ import mcpp.deps.vcpkg;
198+ import mcpp.plugins.tool;
199+
200+ int main () {
201+ mcpp::deps::vcpkg::options o;
202+ o.libraries = { "fmt" };
203+
204+ // the copy in the repository, relative to the package root
205+ o.vcpkg = mcpp::plugins::tool::root("third_party/vcpkg");
206+
207+ // and the machine's own, where CI provides one
208+ if (const char* r = std::getenv("VCPKG_ROOT"); r && *r) {
209+ mcpp::rerun_if_env_changed ("VCPKG_ROOT");
210+ o.vcpkg = mcpp::plugins::tool::root(r);
211+ }
212+ return mcpp::deps::vcpkg::use(o) ? 0 : 1;
133213}
134- // left default: the ecosystem's xim:vcpkg
135214```
136215
137- ` mcpp::plugins::toolchain::env("VCPKG_ROOT") ` is the same two lines, for a
138- project that already enables ` plugins-toolchain ` .
216+ Leaving the option untouched in some branch is also a decision: that branch takes
217+ the ecosystem's ` xim:vcpkg ` . ` mcpp::plugins::toolchain::env("VCPKG_ROOT") ` is the
218+ same two lines as the ` getenv ` pair, for a project that already enables
219+ ` plugins-toolchain ` .
139220
140221### 3.4 A stated choice that fails is not replaced
141222
0 commit comments