Skip to content

Commit ea57982

Browse files
authored
[tasks] Add auto runtime initialization template to LibraryBuilder (#83050)
* [tasks] Add auto runtime initialization template to LibraryBuilder * Grab shared library directory * [tasks] Extend auto initialization template to account for customization * Revert "Grab shared library directory" This reverts commit bc86f2b. * Remove platform specific naming * [tasks] Move App Context setup back to autoinit.c * Remove registering bundled modules and debugging until they can be validated * Remove unnecessary wrapper * Grab bundle_path later without eglib Setting bundle_path in constructor may be too early for environment variables to be set so grab it first thing when initializing the runtime. Use getenv directly instead of calling into eglib with just one api * Rename AssetsPath to AssembliesLocation * Move assembly loading into separate function * Remove unnecessary function * Cleanup CMakeLists template indentation * Add dotnet header to autoinit.c * Default bundle_path if assemblies path environment variable not set * Pass bundle_path to load assemblies * Add logging and abort on failures * Load assemblies with partial name * Clean up targets and unneeded properties * Rename source file * Remove preload hook and make out of memory error more generic * Throw when no exported symbols are found * Remove aot data load prehook and aotdata generation * Address feedback * Address more feedback * Add various fixes and make bundle_path a local variable * Reintroduce load aot data hook in autoinit with guard * Fix closing tag * Include guard library-builder.h * Fix typo
1 parent b6319cd commit ea57982

File tree

10 files changed

+328
-53
lines changed

10 files changed

+328
-53
lines changed

src/mono/msbuild/android/build/AndroidApp.targets

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@
7676
<_AOTMode Condition="'$(ForceFullAOT)' == 'true'">Full</_AOTMode>
7777
</PropertyGroup>
7878

79+
<PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
80+
<_UsesRuntimeInitCallback>$(UsesRuntimeInitCallback)</_UsesRuntimeInitCallback>
81+
<_UsesRuntimeInitCallback Condition="'$(_UsesRuntimeInitCallback)' == ''">true</_UsesRuntimeInitCallback>
82+
</PropertyGroup>
83+
7984
<ItemGroup>
8085
<MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'arm'" Include="mtriple=armv7-linux-gnueabi" />
8186
<MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'arm64'" Include="mtriple=aarch64-linux-android" />
@@ -85,6 +90,8 @@
8590
<MonoAOTCompilerDefaultAotArguments Include="static" />
8691
<MonoAOTCompilerDefaultAotArguments Include="dwarfdebug" />
8792
<MonoAOTCompilerDefaultAotArguments Condition="'$(_IsLibraryMode)' == 'true'" Include="direct-icalls" />
93+
<MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) == ''" Include="runtime-init-callback" />
94+
<MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) != ''" Include="runtime-init-callback=$(CustomRuntimeInitCallback)" />
8895

8996
<MonoAOTCompilerDefaultAotArguments Include="nimt-trampolines=2000" />
9097
<MonoAOTCompilerDefaultAotArguments Include="ntrampolines=10000" />
@@ -133,6 +140,12 @@
133140
Condition="'$(RunAOTCompilation)' == 'true'"
134141
DependsOnTargets="_AndroidBeforeAotCompileApp">
135142

143+
<PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
144+
<_EnableUnmanagedCallersOnlyMethodsExport>true</_EnableUnmanagedCallersOnlyMethodsExport>
145+
<_UseAotDataFile>$(UseAotDataFile)</_UseAotDataFile>
146+
<_UseAotDataFile Condition="'$(_UseAotDataFile)' == ''">false</_UseAotDataFile>
147+
</PropertyGroup>
148+
136149
<ItemGroup>
137150
<ProfiledAOTProfilePaths Include="$(MibcFilePath)" />
138151
</ItemGroup>
@@ -147,10 +160,6 @@
147160
<DirectPInvokes Include="libSystem.Security.Cryptography.Native.Android" />
148161
</ItemGroup>
149162

150-
<PropertyGroup>
151-
<_EnableUnmanagedCallersOnlyMethodsExport Condition="'$(_IsLibraryMode)' == 'true'">true</_EnableUnmanagedCallersOnlyMethodsExport>
152-
</PropertyGroup>
153-
154163
<MonoAOTCompiler
155164
AotModulesTablePath="$(_AotModuleTablePath)"
156165
Assemblies="@(_AotInputAssemblies)"
@@ -164,6 +173,7 @@
164173
Mode="$(_AOTMode)"
165174
OutputDir="$(_MobileIntermediateOutputPath)"
166175
OutputType="AsmOnly"
176+
UseAotDataFile="$(_UseAotDataFile)"
167177
UseLLVM="$(MonoEnableLLVM)">
168178
<Output TaskParameter="CompiledAssemblies" ItemName="AppAssembliesInternal" />
169179
</MonoAOTCompiler>

src/mono/msbuild/apple/build/AppleApp.targets

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,12 @@
9191
<_AOTMode Condition="'$(UseMonoJustInterp)' == 'true'">JustInterp</_AOTMode>
9292
</PropertyGroup>
9393

94-
<PropertyGroup>
95-
<_EnableUnmanagedCallersOnlyMethodsExport Condition="'$(_IsLibraryMode)' == 'true'">true</_EnableUnmanagedCallersOnlyMethodsExport>
94+
<PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
95+
<_EnableUnmanagedCallersOnlyMethodsExport>true</_EnableUnmanagedCallersOnlyMethodsExport>
96+
<_UseAotDataFile>$(UseAotDataFile)</_UseAotDataFile>
97+
<_UseAotDataFile Condition="'$(_UseAotDataFile)' == ''">false</_UseAotDataFile>
98+
<_UsesRuntimeInitCallback>$(UsesRuntimeInitCallback)</_UsesRuntimeInitCallback>
99+
<_UsesRuntimeInitCallback Condition="'$(_UsesRuntimeInitCallback)' == ''">true</_UsesRuntimeInitCallback>
96100
</PropertyGroup>
97101

98102
<ItemGroup>
@@ -104,6 +108,8 @@
104108
<MonoAOTCompilerDefaultAotArguments Include="dwarfdebug" />
105109
<MonoAOTCompilerDefaultAotArguments Condition="'$(TargetArchitecture)' == 'arm64'" Include="mattr=+crc" /> <!-- enable System.Runtime.Intrinsics.Arm (Crc32 and ArmBase for now) -->
106110
<MonoAOTCompilerDefaultAotArguments Include="direct-icalls" />
111+
<MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) == ''" Include="runtime-init-callback" />
112+
<MonoAOTCompilerDefaultAotArguments Condition="'$(_UsesRuntimeInitCallback)' == 'true' and $(CustomRuntimeInitCallback) != ''" Include="runtime-init-callback=$(CustomRuntimeInitCallback)" />
107113

108114
<MonoAOTCompilerDefaultAotArguments Include="nimt-trampolines=2000" />
109115
<MonoAOTCompilerDefaultAotArguments Include="ntrampolines=40000" />
@@ -166,6 +172,7 @@
166172
Mode="$(_AOTMode)"
167173
OutputDir="$(_MobileIntermediateOutputPath)"
168174
OutputType="AsmOnly"
175+
UseAotDataFile="$(_UseAotDataFile)"
169176
UseLLVM="$(MonoEnableLLVM)">
170177
<Output TaskParameter="CompiledAssemblies" ItemName="AppAssembliesInternal" />
171178
</MonoAOTCompiler>

src/mono/msbuild/common/LibraryBuilder.targets

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<PropertyGroup>
99
<_IsSharedLibrary>false</_IsSharedLibrary>
1010
<_IsSharedLibrary Condition="'$(NativeLib)' == 'shared'">true</_IsSharedLibrary>
11+
<_UsesCustomRuntimeInitCallback>false</_UsesCustomRuntimeInitCallback>
12+
<_UsesCustomRuntimeInitCallback Condition="$(CustomRuntimeInitCallback) != ''">true</_UsesCustomRuntimeInitCallback>
1113
</PropertyGroup>
1214

1315
<ItemGroup>
@@ -17,15 +19,18 @@
1719

1820
<LibraryBuilderTask
1921
Assemblies="@(AppAssembliesInternal)"
22+
AssembliesLocation="$(AssembliesLocation)"
2023
ExtraLinkerArguments="@(_ExtraLinkerArgs)"
2124
ExtraSources="@(_ExtraLibrarySources)"
2225
IsSharedLibrary="$(_IsSharedLibrary)"
23-
Name="$(AssemblyName)"
2426
MonoRuntimeHeaders="$(_MonoHeaderPath)"
27+
Name="$(AssemblyName)"
2528
OutputDirectory="$(BundleDir)"
2629
RuntimeIdentifier="$(RuntimeIdentifier)"
2730
RuntimeLibraries="@(_RuntimeLibraries)"
28-
TargetOS="$(TargetOS)">
31+
TargetOS="$(TargetOS)"
32+
UsesCustomRuntimeInitCallback="$(_UsesCustomRuntimeInitCallback)"
33+
UsesRuntimeInitCallback="$(_UsesRuntimeInitCallback)">
2934
<Output TaskParameter="OutputPath" PropertyName="LibraryOutputPath" />
3035
</LibraryBuilderTask>
3136
</Target>

src/tasks/LibraryBuilder/LibraryBuilder.cs

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class LibraryBuilderTask : AppBuilderTask
1919

2020
private string cmakeProjectLanguages = "";
2121
private string targetOS = "";
22+
private bool usesAOTDataFile;
23+
private List<string> exportedAssemblies = new List<string>();
2224

2325
/// <summary>
2426
/// The name of the library being generated
@@ -66,6 +68,23 @@ public bool IsSharedLibrary
6668
}
6769
}
6870

71+
/// <summary>
72+
/// Determines whether or not the mono runtime auto initialization
73+
/// template, autoinit.c, is used.
74+
/// </summary>
75+
public bool UsesCustomRuntimeInitCallback { get; set; }
76+
77+
/// <summary>
78+
/// Determines if there is a mono runtime init callback
79+
/// </summary>
80+
public bool UsesRuntimeInitCallback { get; set; }
81+
82+
/// <summary>
83+
/// The environment variable name that will point to where assemblies
84+
/// are located on the app host device.
85+
/// </summary>
86+
public string? AssembliesLocation { get; set; }
87+
6988
public bool StripDebugSymbols { get; set; }
7089

7190
/// <summary>
@@ -113,6 +132,17 @@ public override bool Execute()
113132
GatherAotSourcesObjects(aotSources, aotObjects, extraSources, linkerArgs);
114133
GatherLinkerArgs(linkerArgs);
115134

135+
File.WriteAllText(Path.Combine(OutputDirectory, "library-builder.h"),
136+
Utils.GetEmbeddedResource("library-builder.h"));
137+
138+
GenerateAssembliesLoader();
139+
140+
if (UsesRuntimeInitCallback && !UsesCustomRuntimeInitCallback)
141+
{
142+
WriteAutoInitializationFromTemplate();
143+
extraSources.AppendLine(" autoinit.c");
144+
}
145+
116146
WriteCMakeFileFromTemplate(aotSources.ToString(), aotObjects.ToString(), extraSources.ToString(), linkerArgs.ToString());
117147
OutputPath = BuildLibrary();
118148

@@ -122,14 +152,18 @@ public override bool Execute()
122152
private void GatherAotSourcesObjects(StringBuilder aotSources, StringBuilder aotObjects, StringBuilder extraSources, StringBuilder linkerArgs)
123153
{
124154
List<string> exportedSymbols = new List<string>();
125-
List<string> exportedAssemblies = new List<string>();
126155
bool hasExports = false;
127156

128157
foreach (CompiledAssembly compiledAssembly in CompiledAssemblies)
129158
{
130159
if (!string.IsNullOrEmpty(compiledAssembly.AssemblerFile))
131160
{
132-
aotSources.AppendLine(compiledAssembly.AssemblerFile);
161+
aotSources.AppendLine($" {compiledAssembly.AssemblerFile}");
162+
}
163+
164+
if (!usesAOTDataFile && !string.IsNullOrEmpty(compiledAssembly.DataFile))
165+
{
166+
usesAOTDataFile = true;
133167
}
134168

135169
if (!string.IsNullOrEmpty(compiledAssembly.LlvmObjectFile))
@@ -145,10 +179,14 @@ private void GatherAotSourcesObjects(StringBuilder aotSources, StringBuilder aot
145179

146180
if (symbolsAdded > 0)
147181
{
148-
exportedAssemblies.Add(Path.GetFileName(compiledAssembly.Path));
182+
exportedAssemblies.Add(Path.GetFileNameWithoutExtension(compiledAssembly.Path));
149183
}
150184
}
151185
}
186+
if (IsSharedLibrary && exportedAssemblies.Count == 0)
187+
{
188+
throw new LogAsErrorException($"None of the compiled assemblies contain exported symbols. Resulting shared library would be unusable.");
189+
}
152190

153191
// for android, all symbols to keep go in one linker script
154192
//
@@ -167,11 +205,9 @@ private void GatherAotSourcesObjects(StringBuilder aotSources, StringBuilder aot
167205
WriteExportedSymbolsArg(MobileSymbolFileName, linkerArgs);
168206
}
169207

170-
WriteAssembliesToLoadList(exportedAssemblies);
171-
172208
foreach (ITaskItem item in ExtraSources)
173209
{
174-
extraSources.AppendLine(item.ItemSpec);
210+
extraSources.AppendLine($" {item.ItemSpec}");
175211
}
176212
}
177213

@@ -226,8 +262,30 @@ private static void WriteLinkerScriptFile(string exportsFile, List<string> expor
226262
.Replace("%GLOBAL_SYMBOLS%", globalExports));
227263
}
228264

265+
private void WriteAutoInitializationFromTemplate()
266+
{
267+
File.WriteAllText(Path.Combine(OutputDirectory, "autoinit.c"),
268+
Utils.GetEmbeddedResource("autoinit.c")
269+
.Replace("%ASSEMBLIES_LOCATION%", !string.IsNullOrEmpty(AssembliesLocation) ? AssembliesLocation : "DOTNET_LIBRARY_ASSEMBLY_PATH")
270+
.Replace("%RUNTIME_IDENTIFIER%", RuntimeIdentifier));
271+
}
272+
273+
private void GenerateAssembliesLoader()
274+
{
275+
var assemblyPreloaders = new List<string>();
276+
foreach (string exportedAssembly in exportedAssemblies)
277+
{
278+
assemblyPreloaders.Add($"preload_assembly(\"{exportedAssembly}\");");
279+
}
280+
281+
File.WriteAllText(Path.Combine(OutputDirectory, "preloaded-assemblies.c"),
282+
Utils.GetEmbeddedResource("preloaded-assemblies.c")
283+
.Replace("%ASSEMBLIES_PRELOADER%", string.Join("\n ", assemblyPreloaders)));
284+
}
285+
229286
private void WriteCMakeFileFromTemplate(string aotSources, string aotObjects, string extraSources, string linkerArgs)
230287
{
288+
string extraDefinitions = GenerateExtraDefinitions();
231289
// BundleDir
232290
File.WriteAllText(Path.Combine(OutputDirectory, "CMakeLists.txt"),
233291
Utils.GetEmbeddedResource("CMakeLists.txt.template")
@@ -237,35 +295,21 @@ private void WriteCMakeFileFromTemplate(string aotSources, string aotObjects, st
237295
.Replace("%MonoInclude%", MonoRuntimeHeaders)
238296
.Replace("%AotSources%", aotSources)
239297
.Replace("%AotObjects%", aotObjects)
298+
.Replace("%ExtraDefinitions%", extraDefinitions)
240299
.Replace("%ExtraSources%", extraSources)
241300
.Replace("%LIBRARY_LINKER_ARGS%", linkerArgs));
242301
}
243302

244-
private void WriteAssembliesToLoadList(List<string> assemblies)
303+
private string GenerateExtraDefinitions()
245304
{
246-
string content;
305+
var extraDefinitions = new StringBuilder();
247306

248-
if (assemblies.Count == 0)
249-
{
250-
content = " return NULL;";
251-
}
252-
else
307+
if (usesAOTDataFile)
253308
{
254-
StringBuilder sb = new StringBuilder();
255-
sb.AppendLine($" char** assembly_list = (char**)malloc({assemblies.Count.ToString()} * sizeof(char*));");
256-
257-
for (int i = 0; i < assemblies.Count; i++)
258-
{
259-
sb.AppendLine($" assembly_list[{i.ToString()}] = \"{assemblies[i]}\";");
260-
}
261-
262-
sb.AppendLine(" return assembly_list;");
263-
content = sb.ToString();
309+
extraDefinitions.AppendLine("add_definitions(-DUSES_AOT_DATA=1)");
264310
}
265311

266-
File.WriteAllText(Path.Combine(OutputDirectory, "assembly_list.c"),
267-
Utils.GetEmbeddedResource("assembly_list.c")
268-
.Replace("%LOADABLE_ASSEMBLIES%", content));
312+
return extraDefinitions.ToString();
269313
}
270314

271315
private string BuildLibrary()

src/tasks/LibraryBuilder/LibraryBuilder.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<Compile Include="..\Common\Builders\AppBuilderTask.cs" />
2020
<Compile Include="..\Common\Builders\AndroidProject.cs" />
2121
<Compile Include="..\Common\Builders\CompiledAssembly.cs" />
22+
<Compile Include="..\Common\LogAsErrorException.cs" />
2223
<Compile Include="..\AppleAppBuilder\TargetOS.cs" />
2324
<Compile Include="..\AppleAppBuilder\Xcode.cs" />
2425
</ItemGroup>

src/tasks/LibraryBuilder/Templates/CMakeLists.txt.template

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ project(%LIBRARY_NAME%)
55
enable_language(%CMAKE_LANGS%)
66

77
set(DOTNET_AOT_SOURCES
8-
%AotSources%
8+
%AotSources%
99
)
1010
set(DOTNET_AOT_OBJECTS
11-
%AotObjects%
11+
%AotObjects%
1212
)
1313
set(DOTNET_EXTRA_SOURCES
14-
%ExtraSources%
15-
assembly_list.c
16-
)
14+
library-builder.h
15+
preloaded-assemblies.c
16+
%ExtraSources%)
1717

1818
include_directories("%MonoInclude%")
1919

2020
add_library(
2121
aot_library STATIC
22-
${DOTNET_AOT_SOURCES}
22+
${DOTNET_AOT_SOURCES}
2323
)
2424
target_link_libraries(
2525
aot_library
@@ -35,9 +35,10 @@ add_library(
3535
if(TARGETS_ANDROID)
3636
set(MOBILE_SYSTEM_LIBS
3737
libz.so
38-
log
38+
log
3939
)
40-
else()
40+
add_definitions(-DHOST_ANDROID=1)
41+
elseif(TARGETS_APPLE_MOBILE)
4142
set(MOBILE_SYSTEM_LIBS
4243
"-framework Foundation"
4344
"-framework Security"
@@ -46,12 +47,16 @@ else()
4647
"-lc++"
4748
"-liconv"
4849
)
50+
add_definitions(-DHOST_APPLE_MOBILE=1)
51+
else()
52+
message(FATAL_ERROR "Unsupported Platform. Ensure the TargetOS is supported by the LibraryBuilder and the platform specific libs are added here.")
4953
endif()
5054

55+
%ExtraDefinitions%
56+
5157
target_link_libraries(
5258
%LIBRARY_NAME%
5359
PUBLIC
5460
aot_library
5561
${MOBILE_SYSTEM_LIBS}
56-
%LIBRARY_LINKER_ARGS%
57-
)
62+
%LIBRARY_LINKER_ARGS%)

src/tasks/LibraryBuilder/Templates/assembly_list.c

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)