Skip to content

fix: prevent stale installed FTXUI headers from shadowing build sources - #1300

Merged
ArthurSonzogni merged 3 commits into
mainfrom
fix/cmake-header-shadowing-1299
Jun 27, 2026
Merged

fix: prevent stale installed FTXUI headers from shadowing build sources#1300
ArthurSonzogni merged 3 commits into
mainfrom
fix/cmake-header-shadowing-1299

Conversation

@ArthurSonzogni

Copy link
Copy Markdown
Owner

Fixes #1299

Problem

When building FTXUI from source (e.g. a MacPorts package upgrade), an older installed version of FTXUI can shadow the headers being built, producing errors like:

error: no member named 'CellAt' in 'ftxui::Screen'
error: no viable conversion from '(lambda)(Cell&)' to 'SelectionStyle' (aka 'std::function<void (Pixel &)>')

Root cause — CMake include-directory deduplication

ftxui_set_options() exported include/ as SYSTEM INTERFACE for BUILD_INTERFACE. This created a propagation chain:

  1. screen adds include/ to its INTERFACE_SYSTEM_INCLUDE_DIRECTORIES.
  2. dom and component link against screen (PUBLIC), so they inherit include/ in their own SYSTEM_INCLUDE_DIRECTORIES.
  3. CMake deduplicates: a path present in both INCLUDE_DIRECTORIES (from the PRIVATE rule) and SYSTEM_INCLUDE_DIRECTORIES (from propagation) is emitted once, as -isystem.
  4. Clang/GCC search all -I paths before any -isystem path, regardless of command-line order.
  5. Package managers such as MacPorts inject -I/opt/local/include via CMAKE_CXX_FLAGS. With an older FTXUI installed there, its headers are found first.

Fix

When FTXUI is the top-level CMake project (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME), the BUILD_INTERFACE include is exported as a plain INTERFACE (dropping SYSTEM). This breaks the propagation chain so every FTXUI target keeps its own include/ as a regular -I path, which is searched before any system path injected by the build environment.

Behaviour matrix

Scenario Before After
Building FTXUI itself (source/package build) -isystem — stale headers can win -I — project headers always win ✓
add_subdirectory / FetchContent consumer -isystem — no warnings -isystem — no warnings ✓
find_package consumer (installed FTXUI) -isystem — no warnings -isystem — no warnings ✓

The goal of suppressing warnings in consumer code is fully preserved.

Fixes #1299

## Previous behaviour

`ftxui_set_options()` exported the project `include/` directory as
`SYSTEM INTERFACE` for `BUILD_INTERFACE`.  This had an unintended
side-effect when building FTXUI itself:

- `screen` propagated `include/` into `dom`'s (and `component`'s)
  `INTERFACE_SYSTEM_INCLUDE_DIRECTORIES`.
- CMake deduplicates: a path that appears in both `INCLUDE_DIRECTORIES`
  (from the `PRIVATE` rule) and `SYSTEM_INCLUDE_DIRECTORIES` (from the
  propagation above) is emitted **once, as `-isystem`**.
- Clang/GCC search all `-I` paths before any `-isystem` path.  Package
  managers such as MacPorts inject `-I/opt/local/include` via
  `CMAKE_CXX_FLAGS`.  If an older FTXUI is already installed there, its
  headers are found first, causing the build to fail with errors like
  "no member named 'CellAt' in 'ftxui::Screen'".

## New behaviour

When FTXUI is the **top-level CMake project** (i.e. being built from
source, not consumed via `add_subdirectory`/`FetchContent`), the
`BUILD_INTERFACE` include is exported as a plain `INTERFACE` (no
`SYSTEM`).  This prevents the SYSTEM propagation chain, so every FTXUI
target keeps its own `include/` as a regular `-I` path that is searched
before any system `-I` injected by the build environment.

When FTXUI is **consumed** via `add_subdirectory` or `FetchContent`,
the `SYSTEM INTERFACE` behaviour is retained, so downstream consumers
continue to receive FTXUI headers as `-isystem` and do not see spurious
warnings.

The `INSTALL_INTERFACE` (used when FTXUI is found via `find_package`)
is unchanged and remains `SYSTEM`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

⚠️ ABI Compatibility Report

Comparing main (base) with HEAD (PR)

ABI fingerprints changed from d0578d99d54909d813dd510a85d45a4a1c1f0d7e8f179b0eac88c644218de938 to c41901d6a4da49c7eec689a174eb1f30c2994f8c54799cc1f60e60a24985001f.

Detailed ABI Analysis
Checking ABI changes between origin/main and HEAD...
Building origin/main...
Building HEAD...
--------------------------------------------------------------------------------
Comparing libftxui-screen.so...
No ABI changes detected for libftxui-screen.so.
--------------------------------------------------------------------------------
Comparing libftxui-dom.so...
No ABI changes detected for libftxui-dom.so.
--------------------------------------------------------------------------------
Comparing libftxui-component.so...
No ABI changes detected for libftxui-component.so.
--------------------------------------------------------------------------------
No ABI changes detected.

ArthurSonzogni and others added 2 commits June 27, 2026 19:42
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nd Screen

Clang's -Wdeprecated-copy-with-dtor fires when a class declares a
destructor but relies on the implicitly-generated copy constructor and
copy assignment operator. Explicitly defaulting them silences the
warning and makes the intent clear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ArthurSonzogni
ArthurSonzogni merged commit 9519806 into main Jun 27, 2026
21 checks passed
@ArthurSonzogni
ArthurSonzogni deleted the fix/cmake-header-shadowing-1299 branch June 27, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7.0.0 fails to build on macOS with clang / libc++: bold.cpp: error: no member named 'CellAt' in 'ftxui::Screen' etc.

1 participant