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

Re-enable trimming of library tests on Apple mobile #104097

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

kotlarmilos
Copy link
Member

@kotlarmilos kotlarmilos commented Jun 27, 2024

Description

This PR re-enables the trimming of library tests on Apple mobile platforms. This change prevents the default settings of ILLink switches from targets that are imported. The regression was introduced in #103594.

Fixes #91923

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

eng/pipelines/runtime.yml Show resolved Hide resolved
@@ -12,6 +12,8 @@
<!-- Forced by ILLink targets -->
<SelfContained>true</SelfContained>
<PublishDir>$(OriginalPublishDir)</PublishDir>
<!-- Prevent getting DynamicCodeSupport=true default from ILLink targets that are imported with the Sdk.targets -->
<DynamicCodeSupport>false</DynamicCodeSupport>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! These are difficult to detect when something goes wrong at runtime.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression we'd only do AOT on helix, not actual trimming. @steveisok how does this work?

Copy link
Member

@akoeplinger akoeplinger Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new default for the property should affect many more cases than just AOT on helix so this doesn't sounds like the correct place for this fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression we'd only do AOT on helix, not actual trimming. @steveisok how does this work?

If you want trimming + AOT on helix, both have to occur in the same place. Otherwise, you have to send individual copies of the trimmed shared framework for each test from the build machine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might not be as painful as it seemed initially.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akoeplinger Since we perform trimming on Helix, we can move this to the Directory.Build.props file. However, it will not have effect on other components.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a default switch to disable trimming on build machines as well. I haven't found a common location where these switches are set in Mono. Since we don't ship Apple mobile support from the runtime repository, the switch is set in the SDK/Xamarin.

A potential place to set this switch could be the AOT compiler props, but they are invoked after the trimming.

/cc: @sbomer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ideal solution would be for the AOT compiler props in this repo to be imported before the trimming props, which is how this works in the SDK. But barring that the Directory.Build.props seems like a good place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ILLink feature switches are moved to ConfigureTrimming target.

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmilos
Copy link
Member Author

Let's revive this PR. Enabling trimming for Apple mobile consolidates it with the default shipping setup and reduces build time on CI.

Copy link
Member

@ivanpovazan ivanpovazan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for trying to revive this!

I agree this is beneficial for reducing our CI resource usage, but before going forward, we might want to also reprioritize and bring closer attention to having better crash/failure logs on iOS platforms testing dotnet/xharness#1188 so that potential new failures caused by trimming are not shadowed by various "Failed USB connection" or "TCP connection failures".

Another idea/option would be to run two jobs with: EnableAggressiveTrimming=true and EnableAggressiveTrimming=false on rolling builds, so that if there is a failure when trimming is enabled it can be compared against a non-trimmed variant to improve root cause detection of a failure.

Finally (and ideally) we would have a single source of truth for setting expected default feature switch values for iOS platforms when running tests, which we would keep in sync with: https://github.com/xamarin/xamarin-macios/blob/43768cfcb7e5ff9554a9bfd057f7b4d7a3c10cc7/dotnet/targets/Xamarin.Shared.Sdk.targets#L120

Comment on lines 103 to 105
<RuntimeHostConfigurationOption Include="System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported" Value="false" />
<RuntimeHostConfigurationOption Include="System.ComponentModel.DefaultValueAttribute.IsSupported" Value="true" />
<RuntimeHostConfigurationOption Include="System.ComponentModel.Design.IDesignerHost.IsSupported" Value="true" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of notes:

  • If we want to actually trim codepaths guarded by these feature switches we would also need to set Trim attribute to true on these RuntimeHostConfigurationOption items, as ILLink picks up only those that have Trim=true
  • Another, probably more robust, approach would be to set the actual feature switch properties instead of altering RuntimeHostConfigurationOption but that would need to happen really early in the build - at the time of property evaluation, like for example how we set DebuggerSupport on line 35 above. So we would have
    <PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true' and '$(BuildTestsOnHelix)' != 'true'">
    ...
    </PropertyGroup>
    <PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true' and '$(BuildTestsOnHelix)' == 'true'">
        <DynamicCodeSupport>false</DynamicCodeSupport>
        ... 
    </PropertyGroup>

instead of these RuntimeHostConfigurationOption overwrites

Comment on lines 50 to 54
<!-- Prevent getting defaults from ILLink targets that are imported with the Sdk.targets -->
<RuntimeHostConfigurationOption Include="System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported" Value="false" />
<RuntimeHostConfigurationOption Include="System.ComponentModel.DefaultValueAttribute.IsSupported" Value="true" />
<RuntimeHostConfigurationOption Include="System.ComponentModel.Design.IDesignerHost.IsSupported" Value="true" />

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant. If the build on build machines was properly configured ie all feature switches have their values properly set for testing, we carry over RuntimeHostConfigurationOption to Helix through _AppleUsedRuntimeHostConfigurationOption item group and set the values in Target Name=_PrepareForAppleBuildAppOnHelix Project=ProxyProjectForAOTOnHelix.proj when we build on Helix.

Comment on lines 41 to 43
<DynamicCodeSupport Condition="'$(DynamicCodeSupport)' == '' and '$(MonoForceInterpreter)' != 'true'">false</DynamicCodeSupport>
<_DefaultValueAttributeSupport Condition="'$(_DefaultValueAttributeSupport)' == ''">true</_DefaultValueAttributeSupport>
<_DesignerHostSupport Condition="'$(_DesignerHostSupport)' == ''">true</_DesignerHostSupport>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW
I think these need to be in a separate property group as I believe BuildTestsOnHelix=true in our setup.
So based on my previous comment, I think we will need a new property group conditioned with '$(EnableAggressiveTrimming)' == 'true' and '$(BuildTestsOnHelix)' == 'true' and then add these switches there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I missed the condition.

@kotlarmilos
Copy link
Member Author

Another idea/option would be to run two jobs with: EnableAggressiveTrimming=true and EnableAggressiveTrimming=false on rolling builds, so that if there is a failure when trimming is enabled it can be compared against a non-trimmed variant to improve root cause detection of a failure.

Do we get the same ability to detect a failure by comparing a PR build (with trimming) with rolling build (without trimming)? I would like to avoid reducing cost by introducing an additional cost :)

Finally (and ideally) we would have a single source of truth for setting expected default feature switch values for iOS platforms when running tests, which we would keep in sync with: https://github.com/xamarin/xamarin-macios/blob/43768cfcb7e5ff9554a9bfd057f7b4d7a3c10cc7/dotnet/targets/Xamarin.Shared.Sdk.targets#L120

Yes, that would be ideal. The main question is how to achieve this without manual sync.

@ivanpovazan
Copy link
Member

Do we get the same ability to detect a failure by comparing a PR build (with trimming) with rolling build (without trimming)? I would like to avoid reducing cost by introducing an additional cost :)

Hm yeah, I see your point.
The problem we are having now is:

  • someone makes a change
  • PR fails on iOS platforms due to a trimming issue
  • the failure looks unrelated to the change, Known Build Error is opened, and the PR is merged (or worse PR is merged on red)
  • the hard-to-detect failure stays, but is flagged by Build Analysis tool
  • we have hard time tracking back what the problem was

To tackle this, it would be great if we would have an ability to rerun the same state with trimming disabled, to rule out that as an issue. With something like /azp rerun ios-platforms-no-trimming we would control the extra cost, and run it only if the failure occurs.

This is just an idea, probably out-of-scope, just thinking of ways of how to improve the triaging experience.

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmilos
Copy link
Member Author

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[mono] Update tests to be trim-compatible on ios/tvos platforms
6 participants