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

WindowsPackageType=None in a class library includes the bootstrapper #2456

Closed
mattleibow opened this issue May 3, 2022 · 4 comments
Closed
Assignees
Labels
area-DynamicDependencies area-Infrastructure Build, test, source layout, package construction (TODO: move to Deployment, DeveloperTools) bug Something isn't working
Milestone

Comments

@mattleibow
Copy link

Describe the bug

If you set the the package type in a class library, then the build adds the bootstrapper to the class library:

<WindowsPackageType>None</WindowsPackageType>

This is because the condition to include the bootstrapper is very loose:

<PropertyGroup Condition="'$(WindowsAppSdkBootstrapInitialize)'=='' and '$(WindowsAppSDKSelfContained)'!='true' and '$(WindowsPackageType)'=='None'">

A workaround is to also set the WindowsAppSdkBootstrapInitialize property:

<WindowsAppSdkBootstrapInitialize Condition=" '$(WindowsAppSdkBootstrapInitialize)' == '' and '$(OutputType)' != 'Exe' and '$(OutputType)' != 'WinExe' ">false</WindowsAppSdkBootstrapInitialize>

Steps to reproduce the bug

  1. File | New | WinUI class library
  2. Set WindowsPackageType=None
  3. Build
  4. Inspect dll and observe bootstrapper

Expected behavior

No bootstrapper

Screenshots

No response

NuGet package version

1.0.0

Packaging type

No response

Windows version

No response

IDE

No response

Additional context

I noticed this when several libraries referenced each other:

C:\Users\mattl.nuget\packages\microsoft.windowsappsdk\1.0.2\include\MddBootstrapAutoInitializer.cs(11,38): warning CS0436: The type 'Release' in 'C:\Users\mattl.nuget\packages\microsoft.windowsappsdk\1.0.2\buildTransitive..\include\WindowsAppSDK-VersionInfo.cs' conflicts with the imported type 'Release' in 'SkiaSharp.Views.Maui.Controls, Version=2.88.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\Users\mattl.nuget\packages\microsoft.windowsappsdk\1.0.2\buildTransitive..\include\WindowsAppSDK-VersionInfo.cs'. [C:\Projects\SkiaSharp\source\SkiaSharp.Views.Maui\SkiaSharp.Views.Maui.Controls.Compatibility\SkiaSharp.Views.Maui.Controls.Compatibility.csproj]

@ghost ghost added the needs-triage label May 3, 2022
@DrusTheAxe DrusTheAxe added area-Infrastructure Build, test, source layout, package construction (TODO: move to Deployment, DeveloperTools) area-DynamicDependencies labels May 3, 2022
@DrusTheAxe DrusTheAxe added this to the 1.1 milestone May 3, 2022
@DrusTheAxe DrusTheAxe added bug Something isn't working and removed needs-triage labels May 3, 2022
@DrusTheAxe
Copy link
Member

DrusTheAxe commented May 3, 2022

Interesting. Yes I think you're right. Narrowing the default to also check for OutputType = Exe or WinExe should be more correct. Thanks for the feedback!

I've added this to my queue. I suspect the change itself is simple but some of our test projects happened to rely on this and will fail (spectacularly) until patched to compensate e.g. by adding <WindowsAppSDKBootstrapInitialize>true</WindowsAppSDKBootstrapInitialize> to their *proj file. IOW do-able but more of a time-sink than it might seem at first blush, so please be patient.

And yes, a workaround until fixed is to add to your *proj file <WindowsAppSDKBootstrapInitialize>false</WindowsAppSDKBootstrapInitialize> to avoid the default evaluation to true.

This has been a complicated space to date so I did some spelunking (below) to verify this conclusion. Please speak up if you see a flaw in the analysis.

+@Scottj1s sound good to you too?

Detailed Spelunking...

The default's been selected this way since 1.0-preview2, revising an earlier implementation in 1.0-preview1 which had its issues (see below).

Per Common MSBuild project properties OutputType is the

...file format of the output file. This parameter can have one of the following values:

  • Library. Creates a code library. (Default value.)
  • Exe. Creates a console application.
  • Module. Creates a module.
  • Winexe. Creates a Windows-based program.

Clearly we do want the Bootstrapper when

Condition="('$(OutputType)'=='Exe') or ($(OutputType)'=='Winexe')"

Case #1: It's probably wrong if it's a Library or Module. I suspect there's some oddball case where a DLL is loaded by a generic exe (a la regsvr32.exe, dllhost.exe, te.exe or litany of others) but that's unusual enough and ambiguous enough that we can ignore it for the default (those who truly want it to explicitly set <WindowsAppSDKBootstrapInitialize>true</>).

Case #2: What if OutputType is undefined? It's possible but again it seems we're getting into weirdly unusual territory requiring developer action to explicitly tell us if they want auto-initialization.

BTW the docs note a caveat about OutputType:

For C# and Visual Basic, this property is equivalent to the /target switch. The output type can be automatically overridden by inferencing. See OutputType set to WinExe for WPF and WinForms apps. Disable inferencing by setting DisableWinExeOutputInference to true.

but that has to do with OutputType = Exe vs WinExe so it doesn't change our calculus.

As to why the Bootstrapper default is the way it is today we need to do a little software archaeology...

The default is defined in build\NuSpecs\Microsoft.WindowsAppSDK.BootstrapCommon.targets

    <PropertyGroup Condition="'$(WindowsAppSdkBootstrapInitialize)'=='' and '$(WindowsAppSDKSelfContained)'!='true' and '$(WindowsPackageType)'=='None'">
        <!--Allows GenerateBootstrapCS/GenerateBootstrapCpp to run-->
        <WindowsAppSdkBootstrapInitialize>true</WindowsAppSdkBootstrapInitialize>
    </PropertyGroup>

which actually dates back to build/NuSpecs/Microsoft.WindowsAppSDK.MddCommon.targets as shipped in 1.0-preview2 and created in commit 48e6b8f on Oct'14,2021. Before that 1.0-preview1 defined in build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets

<Import Project="$(MSBuildThisFileDirectory)Microsoft.WindowsAppSDK.Bootstrap.targets" Condition="'$(MSBuildProjectExtension)' != '.wapproj'" />

which was an overly broad target and led to the refinments on Oct'14 in commit 1459372 for 1.0-preview2.

DrusTheAxe added a commit that referenced this issue May 12, 2022
…ssembly()) { return; }' shortcircuit as it catches loading for reflection AND for common test cases e.g. 'te.exe foo.dll' as auto-initialization isn't restricted to exes (i.e. it gets compiled into foo.dll) and then Entry!=Executing. Revert this for now and restore later when #2456 is addressed (by restrcting auto-init to only compile into exes)
@DrusTheAxe
Copy link
Member

See the related PR Remove C# auto-initialization check for reflection#2500

DrusTheAxe added a commit that referenced this issue May 12, 2022
* Remove the 'if (Assembly.GetEntryAssembly() != Assembly.GetExecutingAssembly()) { return; }' shortcircuit as it catches loading for reflection AND for common test cases e.g. 'te.exe foo.dll' as auto-initialization isn't restricted to exes (i.e. it gets compiled into foo.dll) and then Entry!=Executing. Revert this for now and restore later when #2456 is addressed (by restrcting auto-init to only compile into exes)

* Fix typo
sachintaMSFT pushed a commit that referenced this issue May 12, 2022
* Remove the 'if (Assembly.GetEntryAssembly() != Assembly.GetExecutingAssembly()) { return; }' shortcircuit as it catches loading for reflection AND for common test cases e.g. 'te.exe foo.dll' as auto-initialization isn't restricted to exes (i.e. it gets compiled into foo.dll) and then Entry!=Executing. Revert this for now and restore later when #2456 is addressed (by restrcting auto-init to only compile into exes)

* Fix typo
sachintaMSFT added a commit that referenced this issue May 12, 2022
…elf-contained (#2502)

* Fix UndockedRegFreeWinRT auto-initializer issues (#2476)

* Fix bad filename

* No precompiledheaders when compiling the auto-initializer

* Some refinements on the UndockedRegFreeWinRT self-contained and auto-initialization support (#2493)

* UrfwInitialize() didn't report if ExtRoLoadCatalog() errored and returned a failing HRESULT (only trapped thrown exceptions, but the implementation does both) (#2498)

* Remove C# auto-initialization check for reflection (#2500)

* Remove the 'if (Assembly.GetEntryAssembly() != Assembly.GetExecutingAssembly()) { return; }' shortcircuit as it catches loading for reflection AND for common test cases e.g. 'te.exe foo.dll' as auto-initialization isn't restricted to exes (i.e. it gets compiled into foo.dll) and then Entry!=Executing. Revert this for now and restore later when #2456 is addressed (by restrcting auto-init to only compile into exes)

* Fix typo

* Fix URFW auto-init reference to EnsureIsLoaded() (#2501)

Co-authored-by: Howard Kapustein <howardk@microsoft.com>
@DrusTheAxe DrusTheAxe modified the milestones: 1.1, 1.2 Aug 1, 2022
@DrusTheAxe
Copy link
Member

Given the nature of the impact this is probably something we should not service to 1.1.

Tee'd up for 1.2 => #2775

@DrusTheAxe
Copy link
Member

This has been resolved in 1.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-DynamicDependencies area-Infrastructure Build, test, source layout, package construction (TODO: move to Deployment, DeveloperTools) bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants