diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props b/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
index 5ed981fedd4..5303d99c4f2 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
@@ -70,7 +70,8 @@ See the LICENSE file in the project root for more information.
-
+
+
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props b/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
index 2214b342372..9949a24ec02 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
@@ -61,7 +61,6 @@ See the LICENSE file in the project root for more information.
-
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.targets b/src/BuildIntegration/Microsoft.NETCore.Native.targets
index 03b5366cb00..4a334e6244d 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -31,6 +31,7 @@ See the LICENSE file in the project root for more information.
.obj
.o
.bc
+
.lib
.a
@@ -48,8 +49,12 @@ See the LICENSE file in the project root for more information.
.a
.html
+ .def
+ .exports
+
$(NativeIntermediateOutputPath)$(TargetName)$(NativeObjectExt)
$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)
+ $(NativeIntermediateOutputPath)$(TargetName)$(ExportsFileExt)
$(NativeObject)
$(NativeIntermediateOutputPath)$(TargetName).cpp
@@ -151,7 +156,8 @@ See the LICENSE file in the project root for more information.
-
+
+
@@ -193,6 +199,8 @@ See the LICENSE file in the project root for more information.
+
+
diff --git a/src/ILCompiler.Compiler/src/Compiler/ExportedMethodsRootProvider.cs b/src/ILCompiler.Compiler/src/Compiler/ExportedMethodsRootProvider.cs
index 11fa9c01f19..fcedbe2553b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/ExportedMethodsRootProvider.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/ExportedMethodsRootProvider.cs
@@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
namespace ILCompiler
@@ -18,27 +21,37 @@ public ExportedMethodsRootProvider(EcmaModule module)
_module = module;
}
- public void AddCompilationRoots(IRootingServiceProvider rootProvider)
+ public IEnumerable ExportedMethods
{
- foreach (var type in _module.GetAllTypes())
+ get
{
- foreach (var method in type.GetMethods())
+ foreach (var type in _module.GetAllTypes())
{
- EcmaMethod ecmaMethod = (EcmaMethod)method;
-
- if (ecmaMethod.IsRuntimeExport)
+ foreach (var method in type.GetMethods())
{
- string runtimeExportName = ecmaMethod.GetRuntimeExportName();
- if (runtimeExportName != null)
- rootProvider.AddCompilationRoot(method, "Runtime export", runtimeExportName);
+ EcmaMethod ecmaMethod = (EcmaMethod)method;
+ if (ecmaMethod.IsRuntimeExport || ecmaMethod.IsNativeCallable)
+ yield return ecmaMethod;
}
+ }
+ }
+ }
- if (ecmaMethod.IsNativeCallable)
- {
- string nativeCallableExportName = ecmaMethod.GetNativeCallableExportName();
- if (nativeCallableExportName != null)
- rootProvider.AddCompilationRoot(method, "Native callable", nativeCallableExportName);
- }
+ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
+ {
+ foreach (var ecmaMethod in ExportedMethods)
+ {
+ if (ecmaMethod.IsRuntimeExport)
+ {
+ string runtimeExportName = ecmaMethod.GetRuntimeExportName();
+ if (runtimeExportName != null)
+ rootProvider.AddCompilationRoot((MethodDesc)ecmaMethod, "Runtime export", runtimeExportName);
+ }
+ else if (ecmaMethod.IsNativeCallable)
+ {
+ string nativeCallableExportName = ecmaMethod.GetNativeCallableExportName();
+ if (nativeCallableExportName != null)
+ rootProvider.AddCompilationRoot((MethodDesc)ecmaMethod, "Native callable", nativeCallableExportName);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/ExportsFileWriter.cs b/src/ILCompiler.Compiler/src/Compiler/ExportsFileWriter.cs
new file mode 100644
index 00000000000..9935a4dbeac
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/ExportsFileWriter.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler
+{
+ public class ExportsFileWriter
+ {
+ private string _exportsFile;
+ private List _methods;
+ private TypeSystemContext _context;
+
+ public ExportsFileWriter(TypeSystemContext context, string exportsFile)
+ {
+ _exportsFile = exportsFile;
+ _context = context;
+ _methods = new List();
+ }
+
+ public void AddExportedMethods(IEnumerable methods)
+ => _methods.AddRange(methods.Where(m => m.Module != _context.SystemModule));
+
+ public void EmitExportedMethods()
+ {
+ FileStream fileStream = new FileStream(_exportsFile, FileMode.Create);
+ using (StreamWriter streamWriter = new StreamWriter(fileStream))
+ {
+ if (_context.Target.IsWindows)
+ {
+ streamWriter.WriteLine("EXPORTS");
+ foreach (var method in _methods)
+ streamWriter.WriteLine($" {method.GetNativeCallableExportName()}");
+ }
+ else
+ {
+ foreach (var method in _methods)
+ streamWriter.WriteLine($"_{method.GetNativeCallableExportName()}");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index 7df0a8e4dff..a29a5cd10f7 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -332,6 +332,7 @@
+
diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs
index 0599756d504..e869f7540dc 100644
--- a/src/ILCompiler/src/Program.cs
+++ b/src/ILCompiler/src/Program.cs
@@ -40,6 +40,7 @@ internal class Program
private string _systemModuleName = "System.Private.CoreLib";
private bool _multiFile;
private bool _nativeLib;
+ private string _exportsFile;
private bool _useSharedGenerics;
private bool _useScanner;
private bool _noScanner;
@@ -134,6 +135,7 @@ private ArgumentSyntax ParseCommandLine(string[] args)
syntax.DefineOption("cpp", ref _isCppCodegen, "Compile for C++ code-generation");
syntax.DefineOption("wasm", ref _isWasmCodegen, "Compile for WebAssembly code-generation");
syntax.DefineOption("nativelib", ref _nativeLib, "Compile as static or shared library");
+ syntax.DefineOption("exportsfile", ref _exportsFile, "File to write exported method definitions");
syntax.DefineOption("dgmllog", ref _dgmlLogFileName, "Save result of dependency analysis as DGML");
syntax.DefineOption("fulllog", ref _generateFullDgmlLog, "Save detailed log of dependency analysis");
syntax.DefineOption("scandgmllog", ref _scanDgmlLogFileName, "Save result of scanner dependency analysis as DGML");
@@ -446,6 +448,17 @@ private int Run(string[] args)
ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null;
CompilationResults compilationResults = compilation.Compile(_outputFilePath, dumper);
+ if (_exportsFile != null)
+ {
+ ExportsFileWriter defFileWriter = new ExportsFileWriter(typeSystemContext, _exportsFile);
+ foreach (var compilationRoot in compilationRoots)
+ {
+ if (compilationRoot is ExportedMethodsRootProvider provider)
+ defFileWriter.AddExportedMethods(provider.ExportedMethods);
+ }
+
+ defFileWriter.EmitExportedMethods();
+ }
if (_dgmlLogFileName != null)
compilationResults.WriteDependencyLog(_dgmlLogFileName);