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

Download ILCompiler target pack when cross-compiling #30818

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

filipnavara
Copy link
Member

@agocke
Copy link
Member

agocke commented Feb 23, 2023

Two things:

  1. It's not clear to me why this is only a problem for Mac. I think I've seen people successfully make this work on Linux. Why?
  2. Could we add a test for this? We have a Mac leg, ideally we could just try to cross-compile for ARM64.

if (EnableRuntimePackDownload)
{
// We need to download the target runtime pack
TaskItem runtimePackToDownload = new TaskItem(targetIlcPackName);
Copy link
Member

Choose a reason for hiding this comment

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

Do we know why this condition is not needed for other platforms? -r osx-x64 on osx-arm64 or -r linux-arm64 on linux-x64 etc.

Copy link
Member Author

@filipnavara filipnavara Feb 23, 2023

Choose a reason for hiding this comment

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

I'm pretty sure it's needed for those as well. It's just that the original reporter happened to run things in order that populated the NuGet cache.

Weirdly I can confirm that works... will report back when I analyze the binlog.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's actually quite a mystery. It's not in _PackageToDownload but it's restored by the Restore task right after that. The only input that could be relevant is Microsoft.DotNet.ILCompiler dependency without a RID.

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 difference is actually the dependency of the ILCompiler package.

This is the working one:

    "net8.0/osx-x64": {
      "Microsoft.DotNet.ILCompiler/8.0.0-preview.1.23110.8": {
        "type": "package",
        "dependencies": {
          "runtime.osx-x64.Microsoft.DotNet.ILCompiler": "8.0.0-preview.1.23110.8"
        },
        "build": {
          "build/Microsoft.DotNet.ILCompiler.props": {},
          "build/Microsoft.DotNet.ILCompiler.targets": {}
        }
      },

This is the non-working one:

    "net8.0/osx-arm64": {
      "Microsoft.DotNet.ILCompiler/8.0.0-preview.1.23110.8": {
        "type": "package",
        "build": {
          "build/Microsoft.DotNet.ILCompiler.props": {},
          "build/Microsoft.DotNet.ILCompiler.targets": {}
        }
      },

The runtime.json file in https://nuget.info/packages/Microsoft.DotNet.ILCompiler/8.0.0-preview.1.23110.8 doesn't have the osx-arm64 entry at all.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Weirdly I can confirm that works... will report back when I analyze the binlog.

Ah, same here, amd64 -> arm64 is restoring. I started testing it in a VM and made a Dockerfile 😅

# on linux host, make sure the environment is ready for cross-arch execution:
#    docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

FROM amd64/ubuntu:22.04

RUN apt update && apt install -y curl build-essential clang libicu70 file qemu-user-static binutils-aarch64-linux-gnu debootstrap qemu binfmt-support

RUN curl -SLO https://raw.githubusercontent.com/dotnet/arcade/main/eng/common/cross/build-rootfs.sh
RUN curl --create-dirs --output-dir arm64 -SLO https://raw.githubusercontent.com/dotnet/arcade/main/eng/common/cross/arm64/sources.list.jammy
RUN bash build-rootfs.sh arm64 jammy lldb14 --rootfsdir /crossrootfs/arm64

RUN mkdir ~/.dotnet && curl -sSL https://aka.ms/dotnet/8.0.1xx/daily/dotnet-sdk-linux-x64.tar.gz | tar xzf - -C ~/.dotnet

ENV PATH=${PATH}:/root/.dotnet

RUN dotnet new console -n app1
RUN echo '<configuration><packageSources><add key="dotnet8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json" /></packageSources></configuration>' > nuget.config
RUN dotnet publish app1 -p:PublishAot=true -o dist -r linux-arm64 -p:SysRoot=/crossrootfs/arm64

ENTRYPOINT ["file", "dist/app1"]

docker build . -t test-arm64 followed by docker run test-arm64 prints:

dist/app1: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=19ec64d2622bbc890e741938f651d1473c0e9e50, for GNU/Linux 3.7.0, with debug_info, not stripped

Copy link
Member Author

Choose a reason for hiding this comment

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

Glad to have secondary confirmation for what is happening. Microsoft.DotNet.ILCompiler has dependency for all the linux* RIDs on the RID-specific packages so it makes the restore working. osx-arm64 was the only outlier (but we are likely to hit this again with the ios-like platforms soon).

@filipnavara
Copy link
Member Author

filipnavara commented Feb 23, 2023

It's not clear to me why this is only a problem for Mac. I think I've seen people successfully make this work on Linux. Why?

I don't think it's Mac specific problem. I never hit this before because I already had the NuGet packages cached. I'm very much convinced it's broken for all SDK-based (ie. .NET7+ PublishAot=true) cross-compiling scenarios when the packages are not already present in the NuGet cache.

Turns out, it is osx-x64>osx-arm64 specific. See discussion under comment above.

@filipnavara
Copy link
Member Author

filipnavara commented Feb 23, 2023

Could we add a test for this? We have a Mac leg, ideally we could just try to cross-compile for ARM64.

I agree a test would be nice. Unfortunately I am not very familiar with the dotnet/sdk repository and its test infrastructure. I'm not sure how to ensure such a test would not inadvertently get packages from the NuGet cache. It would be possible to test the output of the MSBuild task but testing the whole end-to-end scenario seems a bit tricky.

@agocke
Copy link
Member

agocke commented Feb 23, 2023

I just tried this locally on a Linux-x64 machine for linux-musl-arm64. The result is:

$ dotnet publish -r linux-musl-x64 -p:PublishAot=true hello.csproj
MSBuild version 17.4.1+9a89d02ff for .NET
Determining projects to restore...
Restored /home/andy/tmp/hello/hello.csproj (in 4.96 sec).
hello -> /home/andy/tmp/hello/bin/Debug/net7.0/linux-musl-x64/hello.dll
/home/andy/.local/share/dnvm/dn/sdk/7.0.102/Sdks/Microsoft.DotNet.ILCompiler/build/Microsoft.NETCore.Native.Publish.targets(71,5): error : Add a PackageReference for 'runtime.linux-musl-x64.Microsoft.DotNet.ILCompiler' to allow cross-compilation for x64 [/home/andy/tmp/hello/hello.csproj]

So my question is: why is that error message not appearing? Because it seems like that would force the presence of that runtime pack.

@filipnavara
Copy link
Member Author

filipnavara commented Feb 23, 2023

So my question is: why is that error message not appearing? Because it seems like that would force the presence of that runtime pack.

Would you happen to have a .binlog? I can compare it to the one I got on my Mac.

I don't hit the condition because IlcHostPackagePath is non-empty and RuntimePackagePath is empty (ie. exact opposite of the check).

@agocke
Copy link
Member

agocke commented Feb 23, 2023

binlog.zip

@filipnavara
Copy link
Member Author

filipnavara commented Feb 23, 2023

binlog.zip

Thanks! That's incredibly weird to me, IlcHostPackageName is the linux-musl-x64 one. In my case it's osx-x64 on Intel Mac (or under Rosetta) irrespective of the target RID.

The IlcHostPackageName construction doesn't sound right. It mixes target OS and host arch. That would explain why it behaves differently when cross-compiling for different OS vs different arch.

@filipnavara
Copy link
Member Author

dotnet/runtime#82558 is an alternative fix for the original problem. I suppose this change is not strictly necessary if that PR is merged. However, the reason why the other fix works is a mere side-effect of the Microsoft.DotNet.ILCompiler reference. 🤷🏻‍♂️

@agocke
Copy link
Member

agocke commented Feb 23, 2023

Tbh, this code is getting kinda complex and I'm not sure I'm understanding all the nuances.

I think we need to come up with a doc or something similar that explains exactly what UX should be when a RID is specified that:

  1. Isn't the same as the current SDK RID
  2. Is/isn't an explicitly supported RID
  3. Is a non-portable RID, like ubuntu-22.04.

@am11
Copy link
Member

am11 commented Feb 23, 2023

The alternative fix to bring osx-arm64 to the same plan as (the existing) {freebsd,linux,win}-arm64 looks great.

Is a non-portable RID, like ubuntu-22.04.

Non-portable RIDs are not supported yet. I hope that we come up with a better strategy so non-portable RIDs are not needed for NativeAOT for source-build at all, otherwise it will complicate a lot of things and we will be in the same situation as we are with corehost.

@filipnavara
Copy link
Member Author

Tbh, this code is getting kinda complex and I'm not sure I'm understanding all the nuances.

I am on the same boat. :-)

I think we need to come up with a doc or something similar that explains exactly what UX should be when a RID is specified that:

  1. Isn't the same as the current SDK RID
  2. Is/isn't an explicitly supported RID
  3. Is a non-portable RID, like ubuntu-22.04.

Agreed, this should be clearly specified.

  1. a) I would expect cross-arch builds to work. That should be fairly straightforward nowadays for the framework assemblies and ILCompiler. It gets a bit trickier when the platform linker gets involved but at least on macOS the default linker is capable of switching archs/targets. I wouldn't expect it to be a problem with LLVM on Linux. Not sure what's the status on Windows.
    b) At least some limited support of cross-OS is necessary. This will be required for the new iOS-like platforms with osx-x64/arm64 hosts. I would also expect linux-* and linux-musl-* to be feasible but I don't think it's a strict requirement. At the moment this is totally uncharted territory that's likely broken in more than one way.
  2. That's currently guarded by the SDK/installer much to my chagrin. New platforms need to update it, and I believe there's some code that produces human readable error.
  3. I guess it may depend on the outcome of Simplify RID Model designs#260

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

Successfully merging this pull request may close these issues.

[NativeAOT] cross-compiling to osx-arm64 from osx-x64 does not work
3 participants