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

[Xamarin.Android.Build.Tasks] skip MSBuild targets when project file changes #7673

Conversation

jonathanpeppers
Copy link
Member

Context: dotnet/maui#7808

There is currently a bug in VS where adding new MAUI pages edits the .csproj file:

<ItemGroup>
  <MauiXaml Update="NewPage1.xaml">
    <Generator>MSBuild:Compile</Generator>
  </MauiXaml>
</ItemGroup>

Unfortunately, this triggers many of the Android MSBuild targets to run again -- when they really don't need to.

Various targets have different forms of:

Inputs="@(_AndroidMSBuildAllProjects)"
Inputs="$(MSBuildProjectFullPath)"

Understandably, this reduces the chance of bin/obj bugs such as:

  1. I build my project.

  2. I change some setting my my project file.

  3. I expect the MSBuild targets interested in this setting to rebuild.

So I don't think we can blindly delete all instances of @(_AndroidMSBuildAllProjects), but try a few at a time. We can replace this value with $(_AndroidBuildPropertiesCache) (which is build.props) making sure important properties are stored in this file.

Interestingly, even CoreCompile reruns if the project file changes:

Building target "CoreCompile" completely.
Input file "UnnamedProject.csproj" is newer than output file "obj\Debug\UnnamedProject.pdb".

Meaning that any of our targets that depend on the current project's build output is going to run anyway. But we can focus on slow parts of the build like javac and d8/r8.

So far, I updated the following targets:

  • _ConvertResourcesCases
    • Not related to project file at all?
  • _CompileBindingJava and _CompileJava
    • Runs when .java source file change, adjusted some Inputs
  • _GenerateAndroidAssetsDir and _GenerateAndroidResourceDir
    • Not related to project file at all?
  • _BeforeManagedUpdateAndroidResgen
    • Runs when @(AndroidResource) files change
  • _GenerateJavaStubs
    • actually runs when .NET assemblies change anyway
  • _ManifestMerger
    • $(AndroidManifestMerger) added to build.props
  • _GeneratePackageManagerJava
    • $(AndroidEnableMarshalMethods), $(AndroidUseAssemblyStore), and $(AndroidEnableAssemblyCompression) added to build.props.
  • _CompileToDalvik
    • runs when .jar files change
  • _BuildApkEmbed
    • runs when .NET assemblies change
  • _PrepareForSign
    • without Fast Dev, runs when .NET assemblies change
    • runs when .apk/.aab files change

There are still more MSBuild targets that use @(_AndroidMSBuildAllProjects), but this is a start.

I added a new test for this scenario.

…changes

Context: dotnet/maui#7808

There is currently a bug in VS where adding new MAUI pages edits the
`.csproj` file:

    <ItemGroup>
      <MauiXaml Update="NewPage1.xaml">
        <Generator>MSBuild:Compile</Generator>
      </MauiXaml>
    </ItemGroup>

Unfortunately, this triggers many of the Android MSBuild targets to
run again -- when they really don't need to.

Various targets have different forms of:

    Inputs="@(_AndroidMSBuildAllProjects)"
    Inputs="$(MSBuildProjectFullPath)"

Understandably, this reduces the chance of bin/obj bugs such as:

1. I build my project.

2. I change some setting my my project file.

3. I expect the MSBuild targets interested in this setting to rebuild.

So I don't think we can blindly delete all instances of
`@(_AndroidMSBuildAllProjects)`, but try a few at a time. We can
replace this value with `$(_AndroidBuildPropertiesCache)` (which is
`build.props`) making sure important properties are stored in this
file.

Interestingly, even `CoreCompile` reruns if the project file changes:

    Building target "CoreCompile" completely.
    Input file "UnnamedProject.csproj" is newer than output file "obj\Debug\UnnamedProject.pdb".

Meaning that any of our targets that depend on the current project's
build output is going to run anyway. But we can focus on slow parts of
the build like `javac` and `d8`/`r8`.

So far, I updated the following targets:

* `_ConvertResourcesCases`
    * Not related to project file at all?
* `_CompileBindingJava` and `_CompileJava`
    * Runs when `.java` source file change, adjusted some `Inputs`
* `_GenerateAndroidAssetsDir` and `_GenerateAndroidResourceDir`
    * Not related to project file at all?
* `_BeforeManagedUpdateAndroidResgen`
    * Runs when `@(AndroidResource)` files change
* `_GenerateJavaStubs`
    * actually runs when .NET assemblies change anyway
* `_ManifestMerger`
    * `$(AndroidManifestMerger)` added to `build.props`
* `_GeneratePackageManagerJava`
    * `$(AndroidEnableMarshalMethods)`, `$(AndroidUseAssemblyStore)`,
      and `$(AndroidEnableAssemblyCompression)` added to `build.props`.
* `_CompileToDalvik`
    * runs when `.jar` files change
* `_BuildApkEmbed`
    * runs when .NET assemblies change
* `_PrepareForSign`
    * without Fast Dev, runs when .NET assemblies change
    * runs when `.apk`/`.aab` files change

There are still more MSBuild targets that use
`@(_AndroidMSBuildAllProjects)`, but this is a start.

I added a new test for this scenario.
Change a property to solve:

    The target _ManifestMerger should have not been skipped.
@jonathanpeppers
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonathanpeppers
Copy link
Member Author

After talking about it, I'm slightly terrified of the potential "bin/obj" bugs from this change.

Going to close this for now and investigate other ideas.

@github-actions github-actions bot locked and limited conversation to collaborators Jan 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant