|
1 | 1 | -- M6.x glob-aware Form B descriptor for FTXUI 6.1.9 and 7.0.3. |
2 | 2 | -- |
3 | | --- Pure C++ library (no C++23 modules); compiled sources + public headers. |
| 3 | +-- Compiled sources + public headers by default; 7.0.3 additionally offers |
| 4 | +-- upstream's named modules behind the opt-in `modules` feature (see below). |
4 | 5 | -- Uses mcpp 0.0.4's glob exclusion (`!` prefix) to skip the |
5 | 6 | -- *_test.cpp / *_fuzzer.cpp files that live alongside the library |
6 | 7 | -- sources in the same directories (6.1.9: ~30 test / ~16 fuzzer; |
|
14 | 15 | -- FTXUI_BUILD_MODULES, off by default); the `*.cpp` globs never match them, |
15 | 16 | -- and the plain .cpp sources still compile header-only style. |
16 | 17 | -- |
| 18 | +-- The `modules` feature (7.0.3+) |
| 19 | +-- ------------------------------ |
| 20 | +-- 7.x ships upstream's own named modules — an `ftxui` umbrella that |
| 21 | +-- `export import`s four sub-modules (ftxui.component/.dom/.screen/.util), |
| 22 | +-- each of which textually includes the matching public headers in its global |
| 23 | +-- module fragment. `features.modules` adds exactly the five files upstream's |
| 24 | +-- cmake/ftxui_modules.cmake lists, so `import ftxui;` becomes available |
| 25 | +-- without touching the header surface: the module units carry no definitions |
| 26 | +-- of their own (they are `export namespace ftxui { using ... }` re-exports), |
| 27 | +-- so they layer ON TOP of the same libftxui.a the default build produces. |
| 28 | +-- Both surfaces coexist in one archive; a consumer picks either. |
| 29 | +-- |
| 30 | +-- OFF BY DEFAULT — but NOT because the units fail to build. They build and |
| 31 | +-- run under gcc 16.1.0 and llvm 22.1.8 alike, verified on the mcpp version CI |
| 32 | +-- pins. The reason is cost and choice: the module surface is five extra TUs |
| 33 | +-- and their BMIs that no header consumer of 7.0.3 should pay for unasked, |
| 34 | +-- upstream itself defaults FTXUI_BUILD_MODULES to OFF, and there is a |
| 35 | +-- consumer-side constraint below that only the consumer can honour. |
| 36 | +-- |
| 37 | +-- ⚠️ THE CONSTRAINT IS IN THE CONSUMER'S TU, NOT IN THIS PACKAGE, AND #292 |
| 38 | +-- IS WHY IT IS WORTH SPELLING OUT. Because each sub-module puts the public |
| 39 | +-- headers — and transitively libstdc++ — into a global module fragment, a |
| 40 | +-- consumer TU that writes `import ftxui;` and ALSO textually `#include`s a |
| 41 | +-- standard header hands gcc two copies of the standard library's |
| 42 | +-- declarations. gcc 16 refuses, at volume: |
| 43 | +-- |
| 44 | +-- c++config.h:355:15: error: redefinition of 'void std::__terminate()' |
| 45 | +-- memoryfwd.h:68:11: error: conflicting declaration of template |
| 46 | +-- 'template<class> struct std::allocator' |
| 47 | +-- stringfwd.h:55:12: error: conflicting declaration of template |
| 48 | +-- 'template<class _CharT> struct std::char_traits' |
| 49 | +-- |
| 50 | +-- That is exactly what sank #292's first attempt at this. Its smoke TU wrote |
| 51 | +-- `import ftxui;` above `#include <string>` and `#include <gtest/gtest.h>`, |
| 52 | +-- and the linux gcc leg died on those three errors (and ~16k more) while |
| 53 | +-- llvm, macOS and windows stayed green — clang accepts the mixed TU. The one |
| 54 | +-- object that failed in that run was the smoke TU's own (`obj/module.o`); the |
| 55 | +-- package's five module units had already compiled. |
| 56 | +-- |
| 57 | +-- A consumer that stays ON the module surface — `import std;` beside |
| 58 | +-- `import ftxui;`, no textual includes, the discipline tests/examples/ |
| 59 | +-- asio-module already documents — builds clean on both compilers. That is |
| 60 | +-- what tests/examples/ftxui-module asserts, and it is why that member can run |
| 61 | +-- on both of CI's linux legs rather than needing a toolchain pin. |
| 62 | +-- |
| 63 | +-- Upstream's own module CI is llvm-only (`test_modules` in |
| 64 | +-- .github/workflows/build.yaml: a one-entry ubuntu + llvm matrix carrying |
| 65 | +-- `# TODO add gcc / msvc`), and ftxui_modules.cmake still forces |
| 66 | +-- `-fmodules-ts` under CMAKE_COMPILER_IS_GNUCXX above a bare |
| 67 | +-- `# TODO: Explain why this is needed.`. So gcc is UNTESTED upstream — worth |
| 68 | +-- knowing before trusting the combination far — but, as measured here, it is |
| 69 | +-- not broken. |
| 70 | +-- |
| 71 | +-- On 6.1.9 the feature's glob matches nothing (no .cppm before 7.0.0), which |
| 72 | +-- is a warning rather than an error — the same union-of-layouts tolerance |
| 73 | +-- compat.catch2 and compat.redis-plus-plus rely on. `modules` below is the |
| 74 | +-- declared export set, in the same spelling every other module package in |
| 75 | +-- this index uses. Note what it does NOT buy here: mcpp validates |
| 76 | +-- `[modules].exports` against the scanner only for the PRIMARY manifest of a |
| 77 | +-- build, so a DEPENDENCY's list is never checked — measured by deleting |
| 78 | +-- `ftxui.util` from it and rebuilding with the package cache bypassed, which |
| 79 | +-- built and passed. It is documentation and metadata, not a guard. |
| 80 | +-- |
17 | 81 | -- ONE version skew the globs cannot express (no per-version build blocks, |
18 | 82 | -- mcpp-community/mcpp#290): FTXUI 7 moved Loop's method definitions from |
19 | 83 | -- loop.cpp into app.cpp and dropped loop.cpp from the CMake build, but the |
@@ -98,6 +162,40 @@ package = { |
98 | 162 | "!*/src/ftxui/**/*_fuzzer.cpp", -- fuzz targets (16 in 6.1.9, 6 in 7.0.3) |
99 | 163 | }, |
100 | 164 | targets = { ["ftxui"] = { kind = "lib" } }, |
| 165 | + -- The export set of the `modules` feature, in the spelling every other |
| 166 | + -- module package in this index uses. Documentation and metadata only: |
| 167 | + -- mcpp checks `[modules].exports` against the scanner for the PRIMARY |
| 168 | + -- manifest of a build, never for a dependency's, so nothing here is |
| 169 | + -- enforced at a consumer's build (measured — see the header comment). |
| 170 | + -- Order follows upstream's ftxui_modules.cmake. |
| 171 | + modules = { |
| 172 | + "ftxui", |
| 173 | + "ftxui.component", |
| 174 | + "ftxui.dom", |
| 175 | + "ftxui.screen", |
| 176 | + "ftxui.util", |
| 177 | + }, |
| 178 | + features = { |
| 179 | + -- Upstream's five module units, verbatim from |
| 180 | + -- cmake/ftxui_modules.cmake. `*.cppm` cannot collide with the base |
| 181 | + -- `**/*.cpp` globs (different extension), so this is a pure |
| 182 | + -- ADDITION — no `!` exclusion is involved and the base source set |
| 183 | + -- is untouched whether the feature is on or off. That matters: |
| 184 | + -- a `!` exclusion in mcpp is global and would out-rank a feature |
| 185 | + -- entry naming the same file, so "exclude in base, add back in the |
| 186 | + -- feature" is not an expressible shape. |
| 187 | + -- |
| 188 | + -- No `include_dirs` here (features cannot carry them, and none is |
| 189 | + -- needed): the GMF `#include <ftxui/...>` resolve through the |
| 190 | + -- package-level `*/include`, which mcpp applies to the package's |
| 191 | + -- own TUs as well as to consumers. |
| 192 | + -- |
| 193 | + -- Consumer-side rule, gcc only: don't mix `import ftxui;` with a |
| 194 | + -- textual `#include` in one TU. See the header comment. |
| 195 | + ["modules"] = { |
| 196 | + sources = { "*/src/ftxui/*.cppm" }, |
| 197 | + }, |
| 198 | + }, |
101 | 199 | deps = { }, |
102 | 200 | windows = { |
103 | 201 | cxxflags = { "-DUNICODE", "-D_UNICODE" }, |
|
0 commit comments