Skip to content

NativeAOT + classlib + macOS host + linux-bionic-arm64 target: doesn't work out of the box / inscrutable errors #101727

@jonpryor

Description

@jonpryor

Description

Trying to use NativeAOT to build a linux-bionic-arm64 shared library from macOS does not work out of the box.

Reproduction Steps

% dotnet new classlib -n HelloBionicSharedLib
% cd HelloBionicSharedLib
% dotnet publish -c Release -r linux-bionic-arm64 -p:PublishAotUsingRuntimePack=true -p:PublishAot=true

Expected behavior

Above dotnet publish should produce a .so file.

Actual behavior

…
clang : error : invalid linker name in argument '-fuse-ld=lld'
$HOME/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.4/build/Microsoft.NETCore.Native.Unix.targets(236,5): error :
Symbol stripping tool ('llvm-objcopy' or 'objcopy') not found in PATH. Try installing appropriate package for llvm-objcopy or objcopy to resolve the problem or set the StripSymbols property to false to disable symbol stripping.

Yes, neither llvm-objcopy nor objcopy are in $PATH, but the first line "hides" the second; invalid linker name in argument '-fuse-ld=lld' looks like the "root" error, and doesn't really make sense by itself.

The second line is actually explanatory, if you get past reading the first. (Yes, reading comprehension is hard. Regardless, error messages should be actionable, and the first line is not actionable.)

If we fix that up:

% export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin:$PATH

…then it still fails to build:

% dotnet publish -c Release -r linux-bionic-arm64 -p:PublishAotUsingRuntimePack=true -p:PublishAot=true

ld.lld : error : version script assignment of 'V1.0' to symbol '_init' failed: symbol not defined
ld.lld : error : version script assignment of 'V1.0' to symbol '_fini' failed: symbol not defined
clang-17 : error : linker command failed with exit code 1 (use -v to see invocation)
$HOME/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.4/build/Microsoft.NETCore.Native.targets(367,5): error MSB3073: The command ""clang" "obj/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.o" -o "bin/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.so" -Wl,--version-script=obj/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.exports -Wl,--export-dynamic -gz=zlib -fuse-ld=lld $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libbootstrapperdll.o $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libRuntime.WorkstationGC.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libeventpipe-disabled.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libstdc++compat.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Globalization.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.IO.Compression.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Security.Cryptography.Native.OpenSsl.a --target=aarch64-linux-android21 -g -Wl,-rpath,'$ORIGIN' -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,--discard-all -Wl,--gc-sections -Wl,-T,"obj/Release/net8.0/linux-bionic-arm64/native/sections.ld"" exited with code 1.

#92272 (comment) suggests adding the following snippet to the .csproj:

<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-bionic'">
  <LinkerArg Include="-Wl,--defsym,_init=__libc_init" />
  <LinkerArg Include="-Wl,--defsym,_fini=__libc_fini" />
</ItemGroup

This doesn't work because the $(RuntimeIdentifier) comparison is wrong, but if we fix that:

  <ItemGroup Condition="$(RuntimeIdentifier.StartsWith('linux-bionic'))">
    <LinkerArg Include="-Wl,--defsym,_init=__libc_init" />
    <LinkerArg Include="-Wl,--defsym,_fini=__libc_fini" />
  </ItemGroup>

…then it still fails to build:

ld.lld : error : --defsym:1: symbol not found: __libc_fini
ld.lld : error : --defsym:1: symbol not found: __libc_init
ld.lld : error : --defsym:1: symbol not found: __libc_fini
ld.lld : error : --defsym:1: symbol not found: __libc_init
ld.lld : error : --defsym:1: symbol not found: __libc_fini
clang-17 : error : linker command failed with exit code 1 (use -v to see invocation)
$HOME/.nuget/packages/microsoft.dotnet.ilcompiler/8.0.4/build/Microsoft.NETCore.Native.targets(367,5): error MSB3073:
The command ""clang" "obj/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.o" -o "bin/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.so" -Wl,--version-script=obj/Release/net8.0/linux-bionic-arm64/native/HelloBionicSharedLib.exports -Wl,--export-dynamic -Wl,--defsym,_init=__libc_init -Wl,--defsym,_fini=__libc_fini -gz=zlib -fuse-ld=lld $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libbootstrapperdll.o $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libRuntime.WorkstationGC.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libeventpipe-disabled.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libstdc++compat.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Globalization.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.IO.Compression.Native.a $HOME/.nuget/packages/microsoft.netcore.app.runtime.nativeaot.linux-bionic-arm64/8.0.4/runtimes/linux-bionic-arm64/native/libSystem.Security.Cryptography.Native.OpenSsl.a --target=aarch64-linux-android21 -g -Wl,-rpath,'$ORIGIN' -Wl,--build-id=sha1 -Wl,--as-needed -Wl,-e0x0 -pthread -ldl -lz -llog -lm -shared -Wl,-z,relro -Wl,-z,now -Wl,--eh-frame-hdr -Wl,--discard-all -Wl,--gc-sections -Wl,-T,"obj/Release/net8.0/linux-bionic-arm64/native/sections.ld"" exited with code 1.

Regression?

No.

Known Workarounds

A cause of the original ld.lld : error : version script assignment of 'V1.0' to symbol '_init' failed: symbol not defined is that none of the .a files used in the link command provide that symbol. Perhaps one of them should?

In the meantime, android-bionic.md has a Known issues section which suggests adding a -Wl,--undefined-version linker argument.

Update HelloBionicSharedLib.csproj to end with:

  <Import Project="HelloBionicSharedLib.targets" />

then add HelloBionicSharedLib.targets to the HelloBionicSharedLib directory with contents:

<Project>
  <ItemGroup Condition="$(RuntimeIdentifier.StartsWith('linux-bionic'))">
    <LinkerArg Include="-Wl,--undefined-version" />
  </ItemGroup>
</Project>

and the dotnet publish command now succeeds without error, producing a bin/Release/net8.0/linux-bionic-arm64/publish/HelloBionicSharedLib.so artifact.

Configuration

.NET Configuration:

  • .NET 8.0.204
  • macOS 14.4.1
  • x64

I have no idea if it's specific to this configuration.

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-NativeAOT-coreclrin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions