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

Skip projection generation during design-time build if inputs are missing #1105

Merged
merged 2 commits into from
Feb 23, 2022

Conversation

evelynwu-msft
Copy link
Contributor

Although it is generally desirable for CsWinRT projection generation to explicitly fail if input .winmds are missing, we don't want this to happen during a design-time build. Due to Visual Studio's architecture, failures in a project's design-time build can leave the results of dependent projects' design-time builds in an inconsistent state (this was determined to be one of the primary root causes of https://task.ms/37142724). An example of this scenario would be a CsWinRT project that depends on a C++/CX Windows Runtime Component project: the latter produces its output .winmd during the Link target and so the .winmd does not exist for the former to consume until a normal build has completed.

This change modifies the CsWinRTGenerateProjection target to skip the cswinrt.exe command if it is determined that (a) it is currently running in the context of a design-time build, and (b) one or more of the input .winmds does not exist. This allows the design-time build to succeed while still allowing for the possibility of a legitimate failure during a normal build.

@jlaanstra
Copy link
Collaborator

jlaanstra commented Feb 10, 2022

Although it is generally desirable for CsWinRT projection generation to explicitly fail if input .winmds are missing, we don't want this to happen during a design-time build. Due to Visual Studio's architecture, failures in a project's design-time build can leave the results of dependent projects' design-time builds in an inconsistent state

This problem can also happen when a WinMD is present but it's out of date.

This change modifies the CsWinRTGenerateProjection target to skip the cswinrt.exe command if it is determined that (a) it is currently running in the context of a design-time build, and (b) one or more of the input .winmds does not exist. This allows the design-time build to succeed while still allowing for the possibility of a legitimate failure during a normal build.

I think we can solve this with a much simpler change, by simply setting COntinueOnError on the CsWinRT Exec task as follows:

        <PropertyGroup>
            <CsWinRTContinueOnError>false</CsWinRTContinueOnError>
            <CsWinRTContinueOnError Condition="'$(DesignTimeBuild)' == 'true' OR '$(BuildingProject)' != 'true'">true</CsWinRTContinueOnError>
        </PropertyGroup>

        <Exec Command="$(CsWinRTCommand)" ContinueOnError="$(CsWinRTContinueOnError)" />

Thoughts?

@angelazhangmsft
Copy link
Contributor

@evelynwu-msft does this fix #1056 and/or #963?

@jlaanstra
Copy link
Collaborator

@angelazhangmsft my suggested approach fixes #963

@evelynwu-msft
Copy link
Contributor Author

I think we can solve this with a much simpler change, by simply setting COntinueOnError on the CsWinRT Exec task as follows:

        <PropertyGroup>
            <CsWinRTContinueOnError>false</CsWinRTContinueOnError>
            <CsWinRTContinueOnError Condition="'$(DesignTimeBuild)' == 'true' OR '$(BuildingProject)' != 'true'">true</CsWinRTContinueOnError>
        </PropertyGroup>

        <Exec Command="$(CsWinRTCommand)" ContinueOnError="$(CsWinRTContinueOnError)" />

Thoughts?

My preference is to skip the scenario entirely if we know in advance that it's going to generate an error. It minimizes the amount of unnecessary work that is done, and avoids the possibility of cswinrt.exe, even in an error situation, leaving behind cruft that pollutes the build outputs.

(It's also not clear to me from the MSDN documentation if <Task ContinueOnError="ErrorAndContinue" /> will trigger an <OnError /> element; if it doesn't then we'd still have to skip creation of the .rsp file.)

@evelynwu-msft
Copy link
Contributor Author

@evelynwu-msft does this fix #1056 and/or #963?

@angelazhangmsft Yes, I believe it would address both of them.

@jlaanstra
Copy link
Collaborator

My preference is to skip the scenario entirely if we know in advance that it's going to generate an error. It minimizes the amount of unnecessary work that is done, and avoids the possibility of cswinrt.exe, even in an error situation, leaving behind cruft that pollutes the build outputs.

Skipping the scenario makes the IDE experience worse as you get no intellisense until you do a build. That doesn't seem like the right way forward.

@jlaanstra
Copy link
Collaborator

jlaanstra commented Feb 10, 2022

(It's also not clear to me from the MSDN documentation if <Task ContinueOnError="ErrorAndContinue" /> will trigger an <OnError /> element; if it doesn't then we'd still have to skip creation of the .rsp file.)

Per docs here https://docs.microsoft.com/en-us/visualstudio/msbuild/onerror-element-msbuild?view=vs-2022#remarks OnError will be skipped but this is fine. If the inputs don't change, the target wouldn't create any other output either way and once any of the inputs are generated the target would be run again, because the input changed.

@evelynwu-msft
Copy link
Contributor Author

Skipping the scenario makes the IDE experience worse as you get no intellisense until you do a build. That doesn't seem like the right way forward.

Wouldn't Intellisense information be missing regardless because cswinrt.exe errors out during projection generation?

@jlaanstra
Copy link
Collaborator

Wouldn't Intellisense information be missing regardless because cswinrt.exe errors out during projection generation?

From observation and experience it still generates the partial projection up to the point it hits the error, so you'd get some intellisense.

@jlaanstra
Copy link
Collaborator

@evelynwu-msft does this fix #1056 and/or #963?

@angelazhangmsft Yes, I believe it would address both of them.

Note that the fix as proposed in this PR doesn't completely address #693. The designtime build can still fail for a reason other than a missing output file, for example a missing project reference to a WinMD containing types used by a different WinMD. In that case there are no missing files as far as the logic is concerned and so the Designtime build would still fail, causing all the same problems.

@evelynwu-msft evelynwu-msft force-pushed the evelynwu-msft/dtb-break-fix branch from 1f5bad8 to 1db254d Compare February 18, 2022 03:08
@evelynwu-msft
Copy link
Contributor Author

evelynwu-msft commented Feb 18, 2022

@jlaanstra Your suggestion worked!

@jlaanstra
Copy link
Collaborator

LGTM /cc @Scottj1s

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.

4 participants