dotnet / runtime

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

NativeAOT library folder structure hygiene #108649

Open JCash opened 2 weeks ago

JCash commented 2 weeks ago

Description

Currently, when building a C++ native aot app, you need to specify the runtime libraries with full paths, or clang will automatically choose the the .dylib files.

Reproduction Steps

Use -Lpathtolibs -lSystem.IO.Compression.Native and it will link dynamically, even though I'm looking for a statically linked executable.

This makes maintenance non-standard and more time consuming (and error prone) than needed.

Expected behavior

I'd like the shared libraries in a different folder. E.g. "./shared/" or similar.

Actual behavior

I get a dynamically linked executable.

Regression?

No response

Known Workarounds

The current workaround is to put full absolute paths on the command line to clang.

Configuration

DotNet 9 rc1

Other information

No response

dotnet-policy-service[bot] commented 2 weeks ago

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

am11 commented 2 weeks ago

With bfd and lld linkers, we can use the colon syntax -Lpathtolibs -l:libSystem.IO.Compression.Native.a when both .a and .dylib (or .so on linux) are in the same directory, but the mac's default linker (ld64) doesn't allow the colon syntax.

Can you describe the use-case why do you need to manually link library from framework directory? Normally PublishAot=true takes care of it for us without needing us to locate the package directories etc.

To run into this issue, you anyway need to know the full path:

~/.nuget/packages/runtime.$(RID).microsoft.dotnet.ilcompiler/$(version)/framework/libSystem.IO.Compression.Native.dylib
~/.nuget/packages/runtime.$(RID).microsoft.dotnet.ilcompiler/$(version)/framework/libSystem.IO.Compression.Native.a
MichalStrehovsky commented 2 weeks ago

The dylib/so doesn't even need to be in the package, it's not used. We probably package it by mistake (JIT-based version of the runtime needs these, but not the AOT version that links them statically).

JCash commented 2 weeks ago

Can you describe the use-case why do you need to manually link library from framework directory?

The use case is that we use NativeAOT to create a static library, that we then use in our C++ engine. I know of at least one other game engine looking to use this setup (we're just further along in the process).

Oh, and another hygiene issue, is that for Windows, you need to add an extra string on the libraries. It feels like this could change in any release, so perhaps now is a good time (i.e. in dotnet9 rc2)? This code works for macOS and windows. (I haven't tested Linux yet)

String aotSuffix = "";
if (isWindows(platform))
    aotSuffix = ".Aot";
paths.add(getLibName(platform, "System.IO.Compression.Native" + aotSuffix));
paths.add(getLibName(platform, "System.Globalization.Native" + aotSuffix));
MichalStrehovsky commented 2 weeks ago

Oh, and another hygiene issue, is that for Windows, you need to add an extra string on the libraries. It feels like this could change in any release, so perhaps now is a good time (i.e. in dotnet9 rc2)? This code works for macOS and windows. (I haven't tested Linux yet)

It's not just about the Aot suffix. The entire list of native libraries to link is an implementation detail and subject to change without notice.

Note that building static libraries is in general unsupported because of all of these rough edges. I strongly recommend building a shared library instead.

am11 commented 2 weeks ago

This should take care of it https://github.com/dotnet/runtime/compare/main...am11:runtime:patch-14 (haven't tested yet).

JCash commented 2 weeks ago

Oh, wow, I hadn't seen that before. So, in essence unsupported means it could actually be removed at any point. That's not good to build upon, and I need to think about it. Adding shared library support it just a much bigger task, and not sure how it'd work on e.g wasm.

I'm quite sure it's never been brought up by the Dotnet team in our private Discord chat. I'll have to raise the issue there as well.

MichalStrehovsky commented 2 weeks ago

Unsupported just means you might need to support yourself. I don't think we'd ever go and remove this. But:

Things like that.

and not sure how it'd work on e.g wasm.

Native AOT doesn't support WASM as of .NET 9 and there's no concrete plans for that for .NET 10 that I know of either.

JCash commented 2 weeks ago

I don't think we'd ever go and remove this.

Yeah, while I personally understand the reasoning, it's a different beast professionally supporting a vast number of developers that want to ship products uninterrupted.

I think if changes are limited to major versions (9 -> 10 etc), then it's manageable imho. However, I think that "unsupported" needs to be addressed on that page. (My five cents)

Native AOT doesn't support WASM as of .NET 9 and there's no concrete plans for that for .NET 10 that I know of either.

Understandable, but web games are huge, ppl seem to think it's dead but it's most certainly not. There are many successful game portals around, like poki.com. Our customers have shifted from Mobile-first to Web-first (for many reasons). So, if games are part of the goal for the nativeaot project, then I'd look into wasm as a target for sure.