dotnet / runtime

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

Cannot build Native AOT for win32 on linux #108587

Open JCash opened 3 days ago

JCash commented 3 days ago

Description

The dotnet toolchain should make it easier to cross compile.

Reproduction Steps

On linux, build a native aot library

Expected behavior

I expect to be able to build it dotnet for WIn32 on a linux server.

Actual behavior

It outputs errors saying it's not supported.

Regression?

Previous (auto closed issue with discussion): https://github.com/dotnet/runtime/issues/107336

Known Workarounds

Currently, I have not been able to verify a workaround.

Configuration

Dotnet 9 RC1

Other information

No response

JCash commented 3 days ago

The current suggestions of @MichalStrehovsky does't seem to work fully as it still outputs the .dll:

    <NativeLib>static</NativeLib>
    <IlcUseEnvironmentalTools>True</IlcUseEnvironmentalTools>
    <DisableUnsupportedError>True</DisableUnsupportedError>

the .dll output

./NativeLibrary/obj/Release/net9.0/win-x64/ref/libNativeLibrary.dll
./NativeLibrary/obj/Release/net9.0/win-x64/refint/libNativeLibrary.dll
./NativeLibrary/obj/Release/net9.0/win-x64/libNativeLibrary.dll
./NativeLibrary/bin/Release/net9.0/win-x64/libNativeLibrary.dll

I've added a lib executable script to my PATH, and it does seem to produce a libNativeLibrary.lib. Next up is the question: is it static or dynamic (given that the .dll was still produced... 🤔 )

#!/usr/bin/env bash

wine ${WINDOWS_VCINSTALLDIR_2022}/bin/Hostx64/x64/lib.exe $*
Symbai commented 3 days ago

The dotnet toolchain should make it easier to cross compile.

Native AOT does not support cross-OS compilation 🤷‍♂️

JCash commented 3 days ago

Thanks. This discussion is more for the "moving forward" from the current support. There's really no reason it couldn't be a lot more user friendly in terms of cross compiling.

JCash commented 3 days ago

Part of the final problem, is getting dotnet/nuget to download the correct libraries so that I can link the final executable. Currently, I'm stuck on:

'./NativeLibrary/bin/Release/net9.0/win-x64/native/libNativeLibrary.lib' -> './build/win64/libNativeLibrary.lib'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libbootstrapperdll.o'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libRuntime.WorkstationGC.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libRuntime.VxsortEnabled.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libeventpipe-enabled.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libstandalonegc-enabled.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libSystem.Native.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libSystem.IO.Compression.Native.a'
clang++: error: no such file or directory: '/dynamo_home/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.win-x64/9.0.0-rc.1.24431.7/runtimes/win-x64/native/libSystem.Globalization.Native.a'

Is there a way to get it do download the packages specifically?

JCash commented 3 days ago

Adding to the project:

    <PackageReference Include="Microsoft.NETCore.App.Runtime.win-x64" Version="9.0.0-rc.1.24431.7" />

only gives me:

     /dynamo_home/NativeLibrary/libNativeLibrary.csproj : error NU1213: The package Microsoft.NETCore.App.Runtime.win-x64 9.0.0-rc.1.24431.7 has a package type DotnetPlatform that is incompatible with this project. 
    /dynamo_home/NativeLibrary/libNativeLibrary.csproj : error NU1213: The package Microsoft.NETCore.App.Runtime.win-x64 9.0.0-rc.1.24431.7 has a package type DotnetPlatform that is incompatible with this project. 

when building. SO it doesn't seem to respect the DisableUnsupportedError flag.

dotnet-policy-service[bot] commented 3 days ago

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

MichalStrehovsky commented 3 days ago
./NativeLibrary/obj/Release/net9.0/win-x64/ref/libNativeLibrary.dll
./NativeLibrary/obj/Release/net9.0/win-x64/refint/libNativeLibrary.dll
./NativeLibrary/obj/Release/net9.0/win-x64/libNativeLibrary.dll
./NativeLibrary/bin/Release/net9.0/win-x64/libNativeLibrary.dll

These are all managed dlls, not native DLLs. Output of AOT compilation goes to a /native subdirectory.

Part of the final problem, is getting dotnet/nuget to download the correct libraries so that I can link the final executable.

I think they were downloaded somewhere. Publish with a -bl parameter and inspect the binlog. It should be around the System.Private.Reflection.Execution.dll file that will be mentioned in the build outputs.

It doesn't look right clang++ is trying to run, I doubt it's going to be able to link the output. Windows libraries don't end in .a. We don't ship any Windows libraries in Unix .a files.

JCash commented 3 days ago

Yeah, that .a was posted a bit prematurely, as I hadn't updated the script. But I did a manual search for the .lib files and I couldn't find any on my system 🤔

Thanks! I'll check the -bl option to see if it reveals something.

As long as I can get hold of the .lib files, it should link (we have been cross compiling for windows for many years, so the setup itself works, it's just a new workflow with the dotnet libraries)

JCash commented 3 days ago

I did find the runtime libraries, not sure why they didn't turn up previously. So thanks for the hint!

I've finally managed to build and run my test my (C++) application using a build nativeAOT library for WIn64 on Linux. To summarize what I had to do:

For the curious, the clang call looks like (project source)

clang++ ${OPT} ${FLAGS} -o ${BUILD_DIR}/test \
    ${INCLUDES} \
    ${DEFINES} \
    ${LIBPATHS} \
    -l${BUILD_DIR}/${PREFIX_LIB}NativeLibrary${SUFFIX_LIB} \
    ${LIBS} \
    ${AOTBASE}/${PREFIX_LIB}bootstrapperdll${SUFFIX_OBJ} \
    ${AOTBASE}/${PREFIX_LIB}Runtime.WorkstationGC${SUFFIX_LIB} \
    ${AOTBASE}/${PREFIX_LIB}Runtime.VxsortEnabled${SUFFIX_LIB} \
    ${AOTBASE}/${PREFIX_LIB}eventpipe-enabled${SUFFIX_LIB} \
    ${AOTBASE}/${PREFIX_LIB}standalonegc-enabled${SUFFIX_LIB} \
    ${AOTBASE}/${PREFIX_LIB}System.IO.Compression.Native${AOTLIB_SUFFIX}${SUFFIX_LIB} \
    ${AOTBASE}/${PREFIX_LIB}System.Globalization.Native${AOTLIB_SUFFIX}${SUFFIX_LIB} \
    src/main.cpp

(The dotnet lib setup could be cleaner, as we're currently forced to use absolute paths, or it will link dynamically on macOS)

So, it's definitely possible to create NativeAOT Windows libraries and link executables on a Linux machine. I do hope that you could integrate these steps into you cross compilation guide, moving the eco system forward. (I know at least one other company looking to do the same)

Next up is Android builds on Linux...

JCash commented 2 days ago

Also, another caveat, is that if you use:

    <IntermediateOutputPath>{{BUILDDIR_CS}}</IntermediateOutputPath>
    <OutputPath>{{BUILDDIR_CS}}</OutputPath>

You need to make sure it's a relative path (forward slashes works for me), as the wine/dotnet doesn't work with unix paths starting with a / (/tmp/builddir/...).

Note: It ofc makes it quite awkward if you want to keep build artifacts in a completely different directory from the project directory. You have to use ../../ to make the paths relative.