Summary
Feature request: support per-glob flags inside conditional target sections — [target.'cfg(<os>)'.build] (and [target.<triple>.build]) should accept the same flags = [{ glob, cflags, cxxflags, asmflags, defines }] array that [build] accepts. Today the conditional build section parses only cflags/cxxflags/ldflags/sources (src/manifest/toml.cppm:976-987), and [features.<n>.flags] is likewise global-only; the per-OS flag semantics that #253 added exist only in the xpkg descriptor grammar (mcpp.<os>.features, mcpp.<os>.flags).
This is now the single blocker for the opencv-m single-repo windows leg (Sunrisepeak/opencv-m feat/vendor-single-repo — the vendored OpenCV build that retires compat.opencv).
Why hoisting/global tricks cannot cover windows
The three frozen per-OS snapshots need different per-glob defines on the same TU paths:
-
linux vs macos deltas are pure per-OS additions with group-unique names (PNG_INTEL_SSE_OPT vs PNG_ARM_NEON_OPT, NEON_INTRINSICS, HAVE_CAMV4L2, …) — we hoisted those to per-OS global cflags and shipped the macos leg that way. Workable, but already a hack: it relies on grep-verifying that each define name is only read by its own code group.
-
windows needs both additions and REMOVALS on shared globs, e.g.:
**/3rdparty/zlib/**: linux/mac say HAVE_UNISTD_H=1; windows must NOT define it (clang-MSVC has no unistd.h) and adds NO_FSEEKO
third_party/.../core/src/alloc.cpp: HAVE_MEMALIGN/HAVE_POSIX_MEMALIGN (unix) vs HAVE_WIN32_ALIGNED_MALLOC=1 (win)
**/modules/videoio/**: HAVE_CAMV4L2/HAVE_FFMPEG_LIBAVDEVICE (linux) absent on windows
- every group:
WIN32 _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS _VARIADIC_MAX=10 _WIN32_WINNT=0x0601 _WINDOWS added
A removal cannot be expressed by any global-flag overlay: [[build.flags]] is unconditional, so the unix -DHAVE_UNISTD_H=1 from the union table reaches windows TUs; -U counter-entries would need to be windows-only — same gap, recursed.
The only in-grammar workaround is resurrecting a per-OS tu-stub indirection layer (per-OS wrapper TUs whose paths are OS-unique so globs can key on them) for every conflicting group — the pre-0.0.97 #233-era machinery this project was happy to delete.
Proposed grammar
[target.'cfg(windows)'.build]
cflags = ["-DWIN32", "-D_WIN32_WINNT=0x0601"] # exists today
flags = [ # NEW: same GlobFlags shape as [build].flags
{ glob = "third_party/opencv/3rdparty/zlib/**", defines = ["NO_FSEEKO"] },
{ glob = "third_party/opencv/modules/core/src/alloc.cpp", defines = ["HAVE_WIN32_ALIGNED_MALLOC=1"] },
]
Merge semantics: append the matching conditional entries AFTER [build].flags in the ordered vector (same "last flag wins" rule) — that also gives -U/re--D override power over the unconditional table, which covers the removal case. Same for [target.<sel>.'features'.…] or at least [target.<sel>.build.flags] reachable from features via the existing feature-flag funnel.
Symmetry argument: the descriptor grammar already has exactly this (per-OS flags inside mcpp.<os>, #253); manifest-built packages (single-repo/vendored libraries, workspace members, path deps) are second-class without it. Dep builds already run the conditional merge through the single #229 funnel (merge_conditional_sources_flags), so the plumbing point is well-defined.
Context / evidence
- opencv-m single-repo branch: linux (gcc16 + llvm 20/22 + x86_64-linux-musl static) and the macos wiring are green with the manifest-only approach; the parked windows tables live in the port fragments (
windows-flags-PARKED.toml, windows-dnn-flags-PARKED.toml) ready to drop in the day this lands.
- Conflict inventory was produced mechanically by tools/vendor/port_descriptor.py's cross-OS union check and is reproducible from mcpp-index
pkgs/c/compat.opencv.lua @8692bb26.
Environment: mcpp 0.0.101.
Summary
Feature request: support per-glob flags inside conditional target sections —
[target.'cfg(<os>)'.build](and[target.<triple>.build]) should accept the sameflags = [{ glob, cflags, cxxflags, asmflags, defines }]array that[build]accepts. Today the conditional build section parses onlycflags/cxxflags/ldflags/sources(src/manifest/toml.cppm:976-987), and[features.<n>.flags]is likewise global-only; the per-OS flag semantics that #253 added exist only in the xpkg descriptor grammar (mcpp.<os>.features,mcpp.<os>.flags).This is now the single blocker for the opencv-m single-repo windows leg (Sunrisepeak/opencv-m
feat/vendor-single-repo— the vendored OpenCV build that retirescompat.opencv).Why hoisting/global tricks cannot cover windows
The three frozen per-OS snapshots need different per-glob defines on the same TU paths:
linux vs macos deltas are pure per-OS additions with group-unique names (
PNG_INTEL_SSE_OPTvsPNG_ARM_NEON_OPT,NEON_INTRINSICS,HAVE_CAMV4L2, …) — we hoisted those to per-OS globalcflagsand shipped the macos leg that way. Workable, but already a hack: it relies on grep-verifying that each define name is only read by its own code group.windows needs both additions and REMOVALS on shared globs, e.g.:
**/3rdparty/zlib/**: linux/mac sayHAVE_UNISTD_H=1; windows must NOT define it (clang-MSVC has no unistd.h) and addsNO_FSEEKOthird_party/.../core/src/alloc.cpp:HAVE_MEMALIGN/HAVE_POSIX_MEMALIGN(unix) vsHAVE_WIN32_ALIGNED_MALLOC=1(win)**/modules/videoio/**:HAVE_CAMV4L2/HAVE_FFMPEG_LIBAVDEVICE(linux) absent on windowsWIN32 _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS _VARIADIC_MAX=10 _WIN32_WINNT=0x0601 _WINDOWSaddedA removal cannot be expressed by any global-flag overlay:
[[build.flags]]is unconditional, so the unix-DHAVE_UNISTD_H=1from the union table reaches windows TUs;-Ucounter-entries would need to be windows-only — same gap, recursed.The only in-grammar workaround is resurrecting a per-OS tu-stub indirection layer (per-OS wrapper TUs whose paths are OS-unique so globs can key on them) for every conflicting group — the pre-0.0.97 #233-era machinery this project was happy to delete.
Proposed grammar
Merge semantics: append the matching conditional entries AFTER
[build].flagsin the ordered vector (same "last flag wins" rule) — that also gives-U/re--Doverride power over the unconditional table, which covers the removal case. Same for[target.<sel>.'features'.…]or at least[target.<sel>.build.flags]reachable from features via the existing feature-flag funnel.Symmetry argument: the descriptor grammar already has exactly this (per-OS
flagsinsidemcpp.<os>, #253); manifest-built packages (single-repo/vendored libraries, workspace members, path deps) are second-class without it. Dep builds already run the conditional merge through the single #229 funnel (merge_conditional_sources_flags), so the plumbing point is well-defined.Context / evidence
windows-flags-PARKED.toml,windows-dnn-flags-PARKED.toml) ready to drop in the day this lands.pkgs/c/compat.opencv.lua@8692bb26.Environment: mcpp 0.0.101.