Skip to content

Commit 930be83

Browse files
committed
add native aot
1 parent 879355c commit 930be83

File tree

8 files changed

+92
-4
lines changed

8 files changed

+92
-4
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdio.h>
2+
3+
extern "C" {
4+
int cs_add(int a, int b);
5+
int cs_multiply(int a, int b);
6+
}
7+
8+
int main() {
9+
printf("cs_add(3,4)=%d\n", cs_add(3, 4));
10+
printf("cs_multiply(5,6)=%d\n", cs_multiply(5, 6));
11+
return 0;
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Runtime.InteropServices;
2+
3+
public static class MathLib {
4+
[UnmanagedCallersOnly(EntryPoint = "cs_add")]
5+
public static int Add(int a, int b) => a + b;
6+
7+
[UnmanagedCallersOnly(EntryPoint = "cs_multiply")]
8+
public static int Multiply(int a, int b) => a * b;
9+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import("detect.sdks.find_dotnet")
2+
3+
function test_build(t)
4+
if is_subhost("msys") then
5+
return t:skip("csharp not supported on msys")
6+
end
7+
local dotnet = find_dotnet()
8+
if dotnet and dotnet.sdkver then
9+
t:build()
10+
else
11+
return t:skip("dotnet sdk not found")
12+
end
13+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_rules("mode.debug", "mode.release")
2+
3+
target("cslib")
4+
set_kind("shared")
5+
add_files("src/cslib/*.cs")
6+
set_values("csharp.publish_aot", "true")
7+
8+
target("app")
9+
set_kind("binary")
10+
add_deps("cslib")
11+
add_files("src/app/*.cpp")

xmake/modules/core/tools/dotnet.lua

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ end
9797

9898
-- make the build arguments list
9999
function buildargv(self, sourcefiles, targetkind, targetfile, flags, opt)
100-
local argv = {"build"}
100+
-- use `dotnet publish` for NativeAOT, otherwise `dotnet build`
101+
local target = opt and opt.target
102+
local publish_aot = target and target:values("csharp.publish_aot")
103+
local argv = {publish_aot and "publish" or "build"}
101104

102105
-- add .csproj file
103106
local csprojfile = _get_csprojfile(opt)
@@ -123,4 +126,11 @@ function build(self, sourcefiles, targetkind, targetfile, flags, opt)
123126
os.mkdir(path.directory(targetfile))
124127
local program, argv = buildargv(self, sourcefiles, targetkind, targetfile, flags, opt)
125128
os.runv(program, argv, {envs = self:runenvs()})
129+
130+
-- fix install_name for NativeAOT shared library on macOS
131+
local target = opt and opt.target
132+
local publish_aot = target and target:values("csharp.publish_aot")
133+
if publish_aot and targetkind == "shared" and self:is_plat("macosx", "iphoneos", "watchos") then
134+
os.runv("install_name_tool", {"-id", "@rpath/" .. path.filename(targetfile), targetfile})
135+
end
126136
end

xmake/rules/csharp/config.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ function main(target)
4545

4646
target:data_set("csharp.csproj", csprojfile)
4747

48+
-- for NativeAOT shared library, export targetfile directly for C/C++ consumers
49+
-- dotnet outputs without lib prefix, so we use syslinks with full path
50+
local publish_aot = target:values("csharp.publish_aot")
51+
if publish_aot and target:is_shared() then
52+
target:data_set("inherit.links.deplink", false)
53+
target:add("ldflags", target:targetfile(), {interface = true, force = true})
54+
end
55+
4856
-- add native shared library search paths for P/Invoke
4957
for _, dep in ipairs(target:orderdeps()) do
5058
if dep:is_shared() and not dep:rule("csharp.build") then

xmake/rules/csharp/generator/properties.lua

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,27 @@ function _resolve_assembly_name(context)
6767
end
6868

6969

70+
-- resolve runtime identifier from user config or auto-detect from target plat/arch
71+
-- e.g. "osx-x64", "osx-arm64", "linux-x64", "win-x64"
72+
function _resolve_runtime_identifier(context)
73+
local rid = _get_target_value(context.target, "csharp.runtime_identifier")
74+
if rid then
75+
return rid
76+
end
77+
-- auto-detect RID when publish_aot is enabled
78+
local publish_aot = _get_target_value(context.target, "csharp.publish_aot")
79+
if not publish_aot then
80+
return nil
81+
end
82+
local target = context.target
83+
local plat = target:plat()
84+
local arch = target:arch()
85+
local rid_arch = ({x86_64 = "x64", i386 = "x86", x64 = "x64", x86 = "x86",
86+
arm64 = "arm64", ["arm64-v8a"] = "arm64", armv7 = "arm"})[arch] or arch
87+
local rid_os = ({macosx = "osx", linux = "linux", windows = "win", mingw = "win"})[plat] or plat
88+
return rid_os .. "-" .. rid_arch
89+
end
90+
7091
-- register a single-value csharp.* property entry
7192
function _register_property(register, suffix, xml, default, extra)
7293
local entry = table.join({
@@ -128,7 +149,7 @@ function main()
128149
_register_property(register, "generate_documentation_file", "GenerateDocumentationFile")
129150
_register_property(register, "documentation_file", "DocumentationFile")
130151

131-
_register_property(register, "runtime_identifier", "RuntimeIdentifier")
152+
register({kind = "property", xml = "RuntimeIdentifier", resolve = _resolve_runtime_identifier})
132153
_register_list_property(register, "runtime_identifiers", "RuntimeIdentifiers")
133154
_register_property(register, "self_contained", "SelfContained")
134155
_register_property(register, "use_app_host", "UseAppHost")

xmake/rules/csharp/xmake.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,14 @@
115115
rule("csharp.build")
116116
set_sourcekinds("cs")
117117
on_load(function (target)
118-
-- dotnet always outputs .dll for libraries, and no prefix
119118
if target:is_shared() or target:is_static() then
119+
-- dotnet always outputs without lib prefix
120120
target:set("prefixname", "")
121-
target:set("extension", ".dll")
121+
-- managed libraries use .dll, NativeAOT uses native format (.dylib/.so/.dll)
122+
local publish_aot = target:values("csharp.publish_aot")
123+
if not publish_aot then
124+
target:set("extension", ".dll")
125+
end
122126
end
123127
end)
124128
on_config("config")

0 commit comments

Comments
 (0)