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

Improve consumption of NativeAOT linker flags #18835

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 5 additions & 70 deletions dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1285,77 +1285,12 @@
<TrimmerRootAssembly Include="@(_TrimmerRootAssemblyButOnlyIntermediateAssembly->'%(Filename)')" />
</ItemGroup>

<!--

Collect all the native linker args ILC would have used and use
them ourselves when we link natively.

Unfortunately there's a major difference between LinkerArgs (as
used by ILC) and our _CustomLinkerFlags: ILC splits on space in
LinkerArg, while we quote (when necessary) the items in
_CustomLinkerFlags.

Example:

<LinkerArg Include="-framework UIKit" />

ILC will pass that as two separate arguments to the native
compiler

<_CustomLinkFlags Include="-framework UIKit" />

We'll pass that as a single argument ('-framework UIKit')
to the native compiler (which the native compiler doesn't
like)

So we need to convert the list of space-separated items in
LinkerArg to space-preserved items in _CustomLinkFlags.

How to do this in MSBuild is somewhat non-obvious: first we
convert the LinkerArg item group to a property where every item is
separated by a semi-colon, and where we've also replaced spaces by
semi-colons. This means we have a property where every flag we
want is separated by a semi-colon. Then we split on the property
string on a semi-colon and add those items to the _CustomLinkFlags
item group.

Note: this means ILC doesn't support linker flags with spaces in them.

Additionally, the LinkerArg item group are actually passed to the
native compiler by the NativeAOT build tasks, not the native
linker. This means they might contain wrapped linker arguments:
'-Wl,...', which the compiler understands, but not the linker.
Thus we need to unwrap the (compiler) arguments in LinkerArgs to
be actual linker arguments. Also note that there can be multiple
linker arguments passed using a single compiler argument, and
those are separated by a comma: "-Wl,-linkerarg1,-linkerarg2", so
we need to split those into multiple linker arguments as well. And
to make things even more complicated, there may be quotes as well:
<LinkerArg>'-Wl,-linkerarg1,-linkerarg2'</LinkerArg>.

-->
<PropertyGroup>
<_LinkerArgsSplitBySemiColon>@(LinkerArg->Replace(' ',';'))</_LinkerArgsSplitBySemiColon>
</PropertyGroup>
<ItemGroup>
<_AllLinkerArgs Include="$(_LinkerArgsSplitBySemiColon.Split(';'))" />
<_LinkerArgsWhichAreReallyCompilerArgs Include="@(_AllLinkerArgs)" Condition="$([System.String]::new('%(Identity)').StartsWith('-Wl,'))">
<TransformedArgument>$([System.String]::new('%(Identity)').Substring(4))</TransformedArgument>
</_LinkerArgsWhichAreReallyCompilerArgs>
<!-- Handle quoted arguments: <LinkerArg>'-Wl,-linkerarg'</LinkerArg> -->
<_LinkerArgsWhichAreReallyCompilerArgs Include="@(_AllLinkerArgs)" Condition="$([System.String]::new('%(Identity)').StartsWith('%27-Wl,')) And $([System.String]::new('%(Identity)').EndsWith('%27'))">
<TransformedArgument>$([System.String]::new('%(Identity)').Substring(5, $([MSBuild]::Subtract($([System.String]::new('%(Identity)').Length), 6))))</TransformedArgument>
</_LinkerArgsWhichAreReallyCompilerArgs>
<_CompilerArgsTransformedToLinkerArgs Include="@(_LinkerArgsWhichAreReallyCompilerArgs->'%(TransformedArgument)')" />
</ItemGroup>
<PropertyGroup>
<_CompilerArgsTransformedToLinkerArgsSplitByComma>@(_CompilerArgsTransformedToLinkerArgs->Replace(',',';'))</_CompilerArgsTransformedToLinkerArgsSplitByComma>
</PropertyGroup>
<ItemGroup>
<_AllLinkerArgs Remove="@(_LinkerArgsWhichAreReallyCompilerArgs)" />
<_AllLinkerArgs Include="$(_CompilerArgsTransformedToLinkerArgsSplitByComma.Split(';'))" />

<_CustomLinkFlags Include="@(_AllLinkerArgs)" />
<!-- Collect extra native linker flags ILC would have used -->
<_CustomLinkFlags Include="@(NativeLibrary)" />
<_CustomLinkFlags Include="@(NativeSystemLibrary->'-l%(Identity)')" />
<_CustomLinkFlags Include="@(NativeFramework->'-Wl,-framework,%(Identity)')" />
<_CustomLinkFlags Include="@(ExtraLinkerArg->'-Wl,%(Identity)')" />
</ItemGroup>

<ItemGroup>
Expand Down