dotnet / runtime

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

NativeAOT result binary on macOS targets latest SDK #98124

Closed Mikolaytis closed 6 months ago

Mikolaytis commented 6 months ago

Description

I think that result library should have at least a maximum OS sdk version between used libraries. I've checked all libraries before linker - maximum sdk version is 11.0. But somehow after compile it's 14.0 in a result binary. Maybe there is an linker arg or any csproj parameter to select minimum os sdk version I did not found?

I use .net 8.0.101.

Reproduction Steps

Create console app. Add PublishAot=True dotnet publish -c Release -r osx-x64 otool -l ConsoleApp1

Expected behavior

minos should be 11.0

Load command 13 cmd LC_BUILD_VERSION cmdsize 32 platform 1 minos 11.0 sdk 14.2 ntools 1 tool 3 version 1022.1

Actual behavior

Load command 13 cmd LC_BUILD_VERSION cmdsize 32 platform 1 minos 14.0 sdk 14.2 ntools 1 tool 3 version 1022.1

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

ghost commented 6 months ago

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I think that result library should have at least a maximum OS sdk version between used libraries. I've checked all libraries before linker - maximum sdk version is 11.0. But somehow after compile it's 14.0 in a result binary. Maybe there is an linker arg or any csproj parameter to select minimum os sdk version I did not found? I use .net 8.0.101. ### Reproduction Steps Create console app. Add PublishAot=True dotnet publish -c Release -r osx-x64 otool -l ConsoleApp1 ### Expected behavior minos should be 11.0 Load command 13 cmd LC_BUILD_VERSION cmdsize 32 platform 1 minos 11.0 sdk 14.2 ntools 1 tool 3 version 1022.1 ### Actual behavior Load command 13 cmd LC_BUILD_VERSION cmdsize 32 platform 1 minos 14.0 sdk 14.2 ntools 1 tool 3 version 1022.1 ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration _No response_ ### Other information _No response_
Author: Mikolaytis
Assignees: -
Labels: `untriaged`, `area-NativeAOT-coreclr`, `needs-area-label`
Milestone: -
filipnavara commented 6 months ago

It seems that the logic in the build files only covers iOS-like platforms. We should probably fix that.

As a workaround you can add an argument to the linker in the .csproj file:

    <ItemGroup>
      <LinkerArg Include="-mmacosx-version-min=11.0" />
    </ItemGroup>
jkotas commented 6 months ago

Trying to determine whether this warrants a backport. What is this version used for? Does macOS block binaries with minos version 14.0 from being launched on older macOS versions?

filipnavara commented 6 months ago

Yes, older macOS versions would block running the binaries. I am leaning towards doing a backport. Xamarin workloads already do this and so this is unexpected inconsistency between net8.0 and net8.0-macos. On the other hand the workaround is pretty easy.

I can open a PR when I get home and we can either proceed with it or close it.

filipnavara commented 6 months ago

I made the backport - https://github.com/dotnet/runtime/compare/release/8.0-staging...filipnavara:runtime:min-version-80?expand=1 - and started filling the template, only to realize that macOS (14.3.1) actually ignores the value for console applications, and so does the linker when referencing a dynamic library. With that in mind I no longer think the backport is necessary.

In case the opinion changes in the future, here's part of the prefilled template:

Backport of #98233

/cc @jkotas

## Customer Impact

- [x] Customer reported
- [ ] Found internally

Reported in #98124. Applications and shared libraries targeting `net8.0` without the macOS workload (ie. `net8.0-macos` is not affected) get indeterministic minimum OS version number in the executable header when compiled. Instead of getting the minimum macOS version supported by .NET 8.0, which is macOS 11.0, they get the version corresponding to the Xcode SDK installed on the build machine.

The OS itself seems to ignore the version number for executables (as of macOS 14.3.1), and so does the linker when linking against a dynamic library compiled with NativeAOT. 

## Regression

- [ ] Yes
- [x] No

.NET 8 was the first version of .NET to support NativeAOT on macOS.

## Testing

The fix was tested by compiling a NativeAOT application on macOS with `dotnet publish -p:PublishAot=true` and then verifying the version headers of the exectuable with `vtool -show <path to output binary>`.

## Risk

Low. [To be filled]
jkotas commented 6 months ago

@filipnavara Thank you for looking into it!