@@ -156,6 +156,8 @@ the package/feature boundary, not on an individual target.
156156``` toml
157157[build ]
158158sources = [" src/**/*.cppm" , " src/**/*.cpp" ] # Source globs (default: src/**/*.{cppm,cpp,cc,c,S,s,asm})
159+ module_extensions = [" .ixx" ] # Extra extensions your module INTERFACES use (§ below)
160+ build_program_timeout = 1800 # Seconds a build.mcpp may run; 0 = no limit (§ below)
159161include_dirs = [" include" , " third_party/include" ] # Header search paths
160162include_dirs_after = [" *" ] # Header dirs searched AFTER system dirs (-idirafter)
161163c_standard = " c11" # Standard for C source files (default c11)
@@ -194,6 +196,83 @@ baseline, and 14.0 is the floor of LLVM's official static libraries themselves).
194196This value enters the BMI fingerprint, so switching targets automatically rebuilds
195197the module cache.
196198
199+ ### Module interface extensions (` module_extensions ` )
200+
201+ mcpp treats ` .cppm ` as a module interface unit. The C++ ecosystem has not
202+ converged on one spelling — Clang also recognizes ` .ccm ` and ` .cxxm ` , MSVC uses
203+ ` .ixx ` — so a project whose interfaces use another extension declares it:
204+
205+ ``` toml
206+ [build ]
207+ module_extensions = [" .ixx" , " .ccm" ]
208+ ```
209+
210+ The list is ** additive** : ` .cppm ` is always a module interface and cannot be
211+ removed. To stop a particular file from being built, ` ! ` -exclude it in
212+ ` sources ` ; that is what ` sources ` is for.
213+
214+ Declaring an extension does three things at once, which is the point of having
215+ one key rather than several:
216+
217+ 1 . the convention default for ` sources ` grows to match, so the files are
218+ ** found** (` src/**/*.ixx ` joins the default glob);
219+ 2 . those units compile with the ** module** rule — they emit a BMI and their
220+ objects are linked unconditionally;
221+ 3 . the freshness fast path watches them, so adding an ` import ` to one
222+ invalidates the build graph instead of silently reusing a stale one.
223+
224+ Any extension is accepted ** except** ones that already name a non-module role
225+ (` .cpp ` ` .cc ` ` .cxx ` ` .c ` ` .m ` ` .mm ` ` .h ` ` .hpp ` ` .hh ` ` .hxx ` ` .S ` ` .s `
226+ ` .asm ` ); claiming one of those is a manifest error rather than a warning,
227+ because it would route (say) C files to the C++ module rule and fail somewhere
228+ that names neither the file nor this key.
229+
230+ Extensions are matched ** literally, without case folding** — ` .S ` and ` .s ` are
231+ different languages in this domain, so case is never ignored.
232+
233+ mcpp always tells the compiler explicitly that a module interface unit is one
234+ (` -x c++-module ` on Clang, ` -x c++ ` on GCC, ` /interface /TP ` on MSVC), so an
235+ extension the compiler driver has never heard of works anyway. This is why any
236+ extension is allowed: mcpp does not need the compiler to recognize it.
237+
238+ > ** Publishing note.** An older mcpp does not know this key: it warns, ignores
239+ > it, and then compiles those files as ordinary translation units — a wrong
240+ > build rather than a clean failure. If you publish a package that uses
241+ > ` module_extensions ` , declare an mcpp version floor in its index descriptor.
242+
243+ ### Build-program timeout (` build_program_timeout ` )
244+
245+ A ` build.mcpp ` gets ** 600 seconds** by default, after which mcpp kills it and
246+ fails the build naming the package. A project whose build program legitimately
247+ runs longer (a large code-generation step) raises its own bound:
248+
249+ ``` toml
250+ [build ]
251+ build_program_timeout = 1800 # seconds; 0 = no limit
252+ ```
253+
254+ The value is read from ** the manifest of the package that owns the
255+ ` build.mcpp ` ** — a dependency's generator is bounded by the dependency's own
256+ declaration, because its author is the one who knows how long it takes. The
257+ precedence follows the same shape as ` macos_deployment_target ` :
258+
259+ ```
260+ MCPP_BUILD_PROGRAM_TIMEOUT=<seconds> (this invocation; highest)
261+ > [build] build_program_timeout (that package's manifest)
262+ > 600 (built-in default)
263+ ```
264+
265+ Leaving the key out is not the same as setting ` 0 ` : unset means "use the
266+ default bound", ` 0 ` means "no bound at all".
267+
268+ This value is deliberately ** not** part of the build fingerprint — it changes
269+ no edge in the graph, and folding it in would mean that raising a timeout
270+ rebuilt the whole project, which is the opposite of what someone raising a
271+ timeout wants.
272+
273+ The ** compile** phase is not bounded, only the build * program* . See
274+ [ 07-build-mcpp.md] ( 07-build-mcpp.md ) for why that asymmetry is deliberate.
275+
197276### The C++ runtime contract (` cxx_runtime ` )
198277
199278` cxx_runtime ` states what the produced artifact promises about the machine that
0 commit comments