dotnet / runtime

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

Publishing for linux-arm64 on Linux x64 with NativeAot and StripSymbols uses objcopy instead of aarch64-linux-gnu-objcopy #84769

Closed JinShil closed 2 months ago

JinShil commented 1 year ago

Describe the bug

The following output shows the problem:

dotnet publish -c Release -r linux-arm64 -p:PublishAot=true -p:StripSymbols=true
MSBuild version 17.5.1+f6fdcf537 for .NET
  Generating native code
  objcopy: Unable to recognise the format of the input file `{projectPath}'
/usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073: The command "
/usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073:         "objcopy" --only-keep-debug "{executable_path}" "{executable_path}.dbg" && 
/usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073:         "objcopy" --strip-debug --strip-unneeded "{executable_path}" &&
/usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073:         "objcopy" --add-gnu-debuglink="{executable_path}.dbg" "{executable_path}"" exited with code 1.

To Reproduce

  1. Walk over to a Linux x64 computer
  2. Create a new .NET console project using .NET 7 SDK
  3. Run the above dotnet publish command in an attempt to publish it for Linux ARM64
  4. Notice that it fails because it is trying to use objcopy instead of aarch64-linux-gnu-objcopy to strip the symbols

Further technical details

.NET SDK:
 Version:   7.0.203
 Commit:    5b005c19f5

Runtime Environment:
 OS Name:     debian
 OS Version:  11
 OS Platform: Linux
 RID:         debian.11-x64
 Base Path:   /usr/share/dotnet/sdk/7.0.203/

Host:
  Version:      7.0.5
  Architecture: x64
  Commit:       8042d61b17

.NET SDKs installed:
  6.0.408 [/usr/share/dotnet/sdk]
  7.0.203 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.16 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.16 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
dotnet-issue-labeler[bot] commented 1 year ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 1 year ago

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

Issue Details
### Describe the bug The following output shows the problem: ``` dotnet publish -c Release -r linux-arm64 -p:PublishAot=true -p:StripSymbols=true MSBuild version 17.5.1+f6fdcf537 for .NET Generating native code objcopy: Unable to recognise the format of the input file `{projectPath}' /usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073: The command " /usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073: "objcopy" --only-keep-debug "{executable_path}" "{executable_path}.dbg" && /usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073: "objcopy" --strip-debug --strip-unneeded "{executable_path}" && /usr/share/dotnet/sdk/7.0.203/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.targets(358,5): error MSB3073: "objcopy" --add-gnu-debuglink="{executable_path}.dbg" "{executable_path}"" exited with code 1. ``` ### To Reproduce 1. Walk over to a Linux x64 computer 2. Create a new .NET console project using .NET 7 SDK 3. Run the above `dotnet publish` command in an attempt to publish it for Linux ARM64 4. Notice that it fails because it is trying to use `objcopy` instead of `aarch64-linux-gnu-objcopy` to strip the symbols ### Further technical details ``` .NET SDK: Version: 7.0.203 Commit: 5b005c19f5 Runtime Environment: OS Name: debian OS Version: 11 OS Platform: Linux RID: debian.11-x64 Base Path: /usr/share/dotnet/sdk/7.0.203/ Host: Version: 7.0.5 Architecture: x64 Commit: 8042d61b17 .NET SDKs installed: 6.0.408 [/usr/share/dotnet/sdk] 7.0.203 [/usr/share/dotnet/sdk] .NET runtimes installed: Microsoft.AspNetCore.App 6.0.16 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 6.0.16 [/usr/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App] Other architectures found: None Environment variables: Not set global.json file: Not found Learn more: https://aka.ms/dotnet/info Download .NET: https://aka.ms/dotnet/download ```
Author: JinShil
Assignees: -
Labels: `untriaged`, `area-NativeAOT-coreclr`, `needs-area-label`
Milestone: -
am11 commented 1 year ago

The solution is to either set <ObjCopyName>aarch64-linux-gnu-objcopy property, or install llvm-objcopy, which supports multiple architectures.

JinShil commented 1 year ago

The solution is to either set <ObjCopyName>aarch64-linux-gnu-objcopy property, or install llvm-objcopy, which supports multiple architectures.

I argue that is a workaround, not a solution. The build system should be able to determine what tools the system has and make the correct choice. If a supported tool is not available then it should display an error saying so with information about which tools need to be installed. It should never use the wrong tool.

am11 commented 1 year ago

I don't have strong opinions on this, but when we added this support, the idea/feedback was to keep it simple and keep symbol stripping opt-in. Now we have changed it to opt-out in main branch, so things are evolving and this can too.

If you want this (somewhat niche) scenario to work seamlessly, then feel free to send a PR. We also do not have version-awareness in NativeAOT build integration. Ideally, we should introspect the matching tools the way we do in runtime build (that takes care of 'matching toolchain' && 'matching version' before resorting to 'fallback') https://github.com/dotnet/runtime/blob/c45caed8e96368f30806f86abc945cc5236205cf/eng/native/configuretools.cmake#L24-L70 but implementing cmake-like introspection in NativeAOT's msbuild targets without the dependency on cmake is quite involved.

MichalStrehovsky commented 2 months ago

This is the general "crossbuild is difficult to setup" bucket. We now document one way to set it up as part of official docs here: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/cross-compile#linux. It's unlikely we'd do more tool introspection because it would just be a bugfarm.