[PR #10361] [MERGED] Add support for branch- and branding-based feature flagging #28008

Open
opened 2026-01-31 09:25:44 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/10361
Author: @DHowett
Created: 6/8/2021
Status: Merged
Merged: 6/11/2021
Merged by: @undefined

Base: mainHead: dev/duhowett/jerk


📝 Commits (10+)

  • d44ee40 JERK
  • d8525bc Document!
  • 2e8c95f schema and gen: fix token uniques, check for cplusplus
  • 67c6403 rule: convert to a forced include
  • a6b6032 Don't try to add it to the solution.
  • 0a0da67 spaces, not tabs, yo
  • d743af0 Automatically recalculate when the branch/branding change!
  • 8a10a63 Try very hard to avoid rebuilds when branch is changeD
  • f254eeb Use an example feature file for now.
  • ce4d7bb Speelbot

📊 Changes

8 files changed (+484 additions, -0 deletions)

View changed files

📝 .github/actions/spelling/allow/apis.txt (+2 -0)
📝 .github/actions/spelling/expect/expect.txt (+1 -0)
build/rules/GenerateFeatureFlags.proj (+97 -0)
doc/feature_flags.md (+65 -0)
📝 src/common.build.post.props (+17 -0)
src/features.xml (+13 -0)
tools/FeatureStagingSchema.xsd (+83 -0)
tools/Generate-FeatureStagingHeader.ps1 (+206 -0)

📄 Description

This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).

It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.

It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.

Features are added to src\features.xml and marked with a "stage". For
now, the only stages available are AlwaysDisabled and AlwaysEnabled.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.

For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:

  1. A preprocessor define TIL_FEATURE_XYZ_ENABLED (usable from MIDL,
    C++ and C)
  2. A feature class type Feature_XYZ with a static constexpr member
    IsEnabled() (usable from C++, designed for if constexpr()).

Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to if constexpr (false). :)

Michael suggested that we could use WindowsInbox as a branding to
determine when we were being built inside Windows to supplant our use of
the __INSIDE_WINDOWS preprocessor token. It was brilliant.

Design Decisions

  • Emitting the header as part of an MSBuild project
    • WHY: This allows the MSBuild engine to ensure that the build is
      only run once, even in a parallel build situation.
  • Only having one feature flag document for the entire project
    • WHY: Ease.
  • Forcibly including TilFeatureStaging with /FI for all CL compiler
    invocations.
    • WHY: If this is a project-wide feature system, we should make it as
      easy as possible to use.
  • Emitting preprocessor definitions instead of constexpr/consteval
    • WHY: Removing entire functions/includes is impossible with if constexpr.
    • WHY: MIDL cannot use a static constexpr bool, but it can rely on
      the C preprocessor to remove text.
  • Using MSBuild to emit the text instead of PowerShell
    • WHY: This allows us to leverage MSBuild's WriteOnlyWhenDifferent
      task parameter to avoid changing the file's modification time when
      it would have resulted in the same contents. This lets us use the
      same FeatureStaging header across multiple builds and multiple
      branches and brandings assuming that they do not result in a
      feature flag change
      .
    • The risk in using a force-include is always that it, for some
      reason, determines that the entire project is out of date. We've
      gone to great lengths to make sure that it only does so if the
      features actually materially changed.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/10361 **Author:** [@DHowett](https://github.com/DHowett) **Created:** 6/8/2021 **Status:** ✅ Merged **Merged:** 6/11/2021 **Merged by:** [@undefined](undefined) **Base:** `main` ← **Head:** `dev/duhowett/jerk` --- ### 📝 Commits (10+) - [`d44ee40`](https://github.com/microsoft/terminal/commit/d44ee40cc07ede676a7972d993830efa2ea18048) JERK - [`d8525bc`](https://github.com/microsoft/terminal/commit/d8525bc5efbf018854362b1f1fb3af34b24d6c01) Document! - [`2e8c95f`](https://github.com/microsoft/terminal/commit/2e8c95f31c254f325ad494737b773ae998f020c0) schema and gen: fix token uniques, check for cplusplus - [`67c6403`](https://github.com/microsoft/terminal/commit/67c6403eae7b7bacef2eb7e6bd74324704ba6a19) rule: convert to a forced include - [`a6b6032`](https://github.com/microsoft/terminal/commit/a6b6032adf764b8243db8863514658afce90ceab) Don't try to add it to the solution. - [`0a0da67`](https://github.com/microsoft/terminal/commit/0a0da6793bcb5a641492e2713bc026e4c0f88fd7) spaces, not tabs, yo - [`d743af0`](https://github.com/microsoft/terminal/commit/d743af011e838bb51f9823254d468495122a5eb6) Automatically recalculate when the branch/branding change! - [`8a10a63`](https://github.com/microsoft/terminal/commit/8a10a63c944304bd2835582119e59662ac59c8f4) Try very hard to avoid rebuilds when branch is changeD - [`f254eeb`](https://github.com/microsoft/terminal/commit/f254eeb1885320ac22c0bd8e680a852c71f1f05a) Use an example feature file for now. - [`ce4d7bb`](https://github.com/microsoft/terminal/commit/ce4d7bbb76bd65fba3da74f339bfa4152027a425) Speelbot ### 📊 Changes **8 files changed** (+484 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `.github/actions/spelling/allow/apis.txt` (+2 -0) 📝 `.github/actions/spelling/expect/expect.txt` (+1 -0) ➕ `build/rules/GenerateFeatureFlags.proj` (+97 -0) ➕ `doc/feature_flags.md` (+65 -0) 📝 `src/common.build.post.props` (+17 -0) ➕ `src/features.xml` (+13 -0) ➕ `tools/FeatureStagingSchema.xsd` (+83 -0) ➕ `tools/Generate-FeatureStagingHeader.ps1` (+206 -0) </details> ### 📄 Description This pull request implements a "feature flagging" system that will let us turn Terminal and conhost features on/off by branch, "release" status or branding (Dev, Preview, etc.). It's loosely modelled after the Windows OS concept of "Velocity," but only insofar as it is driven by an XML document and there's a tool that emits a header file for you to include. It only supports toggling features at compile time, and the feature flag evaluators are intended to be fully constant expressions. Features are added to `src\features.xml` and marked with a "stage". For now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`. Features can be toggled to different states using branch and branding tokens, as documented in the included feature flag docs. For a given feature Feature_XYZ, we will emit two fixtures visible to the compiler: 1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL, C++ and C) 2. A feature class type `Feature_XYZ` with a static constexpr member `IsEnabled()` (usable from C++, designed for `if constexpr()`). Like Velocity, we rely on the compiler to eliminate dead code caused by things that compile down to `if constexpr (false)`. :) Michael suggested that we could use `WindowsInbox` as a branding to determine when we were being built inside Windows to supplant our use of the `__INSIDE_WINDOWS` preprocessor token. It was brilliant. Design Decisions ---------------- * Emitting the header as part of an MSBuild project * WHY: This allows the MSBuild engine to ensure that the build is only run once, even in a parallel build situation. * Only having one feature flag document for the entire project * WHY: Ease. * Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler invocations. * WHY: If this is a project-wide feature system, we should make it as easy as possible to use. * Emitting preprocessor definitions instead of constexpr/consteval * WHY: Removing entire functions/includes is impossible with `if constexpr`. * WHY: MIDL cannot use a `static constexpr bool`, but it can rely on the C preprocessor to remove text. * Using MSBuild to emit the text instead of PowerShell * WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent` task parameter to avoid changing the file's modification time when it would have resulted in the same contents. This lets us use the same FeatureStaging header across multiple builds and multiple branches and brandings _assuming that they do not result in a feature flag change_. * The risk in using a force-include is always that it, for some reason, determines that the entire project is out of date. We've gone to great lengths to make sure that it only does so if the features _actually materially changed_. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:25:44 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#28008