Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Produce a winrt-specific types library to hold some of our WinRT helpers without cluttering conhost #2146

Closed
DHowett-MSFT opened this issue Jul 30, 2019 · 0 comments · Fixed by #3350
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Issue-Task It's a feature request, but it doesn't really need a major design. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal. Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Milestone

Comments

@DHowett-MSFT
Copy link
Contributor

  • Things like ScopedResourceLoader would go in there.
  • It would provide a central place for the cppwinrt_utils header and friends to live (and an include path :P)
@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jul 30, 2019
@DHowett-MSFT DHowett-MSFT added Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Issue-Task It's a feature request, but it doesn't really need a major design. Product-Terminal The new Windows Terminal. labels Jul 30, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Jul 30, 2019
@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Jul 30, 2019
DHowett-MSFT pushed a commit that referenced this issue Oct 28, 2019
This commit introduces a C++/WinRT utility library and moves
ScopedResourceLoader into it. I decided to get uppity and introduce
something I like to call "checked resources." The idea is that every
resource reference from a library is knowable at compile time, and we
should be able to statically ensure that all resources exist.

This is a system that lets us immediately failfast (on launch) when a
library makes a static reference to a resource that doesn't exist at
runtime.

Resource checking relies on diligent use of USES_RESOURCE() and RS_()
(which uses USES_RESOURCE), but can make sure we don't ship something
that'll blow up at runtime.

USES_RESOURCE(L"key") should be used when a resource name is needed
but will not be immediately used. RS_(L"key") is intended for immediate
resource extraction.

It works like this:
** IN DEBUG MODE **
- All resource names referenced through USES_RESOURCE() are emitted
  alongside their referencing filenames and line numbers into a static
  section of the binary.
  That section is named .util$res$m.

- We emit two sentinel values into two different sections, .util$res$a
  and .util$res$z.

- The linker sorts all sections alphabetically before crushing them
  together into the final binary.

- When we first construct a library's scoped resource loader, we
  iterate over every resource reference between $a and $z and check
  residency.

** IN RELEASE MODE **
- All checked resource code is compiled out.

Fixes #2146.
@ghost ghost added the In-PR This issue has a related PR label Oct 28, 2019
DHowett-MSFT pushed a commit that referenced this issue Oct 28, 2019
This commit introduces a C++/WinRT utility library and moves
ScopedResourceLoader into it. I decided to get uppity and introduce
something I like to call "checked resources." The idea is that every
resource reference from a library is knowable at compile time, and we
should be able to statically ensure that all resources exist.

This is a system that lets us immediately failfast (on launch) when a
library makes a static reference to a resource that doesn't exist at
runtime.

It exposes two new (preprocessor) APIs:
* RS_(wchar_t): loads a localizable string resource by name.
* USES_RESOURCE(wchar_t): marks a resource key as used, but is intended
  for loading images or passing static resource keys as parameters to
  functions that will look them up later.

Resource checking relies on diligent use of USES_RESOURCE() and RS_()
(which uses USES_RESOURCE), but can make sure we don't ship something
that'll blow up at runtime.

It works like this:
** IN DEBUG MODE **
- All resource names referenced through USES_RESOURCE() are emitted
  alongside their referencing filenames and line numbers into a static
  section of the binary.
  That section is named .util$res$m.

- We emit two sentinel values into two different sections, .util$res$a
  and .util$res$z.

- The linker sorts all sections alphabetically before crushing them
  together into the final binary.

- When we first construct a library's scoped resource loader, we
  iterate over every resource reference between $a and $z and check
  residency.

** IN RELEASE MODE **
- All checked resource code is compiled out.

Fixes #2146.
DHowett-MSFT pushed a commit that referenced this issue Oct 28, 2019
This commit introduces a C++/WinRT utility library and moves
ScopedResourceLoader into it. I decided to get uppity and introduce
something I like to call "checked resources." The idea is that every
resource reference from a library is knowable at compile time, and we
should be able to statically ensure that all resources exist.

This is a system that lets us immediately failfast (on launch) when a
library makes a static reference to a resource that doesn't exist at
runtime.

It exposes two new (preprocessor) APIs:
* RS_(wchar_t): loads a localizable string resource by name.
* USES_RESOURCE(wchar_t): marks a resource key as used, but is intended
  for loading images or passing static resource keys as parameters to
  functions that will look them up later.

Resource checking relies on diligent use of USES_RESOURCE() and RS_()
(which uses USES_RESOURCE), but can make sure we don't ship something
that'll blow up at runtime.

It works like this:
** IN DEBUG MODE **
- All resource names referenced through USES_RESOURCE() are emitted
  alongside their referencing filenames and line numbers into a static
  section of the binary.
  That section is named .util$res$m.

- We emit two sentinel values into two different sections, .util$res$a
  and .util$res$z.

- The linker sorts all sections alphabetically before crushing them
  together into the final binary.

- When we first construct a library's scoped resource loader, we
  iterate over every resource reference between $a and $z and check
  residency.

** IN RELEASE MODE **
- All checked resource code is compiled out.

Fixes #2146.
DHowett-MSFT pushed a commit that referenced this issue Oct 28, 2019
This commit introduces a C++/WinRT utility library and moves
ScopedResourceLoader into it. I decided to get uppity and introduce
something I like to call "checked resources." The idea is that every
resource reference from a library is knowable at compile time, and we
should be able to statically ensure that all resources exist.

This is a system that lets us immediately failfast (on launch) when a
library makes a static reference to a resource that doesn't exist at
runtime.

It exposes two new (preprocessor) APIs:
* RS_(wchar_t): loads a localizable string resource by name.
* USES_RESOURCE(wchar_t): marks a resource key as used, but is intended
  for loading images or passing static resource keys as parameters to
  functions that will look them up later.

Resource checking relies on diligent use of USES_RESOURCE() and RS_()
(which uses USES_RESOURCE), but can make sure we don't ship something
that'll blow up at runtime.

It works like this:
** IN DEBUG MODE **
- All resource names referenced through USES_RESOURCE() are emitted
  alongside their referencing filenames and line numbers into a static
  section of the binary.
  That section is named .util$res$m.

- We emit two sentinel values into two different sections, .util$res$a
  and .util$res$z.

- The linker sorts all sections alphabetically before crushing them
  together into the final binary.

- When we first construct a library's scoped resource loader, we
  iterate over every resource reference between $a and $z and check
  residency.

** IN RELEASE MODE **
- All checked resource code is compiled out.

Fixes #2146.
DHowett-MSFT pushed a commit that referenced this issue Nov 1, 2019
This commit introduces a C++/WinRT utility library and moves
ScopedResourceLoader into it. I decided to get uppity and introduce
something I like to call "checked resources." The idea is that every
resource reference from a library is knowable at compile time, and we
should be able to statically ensure that all resources exist.

This is a system that lets us immediately failfast (on launch) when a
library makes a static reference to a resource that doesn't exist at
runtime.

It exposes two new (preprocessor) APIs:
* `RS_(wchar_t)`: loads a localizable string resource by name.
* `USES_RESOURCE(wchar_t)`: marks a resource key as used, but is intended
  for loading images or passing static resource keys as parameters to
  functions that will look them up later.

Resource checking relies on diligent use of `USES_RESOURCE()` and `RS_()`
(which uses `USES_RESOURCE`), but can make sure we don't ship something
that'll blow up at runtime.

It works like this:

**IN DEBUG MODE**
- All resource names referenced through `USES_RESOURCE()` are emitted
  alongside their referencing filenames and line numbers into a static
  section of the binary.
  That section is named `.util$res$m`.

- We emit two sentinel values into two different sections, `.util$res$a`
  and `.util$res$z`.

- The linker sorts all sections alphabetically before crushing them
  together into the final binary.

- When we first construct a library's scoped resource loader, we
  iterate over every resource reference between `$a` and `$z` and check
  residency.

**IN RELEASE MODE**
- All checked resource code is compiled out.

Fixes #2146.

Macros are the only way to do something this cool, incidentally.

## Validation Steps Performed
Made references to a bunch of bad resources, tried to break it a lot.

It looks like this when it fails:

### App.cpp
```
36  static const std::array<std::wstring_view, 2> settingsLoadErrorsLabels {
37      USES_RESOURCE(L"NoProfilesText"),
38      USES_RESOURCE(L"AllProfilesHiddenText_HA_JUST_KIDDING")
39  };
```

```
WinRTUtils\LibraryResources.cpp(68)\TerminalApp.dll:
    FailFast(1) tid(1034) 8000FFFF Catastrophic failure
    Msg:[Resource AllProfilesHiddenText_HA_JUST_KIDDING not found in
      scope TerminalApp/Resources (App.cpp:38)] [EnsureAllResourcesArePresent]
```
@ghost ghost added Needs-Tag-Fix Doesn't match tag requirements Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Nov 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-CodeHealth Issues related to code cleanliness, linting, rules, warnings, errors, static analysis, etc. Issue-Task It's a feature request, but it doesn't really need a major design. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal. Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant