[Part A] build: XRGUI under mcpp, beside xmake (Windows / MSVC, Linux and macOS / clang, with CI) - #11
Open
Sunrisepeak wants to merge 16 commits into
Open
[Part A] build: XRGUI under mcpp, beside xmake (Windows / MSVC, Linux and macOS / clang, with CI)#11Sunrisepeak wants to merge 16 commits into
Sunrisepeak wants to merge 16 commits into
Conversation
Unmodified master does not compile with the toolset its own workflow
installs. Measured, not inferred: a probe branch carrying one markdown file
and nothing else fails on 14.52.36629 with
typesetting.rich_text.argument.ixx: error C2039:
'vec2': is not a member of 'mo_yanxi::math'
plus the C4430 / C3646 / C2440 cascade behind it, and no other file in the
tree reports anything.
The file uses math::vec2 and nothing it already imports re-exports it:
graphic.color re-exports math.vector4, and vector4 only plain-imports
mo_yanxi.math. It built on 14.52.36510 because names leaked across the module
boundary there; 36629 does not leak them. So the import is written down.
Nothing to do with the rest of this branch — this is the one change
unmodified master needs today, and it is worth taking on its own.
…for it
xmake.lua asked for this: "msvc 新版好像没这问题了,哪天删了,,,".
The macro chose between `#include <gch/small_vector.hpp>` and
`import <gch/small_vector.hpp>;` in sixteen files, and add_xrgui_core_deps()
defined it — so xmake was taking the HEADER UNIT branch, and this commit
keeps the `#include` one. That is not a no-op, and the three source changes
here are its price rather than independent fixes:
A header unit's declarations are reachable to whoever imports the module; a
global module fragment's are discarded unless the purview names them. gch
spells the container's operator== and its iterator's operator-(a, b) as free
function templates rather than hidden friends, so once the header moves into
the GMF, an importer has neither.
typesetting.rich_text.ixx operator== written out, comparing features
through data()/size() rather than the
container. A defaulted one is synthesized at
each odr-use — in every module that compares a
layout_config — and fails there. Writing the
body is not enough on its own: gch::operator==
is itself a template and instantiates at the
call, dragging std::equal and its need for
operator-(a, b) along. `const hb_feature_t*`
has none of that.
typesetting.ixx assign(data(), data() + size()) for the same
reason: vector's range constructor sizes the
allocation with operator-(a, b).
typesetting.segmented_layout includes the header itself, rather than
hoping to inherit it from rich_text.
That these are consequences and not pre-existing breakage is measured: the
baseline probe (unmodified master, macro on) reports no C2243 and nothing out
of <xutility>, and its log shows small_vector.hpp.ifc — the header unit doing
exactly the job this commit gives up.
WHAT IT BUYS. Two things. The macro's live branch was the one nobody had
exercised in a long time — the CI on this branch is what says the surviving
one compiles. And header units are one of the two constructs mcpp's scanner
cannot follow, which a conditional does not help with: it refuses an `import`
inside one whether or not the branch is live.
The hardest part to place was not the fix but the report: cl blames the
template definition (ui.util.ixx:140) while the instantiation is in
text_edit.ixx, label.ixx, and one more for every future comparison — so
fixing it at the importers is whack-a-mole.
Two headers are compiled here by defining an implementation macro before
including them. Both become a problem when the library comes from a package
that already did it, so both get an opt-out — and NEITHER macro is defined by
xmake, so the xmake build is unchanged byte for byte.
XRGUI_MINIAUDIO_IMPL_PROVIDED MINIAUDIO_IMPLEMENTATION
compat.miniaudio compiles upstream's own miniaudio.c. Instantiating it
here as well defines every ma_* symbol twice — and only at LINK time,
which is a long way from the cause.
XRGUI_MSDFGEN_NO_CPP11 MSDFGEN_USE_CPP11
compat.msdfgen is built with it OFF and says so through the
msdfgen-config.h that every public header includes — which is precisely
how that package and its consumers agree on which declarations exist.
Defining it here anyway breaks that agreement one-sidedly:
Contour::addEdge(EdgeHolder&&) gets declared for this TU and exists
nowhere, surfacing as an unresolved external. xrepo's msdfgen IS built
with it, so xmake keeps the define.
Consumer-supplied rather than auto-detected: whether the implementation is
already compiled is a property of the build that provides the library, and
only that build knows it.
Four changes to the xmake workflow, all about it answering the same question
twice in a row. None of them is about mcpp.
runs-on: windows-2025 `windows-latest` currently maps to the VS 2026
image — currently. This build is sensitive to the toolchain, so it says
which one it wants.
assert VCToolsVersion `-vcvars_ver=14.52` is a request; nothing checked
the answer. Dropping to the image's 14.51 is a real failure (C1001 ICE
in template.cpp at vector2.ixx:67, "IFC import detected") and is
presumably why this workflow reached for a preview at all — so a 14.51
answer now fails the job. The exact build number moves whenever
aka.ms/vs/18/insiders does, which is Microsoft's schedule and not a
reason to fail a commit: that is a ::warning:: and the run continues,
while staying the first thing to suspect when this job reddens on an
unrelated change.
concurrency + cancel Each run installs VS 2026 Insider and the Vulkan
SDK before compiling anything. A superseded run is a very long slot
spent on an answer nobody wants.
pull_request (any base) It only ran for PRs targeting master, so a PR
into a topic branch got no build at all.
Sunrisepeak
force-pushed
the
pr/mcpp-build-support
branch
from
September 12, 2026 18:56
31d7426 to
01cb21a
Compare
Sunrisepeak
force-pushed
the
pr/mcpp-build-support
branch
3 times, most recently
from
September 12, 2026 20:19
aa3c2a5 to
561b2fb
Compare
Standard C++ where MSVC was lenient, in the shape the errors named:
* explicit imports where a name arrived through another module's
reachability; an int passed for a float non-type template parameter;
a lambda odr-using an enclosing constexpr; operator== of another
module's global module fragment; std::vector::erase required noexcept
(MSVC's library adds it, libc++ does not); a deduced return type used
before its definition during instantiation.
* two facilities libc++ has not shipped -- views::stride / slide and
move_only_function -- and range_const_reference_t, routed through two
module interfaces added beside the mcpp manifest, mo_yanxi.views and
mo_yanxi.functional, which resolve to std:: where the library has them.
xmake compiles them too; MSVC's library has everything, so there they
are using-declarations.
* gtl's instantiation moved into the translation unit that includes the
header, for clang only: MSVC 14.52 loses the class's member template
at the use site when the specialisation is explicitly instantiated in
the interface.
* a coroutine owned by two objects, and a union initialised through a
conversion MSVC 14.52 tries brace elision on first.
Examples and tests build on Linux (clang 22, libc++) and 54 tests pass.
The reference build stays Windows / MSVC 14.52.
Sunrisepeak
force-pushed
the
pr/mcpp-build-support
branch
2 times, most recently
from
September 13, 2026 04:40
7e82066 to
8f5ab2e
Compare
Nothing in the tree uses it (no VkPhysicalDeviceMaintenance9Features, no call gated on it), and requiring it rejected every device on a Linux machine -- neither a current NVIDIA driver nor llvmpipe reports it -- so the application exited before opening a window. Commented out beside its neighbours; put it back with the code that needs it.
GLFW maps a window as soon as it is created, about 650 ms before this project draws into it; under a compositor that is a transparent rectangle that suddenly fills in. window::show() is idempotent and vk::context calls it after each successful present, on both of its present paths, so every application -- the hello, the showcase, a consumer's -- gets it without a call of its own.
A second build system that changes nothing for the first: mcpp.toml is a
transcription of xmake.lua, and xmake.lua is untouched by this commit.
What mcpp gets told, and what it is left to do itself:
* the source set, defines, include directories and system libraries as
data in mcpp.toml; every third-party library from the index, pinned;
the three submodules as path packages under mcpp/, each manifest a
transcription of that repository's own xmake.lua;
* the shaders as build-graph edges: mcpp.rules.slang compiles every
.slang into the binary, and the two consumers reach them through the
generated header under XRGUI_SHADER_SURFACE (the #else branches are the
xmake code, verbatim);
* the icons through mcpp/svg_outline, a one-file tool this repository
builds: a stroked icon becomes a filled one geometrically (one capsule
contour per segment; msdfgen's overlap support does the union) instead
of being rasterised and traced back by a node package;
* runtime data through [runtime] deploy, the Windows icon through
[resources], the GUI subsystem through windows_subsystem, the
distributables through mcpp:plugins' appimage and wix members.
build.mcpp keeps what mcpp has no key for: two submodule patches (standard
C++ for clang, applied before the module scan; their home is upstream) and
the icon summary header. No tool is looked up on PATH.
Known cost: on Windows the GUI programs no longer attach to a parent
console, so their stdout is not visible there.
Windows: the same VS 2026 Insider toolset (14.52) build_and_dispatch.yml installs, so the two workflows differ in the build system and nothing else. Two legs, because `msvc@system` and `msvc@<toolset>` are different questions: the system leg proves an explicit VSINSTALLDIR outranks the vswhere probe on a runner that has two Visual Studios; the managed leg has no Visual Studio at all and builds with the content-pinned payload the manifest names. Both pack a zip and an MSI. Linux: the clang the manifest pins, the tests run, a vendored tarball and an AppImage. Each job installs one thing, mcpp, and asserts its version.
Sunrisepeak
force-pushed
the
pr/mcpp-build-support
branch
2 times, most recently
from
September 13, 2026 07:50
233bf85 to
7471ad4
Compare
Three things, all scoped to Apple: - rect_ortho.ixx includes <immintrin.h> and uses SSE unconditionally; the submodule patch gains a hunk that keys the intrinsics on SSE being available and gives the overlap test a scalar fallback, which is what an arm64 build gets. - The SDK's assert() expands to __builtin_expect. Named in a module purview, clang 22 attaches the builtin to that module, and a unit that imports two such modules and asserts itself is told the call is ambiguous. mcpp/darwin/assert.h shadows the SDK header on this package's own -I (build.mcpp adds it on macOS only) and redefines the macro without the hint; same __assert_rtn, same NDEBUG behaviour. - cxx_runtime = "host-coupled" was project-wide, for /MD on MSVC. On macOS it means the system libc++, which is older than the clang 22 headers and lacks symbols they reference (__hash_memory, the atomic wait table). The key moves to the MSVC triple; Linux and macOS take mcpp's default, the toolchain's libc++ linked statically. Linux was already linked that way, so nothing changes there.
The Unix workflow becomes a two-row matrix (ubuntu-24.04, macos-15); the manifest configures the same llvm@22.1.8 for macOS as for Linux. Packing stays Linux-only: mcpp's closure walk does not handle Mach-O yet.
src.tests/ becomes tests/: `mcpp test` builds every file there into its own program and runs it, with gtest as a [dev-dependencies] entry whose `main` feature is gtest_main -- so the shared main.cpp goes, and with it the xrgui_tests target, the tests feature and its feature-deps. xmake's single xrgui.tests binary takes the same entry from its gtest package's `main` config. CI runs `mcpp test` in place of build-then-find-binary.
CONST_FN on size()/begin()/data()/end() told clang the result depends on `this` alone; they read storage_, which resize_and_overwrite replaces. At -O2 the data() taken before a resize was reused after it, and the showcase's first draw push memcpy'd into a null pointer (SIGSEGV in contiguous_draw_list::push). MSVC defines the macro empty, so the release build never showed it there. Found by running the release showcase on Linux.
render_context::load_shader("post_process.bloom") -- and the free
load_builtin_shader behind it -- is now the only place that knows where
a shader comes from: the arrays mcpp.rules.slang compiled in under
XRGUI_SHADER_SURFACE, a .spv beside the program otherwise. The renderer
bundle and the showcase both go through it, so the showcase's main.cpp
carries no macro and no generated header, which is what lets it be
built as a separate package (a workspace member, or any consumer):
the macro and the header are private to xrgui.
xrgui is the library; src.hello and src.examples, the directories the two programs already live in, become packages of their own that depend on it by path, so the commands are mcpp's: `mcpp run -p src.hello`, `mcpp run -p src.examples`, `mcpp build --workspace`, and `mcpp pack` from a member's directory. The bin targets, the exe icon and the Windows subsystem leave the root manifest for the members; the `examples` feature stays, requested by the showcase member, and still excludes the member's main.cpp. Each member carries the release profile's NDEBUG, which is not inherited. Nothing moves: xmake's targets read the same files they always did.
…er's runs A debug build asks the loader for VK_LAYER_KHRONOS_validation, and the host's copy is not reachable from the glibc an mcpp-built program runs on (found by manifest, lost at dlopen). The root manifest now names xim:vulkan-validation-layers at the `run` tier: installed for `mcpp run` and `mcpp test`, never part of an artifact, inherited by the two application members and by template projects through their dependency on xrgui. `mcpp run -p showcase` in the dev profile runs with validation on a machine that has no Vulkan SDK, and touches nothing on the host.
Sunrisepeak
force-pushed
the
pr/mcpp-build-support
branch
from
September 13, 2026 08:20
7471ad4 to
152f0c0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part A / 3(Part B:#10 文档,Part C:#12 resize 崩溃修复)。第二条构建链,与 xmake 并存;基于上游 master(
base/upstream-master=6d63715),16 个 commit,按「上游能单独采纳哪一段」拆。commit 与对 xmake 的影响
fix(msvc)refactorXRGUI_FUCK_MSVC_INCLUDE_CPP_HEADER_IN_MODULEbuildciportmo_yanxi.views/mo_yanxi.functional)加进 xmake 的源码集xmake.lua一行add_files;源码改动对 MSVC 等价fix(vulkan)VK_KHR_maintenance9:树里没有任何使用,而它让 Linux 上所有设备都被拒fix(glfw)vk::context在首帧 present 后显示(两条 present 路径都调);之前 ~650 ms 是一块没画过的矩形build(mcpp)mcpp.toml、build.mcpp、mcpp/下三个 submodule 的 path 包和补丁、图标工具mcpp/svg_outline、Windows 图标render_context.cpp/ showcasemain.cpp里XRGUI_SHADER_SURFACE的#else分支是原代码ci(mcpp)mcpp-windows.yml(两条腿:机器上的 VS、mcpp 自装的 toolset)、mcpp-linux.ymlport(macos)rect_ortho.ixx的 SSE 代码在补丁里得到标量回退;SDKassert()里的__builtin_expect被 clang 22 在模块之间报成歧义,mcpp/darwin/assert.h影子掉它(build.mcpp只在 macOS 加这个-I);cxx_runtime = "host-coupled"从全局收窄到 MSVC 三元组(仍是/MD),Linux / macOS 用默认值静态链接工具链的 libc++ci(mcpp)llvm@22.1.8testsrc.tests/改为 mcpp 约定的tests/,每个文件一个程序,mcpp test直接跑;gtest 走[dev-dependencies],mainfeature 即 gtest_main,共用的main.cpp删掉,xrgui_teststarget 和testsfeature 一并删掉xmake.lua:add_files("tests/**.cpp"),gtest 加main = true拿同一个入口fix(graphic)instruction_buffer的四个访问器去掉CONST_FN([[gnu::const]]):它们读storage_,clang -O2 把 resize 前的data()复用到 resize 后,showcase 首个 draw push 写空指针。MSVC 上这个宏为空,所以那边从未暴露refactor(cfg)render_context::load_shader(name)成为取 xrgui 自己着色器的唯一入口:XRGUI_SHADER_SURFACE下读编入的数组,否则读.spv;renderer bundle 和 showcase 都走它,showcase 的main.cpp不再碰宏和生成头,才能作为独立包(成员、任何消费者)构建.spv)build(mcpp)src.hello、src.examples就是 workspace 成员(各自目录里一份mcpp.toml,入口还是原来的main.cpp,没有文件搬家),path 依赖 xrgui:mcpp run -p src.hello/-p src.examples、mcpp build --workspace、成员目录下mcpp pack。bin target、图标、Windows 子系统从根 manifest 移到成员;examplesfeature 保留,由 showcase 成员请求,仍排除成员的main.cpp;成员各带 release 的NDEBUG(profile 不继承)build(mcpp)[target.linux.xlings.workspace]声明xim:vulkan-validation-layers(when = "run",只在mcpp run/mcpp test时安装,不进产物,Linux 上有这个包);mcpp run -p src.examples不再依赖机器上的 Vulkan SDK,也不加载宿主的 layer本地验证(Linux,clang 22):
mcpp build --workspace、mcpp test(5 个程序 54 个用例)、成员目录下mcpp pack(tar、AppImage)都通过;mcpp run -p src.hello和mcpp run -p src.examples --release都开窗渲染(showcase 截图确认,FPS 3500+)。[profile.release]加了-DNDEBUG,和 xmake 的 mode.release 一致,showcase 的 validation layer 开关靠它。已知(不在本 PR 修):showcase 拖动窗口大小时约一半概率
VK_ERROR_DEVICE_LOST,根因是context::get_extent()用 GLFW 缓存的窗口尺寸而不是 swapchain 尺寸,修复在 Part C(#12)。另外 sync validation 报 renderer 上传路径vkCmdCopyBuffer之间的 WRITE_AFTER_WRITE,以及 compositor 里vkCmdSetEvent2用了需要 maintenance8 的dependencyFlags(本机驱动不支持该扩展),都是上游可以单独看的。Review 后的收紧(本轮):
port提交里两处运行期改动拆成自己的 commit(第 6、7 行);源码里的注释压缩到说明"哪个编译器、报什么、为什么是这个形状"的几句(-270 行);mcpp-windows.yml从 448 行减到 190 行,去掉了历史叙述、PYTHONUTF8和一步手动安装的 Vulkan SDK(compat.vulkan已经提供);build.mcpp的文件头和一处过期路径更正,补丁文件缺失时报错而不是静默;path 包 manifest 里 23 行的历史注释压到 5 行。mcpp 这条链的形状:机器上只装 mcpp,编译器、Vulkan、Slang、每个第三方库由
mcpp.toml声明并自动提供;着色器由mcpp.rules.slang逐个编成构建边并嵌入二进制;图标由仓库自带的 C++ 工具做几何展开(替代原来 python + node + potrace 描摹);运行期数据、Windows 图标、GUI 子系统、AppImage / MSI 打包都是 manifest 里的数据。build.mcpp只做 mcpp 没有对应键的事(submodule 补丁、图标汇总头)。平台:Windows / MSVC 14.52 是参考;Linux / clang 22 构建、54 个测试通过、tar 和 AppImage 产出;macOS(arm64,同一个 clang)构建、54 个测试通过;
src/platform/的__APPLE__分支(CoreText、线程名)是原代码,port 见第 11 行;打包暂不做(mcpp 内建的闭包遍历还不处理 Mach-O 程序)。CI:四个 mcpp job(Windows 两腿、Linux、macOS)加上游的 xmake job 都要绿。
已知:Windows 上 mcpp 构建的 GUI 程序是
/SUBSYSTEM:WINDOWS,stdout 不再接终端。从仓库外把 xrgui 作为 path 依赖消费时,clang 下会碰到 mcpp 的一个引擎缺陷(依赖的module_extensions没有用于扫描边),已单独跟进,与本仓无关。