dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.35k stars 4.74k forks source link

[NativeAOT] Simplify build integration with external bundlers for Apple platforms #87187

Open ivanpovazan opened 1 year ago

ivanpovazan commented 1 year ago

Description

In order to support targeting Apple platforms NativeAOT build targets need to be integrated with external build systems and bundlers like:

To achieve this, several project properties need to be set in the correct way and we are currently collecting all that is necessary to achieve the integration.

To improve the integration process and maintainability it would be beneficial to simplify the integration process when targeting Apple platforms with a single "opt-in" MSBuild property.

ghost commented 1 year ago

Tagging subscribers to 'os-ios': @steveisok, @akoeplinger See info in area-owners.md if you want to be subscribed.

Issue Details
## Description In order to support targeting Apple platforms NativeAOT build targets need to be integrated with external build systems and bundlers like: - Xamarin.Sdk - [AppleAppBuilder](https://github.com/dotnet/runtime/tree/10222f94e5d89b19959117dd9e5b8576ef63f878/src/tasks/AppleAppBuilder) To achieve this, several project properties need to be set in the correct way. - For example: in case of targeting an iOS application with NativeAOT (`PublishAot=true`) and integrating it with an external build pipeline, these are the properties that need to be set: ```xml true true static true false Compile;ComputeIlcCompileInputs;SetupOSSpecificProps;PrepareForILLink ``` To improve the integration process and maintainability it would be beneficial to simplify the integration process when targeting Apple platforms with a single "opt-in" MSBuild property.
Author: ivanpovazan
Assignees: -
Labels: `os-ios`, `area-NativeAOT-coreclr`
Milestone: 8.0.0
MichalStrehovsky commented 1 year ago

I'm not sure I understand the IlcCompileDependsOn and NativeCompilationDuringPublish parts. Is the intention that we would not run the Publish target when building for iOS?

ivanpovazan commented 1 year ago

I'm not sure I understand the IlcCompileDependsOn and NativeCompilationDuringPublish parts. Is the intention that we would not run the Publish target when building for iOS?

These are just currently used workarounds to avoid build issues like:

To summarize, I think I was not precise enough in the description of the issue (I will update it), as we are still collecting all that we would need for easier integration and the goal is to hopefully have this all accessible under a single switch.

jkotas commented 1 year ago

it would be beneficial to simplify the integration process when targeting Apple platforms with a single "opt-in" MSBuild property.

I do not think that the settings are the only one right way to target Apple platforms. They are specific to Xamarin app-model. Other app models (e.g. Avalonia) may want to do the integration differently.

We try to avoid hardcoding app-model specific settings in the core runtime .target files. For example, we have the same relationship with ASP.NET app models: ASP.NET SDKs have number of custom overrides of the defaults. I think we should follow the same pattern for all appmodels/SDKs, including Xamarin.

It is fine to expose individual features in cleaner way to make the integration easier.

rolfbjarne commented 1 year ago

It is fine to expose individual features in cleaner way to make the integration easier.

In particular having to set IlcCompileDependsOn seems like could be implemented in a better way.

filipnavara commented 1 year ago

I feel the only fragile part is IlcCompileDependsOn, and the main reason why we need to fiddle with it is to allow running both ILLink and ILCompiler. While there are some discussions about avoiding that in the long-term I feel it would be useful to actually fix the scenario to be allowed. That would primarily mean allowing RunILLink=true opt-in here, and implementing the logic to pass ILLink output to ILCompiler on dotnet/runtime or dotnet/sdk side.

kotlarmilos commented 1 year ago

In particular having to set IlcCompileDependsOn seems like could be implemented in a better way.

While working on the runtime tests, I'm exploring several ideas to address this issue:

For example, we have the same relationship with ASP.NET app models: ASP.NET SDKs have number of custom overrides of the defaults. I think we should follow the same pattern for all appmodels/SDKs, including Xamarin.

It would be good to check out an example of the ASP.NET app models, so we can consider the existing approach.

MichalStrehovsky commented 1 year ago

In particular having to set IlcCompileDependsOn seems like could be implemented in a better way.

What targets in Microsoft.NETCore.Native.Publish.targets are problematic? We could condition them on some property that the Xamarin props would set so that they don't interfere with how Xamarin wants to set up the flow of inputs/outputs.

The same with LinkNative - I'd suggest looking into why it's even executed when we're not doing a publish. Eventually, we'd want to split LinkNative into two targets - one that constructs the command line arguments we want to pass to the linker (so that the Xamarin targets can pick it up) and another one that actually runs linker (Xamarin would not participate in that).

rolfbjarne commented 1 year ago

In particular having to set IlcCompileDependsOn seems like could be implemented in a better way.

What targets in Microsoft.NETCore.Native.Publish.targets are problematic? We could condition them on some property that the Xamarin props would set so that they don't interfere with how Xamarin wants to set up the flow of inputs/outputs.

The same with LinkNative - I'd suggest looking into why it's even executed when we're not doing a publish. Eventually, we'd want to split LinkNative into two targets - one that constructs the command line arguments we want to pass to the linker (so that the Xamarin targets can pick it up) and another one that actually runs linker (Xamarin would not participate in that).

I'd suggest looking into why it's even executed when we're not doing a publish.

Note that we're doing "dotnet publish".

The immediate result I get (with the changes in https://github.com/xamarin/xamarin-macios/pull/17374) if I set NativeCompilationDuringPublish=true is this:

error MSB4006: There is a circular dependency in the target dependency graph involving target "_ComputeLinkerArguments". Since "IlcCompile" has "DependsOn" dependence on "_ComputeLinkerArguments", the circular is "_ComputeLinkerArguments<-IlcCompile<-LinkNative<-ComputeLinkedFilesToPublish<-ComputeResolvedFilesToPublishList<-_ComputeFrameworkAssemblies<-_ComputeLinkerArguments".

Looks like that's because of:

https://github.com/dotnet/runtime/blob/5b900dd43bb1568768d11712d842974da0f368e4/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets#L20-L22

where Microsoft.NETCore.Native.Publish.targets injects the ComputeLinkedFilesToPublish into the build chain, and indirectly LinkNative.

So here's problem 1: we don't want to execute NativeAOT's LinkNative target, because we're using the static library ILC creates, and not the final linked output.

Maybe it would make sense to create a property the SDK could set to indicate that we only need the static library, and not the final linked result?

jkotas commented 1 year ago

Maybe it would make sense to create a property the SDK could set to indicate that we only need the static library, and not the final linked result?

It is what <NativeLib>Static</NativeLib> does today. It may need some tweaks so that it works well for Xamarin config.

kotlarmilos commented 1 year ago

There is more we can do to simplify the integration, so keeping this issue open.