-
Notifications
You must be signed in to change notification settings - Fork 510
Automatic generation of method export file for shared libraries #5154
Changes from 17 commits
9f615d8
0d17711
655be26
ea9e84c
cb11f1f
7443e76
f8106e1
0fad626
996bea2
b5050e6
99435e1
2dbde95
50b0686
7fc2d0d
3bad6d1
0c00f1a
4f80359
b46e2c0
4b7424b
7f7e1d7
9d581df
a062443
f085583
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ See the LICENSE file in the project root for more information. | |
<NativeObjectExt Condition="'$(TargetOS)' == 'Windows_NT'">.obj</NativeObjectExt> | ||
<NativeObjectExt Condition="'$(TargetOS)' != 'Windows_NT'">.o</NativeObjectExt> | ||
<NativeObjectExt Condition="'$(NativeCodeGen)' == 'wasm'">.bc</NativeObjectExt> | ||
|
||
<LibFileExt Condition="'$(TargetOS)' == 'Windows_NT'">.lib</LibFileExt> | ||
<LibFileExt Condition="'$(TargetOS)' != 'Windows_NT'">.a</LibFileExt> | ||
|
||
|
@@ -48,8 +49,12 @@ See the LICENSE file in the project root for more information. | |
<NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' != 'Windows_NT' and $(NativeLib) == 'Static'">.a</NativeBinaryExt> | ||
<NativeBinaryExt Condition="'$(NativeCodeGen)' == 'wasm'">.html</NativeBinaryExt> | ||
|
||
<ExportsFiletExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' == 'Windows_NT' and '$(NativeLib)' == 'Shared'">.def</ExportsFiletExt> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: typo: Filet -> File |
||
<ExportsFiletExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' != 'Windows_NT' and '$(NativeLib)' == 'Shared'">.exports</ExportsFiletExt> | ||
|
||
<NativeObject>$(NativeIntermediateOutputPath)$(TargetName)$(NativeObjectExt)</NativeObject> | ||
<NativeBinary>$(NativeOutputPath)$(TargetName)$(NativeBinaryExt)</NativeBinary> | ||
<ExportsFile Condition="$(NativeLib) == 'Shared' and $(ExportsFile) == ''">$(NativeIntermediateOutputPath)$(TargetName)$(ExportsFiletExt)</ExportsFile> | ||
|
||
<IlcCompileOutput Condition="$(NativeCodeGen) == ''">$(NativeObject)</IlcCompileOutput> | ||
<IlcCompileOutput Condition="$(NativeCodeGen) == 'cpp'">$(NativeIntermediateOutputPath)$(TargetName).cpp</IlcCompileOutput> | ||
|
@@ -151,7 +156,8 @@ See the LICENSE file in the project root for more information. | |
<IlcArg Condition="$(DebugSymbols) == 'true'" Include="-g" /> | ||
<IlcArg Condition="$(IlcGenerateMapFile) == 'true'" Include="--map:$(NativeIntermediateOutputPath)%(ManagedBinary.Filename).map.xml" /> | ||
<IlcArg Condition="$(RdXmlFile) != ''" Include="--rdxml:$(RdXmlFile)" /> | ||
<IlcArg Condition="$(OutputType) == 'Library' and $(NativeLib) != ''" Include="--nativelib" /> | ||
<IlcArg Condition="$(OutputType) == 'Library' and $(NativeLib) != ''" Include="--nativelib" /> | ||
<IlcArg Condition="$(ExportsFile) != ''" Include="--exportsfile:$(ExportsFile)" /> | ||
<ILcArg Condition="'$(Platform)' == 'wasm'" Include="--wasm" /> | ||
</ItemGroup> | ||
|
||
|
@@ -193,6 +199,8 @@ See the LICENSE file in the project root for more information. | |
<CustomLinkerArg Include="$(NativeObject)" /> | ||
<CustomLinkerArg Include="-o $(NativeBinary)" Condition="'$(OS)' != 'Windows_NT'" /> | ||
<CustomLinkerArg Include="/OUT:$(NativeBinary)" Condition="'$(OS)' == 'Windows_NT'" /> | ||
<CustomLinkerArg Include="/DEF:$(ExportsFile)" Condition="'$(OS)' == 'Windows_NT' and $(ExportsFile) != ''" /> | ||
<CustomLinkerArg Include="-exported_symbols_list $(ExportsFile)" Condition="'$(OS)' != 'Windows_NT' and $(ExportsFile) != ''" /> | ||
<CustomLinkerArg Include="@(LinkerArg)" /> | ||
</ItemGroup> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// 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 Internal.TypeSystem; | ||
using Internal.TypeSystem.Ecma; | ||
|
||
namespace ILCompiler | ||
{ | ||
public class DefFileWriter | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is called ExportsFile everywhere else in this change. This should be called ExportsFileWriter to match. |
||
{ | ||
private string _exportsFile; | ||
private List<EcmaMethod> _methods; | ||
private TypeSystemContext _context; | ||
|
||
public DefFileWriter(TypeSystemContext context, string exportsFile) | ||
{ | ||
_exportsFile = exportsFile; | ||
_context = context; | ||
_methods = new List<EcmaMethod>(); | ||
} | ||
|
||
public void AddExportedMethods(IEnumerable<EcmaMethod> methods) | ||
=> _methods.AddRange(methods); | ||
|
||
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()}"); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -12,10 +15,20 @@ namespace ILCompiler | |
public class ExportedMethodsRootProvider : ICompilationRootProvider | ||
{ | ||
private EcmaModule _module; | ||
private List<EcmaMethod> _methods; | ||
|
||
public ExportedMethodsRootProvider(EcmaModule module) | ||
{ | ||
_module = module; | ||
_methods = new List<EcmaMethod>(); | ||
} | ||
|
||
public IEnumerable<EcmaMethod> ExportedMethods | ||
{ | ||
get | ||
{ | ||
return _methods; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you factor this class in a way that we can't get different results depending on when |
||
} | ||
} | ||
|
||
public void AddCompilationRoots(IRootingServiceProvider rootProvider) | ||
|
@@ -36,8 +49,13 @@ public void AddCompilationRoots(IRootingServiceProvider rootProvider) | |
if (ecmaMethod.IsNativeCallable) | ||
{ | ||
string nativeCallableExportName = ecmaMethod.GetNativeCallableExportName(); | ||
|
||
if (nativeCallableExportName != null) | ||
{ | ||
if (ecmaMethod.Module != _module.Context.SystemModule) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Skipping exports from the system module is a policy decision. This class should ideally be policy-free (some other component might want this list too and a filtered list might not be what they intended). Could we filter in DefFileWriter.cs? |
||
_methods.Add(ecmaMethod); | ||
rootProvider.AddCompilationRoot(method, "Native callable", nativeCallableExportName); | ||
} | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"); | ||
|
@@ -302,7 +304,11 @@ private int Run(string[] args) | |
entrypointModule = module; | ||
} | ||
|
||
compilationRoots.Add(new ExportedMethodsRootProvider(module)); | ||
// TODO: Wasm fails to compile some of the exported methods due to missing opcodes | ||
if (!_isWasmCodegen) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This coming back looks like a bad merge. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for this. Been trying to fix the Windows build error |
||
{ | ||
compilationRoots.Add(new ExportedMethodsRootProvider(module)); | ||
} | ||
} | ||
|
||
if (entrypointModule != null) | ||
|
@@ -341,7 +347,11 @@ private int Run(string[] args) | |
if (entrypointModule == null && !_nativeLib) | ||
throw new Exception("No entrypoint module"); | ||
|
||
compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule)); | ||
// TODO: Wasm fails to compile some of the xported methods due to missing opcodes | ||
if (!_isWasmCodegen) | ||
{ | ||
compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule)); | ||
} | ||
|
||
compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext); | ||
} | ||
|
@@ -446,6 +456,17 @@ private int Run(string[] args) | |
ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null; | ||
|
||
CompilationResults compilationResults = compilation.Compile(_outputFilePath, dumper); | ||
if (_nativeLib) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This condition should be |
||
{ | ||
DefFileWriter defFileWriter = new DefFileWriter(typeSystemContext, _exportsFile); | ||
foreach (var compilationRoot in compilationRoots) | ||
{ | ||
if (compilationRoot is ExportedMethodsRootProvider) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: You can use new C# features to avoid the cast.
|
||
defFileWriter.AddExportedMethods(((ExportedMethodsRootProvider)compilationRoot).ExportedMethods); | ||
} | ||
|
||
defFileWriter.EmitExportedMethods(); | ||
} | ||
|
||
if (_dgmlLogFileName != null) | ||
compilationResults.WriteDependencyLog(_dgmlLogFileName); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though that
-shared
works on OSX too. Just for my education - why did you change this to-dynamiclib
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah I know it works. I guess I was just trying to be as platform accurate as possible, most Apple docs use
-dynamiclib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that's fine.