Closed joniles closed 1 year ago
Greetings.
So, the main thing is in .NET Core, there's not place or thing that can be hard coded to specify the specific set of assemblies, or reference assemblies, you want to use for the operation. And they move a lot. So, much like csc.exe did in Core, you need to specify the full set of references required using the -reference argument (Roslyn on Core removed -stdlib, etc)
The error at the end is weird and I'll have to fix it.
But this means you need to -reference to netstandard, wherever it is. And IKVM.Runtime. And every other standard .NET library.
The tool does not automatically use the assemblies that it is distributed with, as those are not necessarily the platform you're targeting. We intend to allow a ikvmstub from 3.1 to generate 6 assemblies, or Framework assemblies, down the line, once a number of other bugs are fixed.
As ikvmstub is used to generate .jar files for later building against them using javac, I'm guessing you're trying to build Java code that references .NET code. We have a MSBuild SDK project to assist with this, if you'd like: IKVM.NET.Sdk: https://www.nuget.org/packages/IKVM.NET.Sdk/8.4.0#readme-body-tab
I should note there was, with the initial Core support, a hard coded calculation to the .NET Core 3.1 reference assembly directory, smacked into the middle of the IKVM code. Which is why this was easier in the past. But that hard coded string broke for quite a few use cases.
Also, because I was interested, I did go ahead and try mpxj with IKVM.Maven.Sdk.
I copied your sample/MpxCreate project into a new MSBuild .csproj project.
I added the following to the csproj:
<ItemGroup>
<PackageReference Include="IKVM" Version="8.4.0" />
<PackageReference Include="IKVM.Maven.Sdk" Version="1.0.2" />
<MavenReference Include="net.sf.mpxj:mpxj" Version="10.14.1" />
</ItemGroup>
I replaced your extension methods with the build in get/set versions.
And I hit run. And it ran.
There's some exceptions coming out from jaxb that I don't understand. Trying to find a bunch of crazy methods on java.lang.Object. Super slow given the number of exceptions it's throwing internally.
But it did finish successfully and produce the output file.
Thanks for the feedback @wasabii, much appreciated.
So, looking at the netcore31
version, in theory I should be able to add a reference to the netstandard assembly, I assume like this:
.\ikvmstub.exe -reference:netstandard.dll -out:mscorlib.jar mscorlib
which give me the same error as before,
Unhandled exception: System.IO.FileNotFoundException: netstandard
at IKVM.Reflection.Universe.Load(String refname, Module requestingModule, Boolean throwOnError) in D:\a\ikvm\ikvm\src\IKVM.Reflection\Universe.cs:line 788
I also tried this (I'm clutching at straws here!):
.\ikvmstub.exe -reference:"C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.32\netstandard.dll" -out:mscorlib.jar mscorlib
again with the same error.
Need to specify the full paths to everything, except the output file.
And you should favor reference assemblies over implementation assemblies.
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1 is where netstandard.dll appears on my system.
I'm sorry, but using the tools by hand requires a lot of understanding of .NET Core at this point. They've made it so much more complicated, with reference assemblies, and forwarder runtime assemblies, etc.
netstandard has dozens of assemblies involved, for instance. The first is the 'ref' assembly, which contains only type signatures (and no method bodies). You are meant to link against these. This is what ikvmstub should want. Then there's the runtime assembly, which since netstandard isn't a REAL library, is just a bunch of TypeForwarderAttributes, directing types to the real underlying assemblies (System.dll, System.Private.CoreLib, etc, System.Collections, etc). You should be able to ignore these, as netstandard at runtime will forward to them.
But it's all very complicated to understand now.
And not all assemblies have reference assembly versions. Most do. But not all. For the ones that represent the "3.1.0 API Surface", they'll be in C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1
.
But, then you pile in NuGet packages, and stuff, and you end up with some NuGet packages that have ref assemblies, some that don't, and some that have multiple.
So I yanked out a IKVM.NET.Sdk project, and took a look at what command it used to generate a stub for mscorlib.dll for netcoreapp3.1, in case you're interested in a full working command line (with expanded paths from a build server though):
C:\work\ikvm\src\ikvmstub\bin\Release\netcoreapp3.1\win7-x64\publish\ikvmstub.exe -r:"C:\work\nuget\packages\sharpziplib\1.3.3\lib\netstandard2.1\ICSharpCode.SharpZipLib.dll" -r:"C:\work\ikvm\src\IKVM.Java\bin\Release\netcoreapp3.1\IKVM.Java.dll" -r:"C:\work\ikvm\src\IKVM.Runtime\bin\Release\netcoreapp3.1\IKVM.Runtime.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.CSharp.dll" -r:"C:\work\nuget\packages\microsoft.extensions.dependencymodel\6.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyModel.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.VisualBasic.Core.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.VisualBasic.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\Microsoft.Win32.Primitives.dll" -r:"C:\work\nuget\packages\microsoft.win32.registry\5.0.0\ref\netstandard2.0\Microsoft.Win32.Registry.dll" -r:"C:\work\nuget\packages\microsoft.win32.systemevents\6.0.0\lib\netcoreapp3.1\Microsoft.Win32.SystemEvents.dll" -r:"C:\work\nuget\packages\mono.posix\7.1.0-final.1.21458.1\lib\netcoreapp3.1\Mono.Posix.dll" -r:"C:\work\nuget\packages\mono.unix\7.1.0-final.1.21458.1\lib\netcoreapp3.1\Mono.Unix.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\mscorlib.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\netstandard.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.AppContext.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Buffers.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.Concurrent.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.Immutable.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.NonGeneric.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.Specialized.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.Annotations.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.DataAnnotations.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.EventBasedAsync.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ComponentModel.TypeConverter.dll" -r:"C:\work\nuget\packages\system.configuration.configurationmanager\6.0.0\lib\netstandard2.0\System.Configuration.ConfigurationManager.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Configuration.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Console.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Core.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Data.Common.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Data.DataSetExtensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Data.dll" -r:"C:\work\nuget\packages\system.data.odbc\6.0.0\lib\netcoreapp3.1\System.Data.Odbc.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.Contracts.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.Debug.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.DiagnosticSource.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.FileVersionInfo.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.Process.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.StackTrace.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.TextWriterTraceListener.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.Tools.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.TraceSource.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Diagnostics.Tracing.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.dll" -r:"C:\work\nuget\packages\system.drawing.common\6.0.0\lib\netcoreapp3.1\System.Drawing.Common.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Drawing.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Drawing.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Dynamic.Runtime.dll" -r:"C:\work\nuget\packages\system.formats.asn1\6.0.0\lib\netstandard2.0\System.Formats.Asn1.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Globalization.Calendars.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Globalization.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Globalization.Extensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.Compression.Brotli.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.Compression.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.Compression.FileSystem.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.Compression.ZipFile.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.dll" -r:"C:\work\nuget\packages\system.io.filesystem.accesscontrol\5.0.0\ref\netstandard2.0\System.IO.FileSystem.AccessControl.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.FileSystem.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.FileSystem.DriveInfo.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.FileSystem.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.FileSystem.Watcher.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.IsolatedStorage.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.MemoryMappedFiles.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.Pipes.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.IO.UnmanagedMemoryStream.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Linq.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Linq.Expressions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Linq.Parallel.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Linq.Queryable.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Memory.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Http.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.HttpListener.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Mail.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.NameResolution.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.NetworkInformation.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Ping.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Requests.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Security.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.ServicePoint.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Sockets.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.WebClient.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.WebHeaderCollection.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.WebProxy.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.WebSockets.Client.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.WebSockets.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Numerics.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Numerics.Vectors.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ObjectModel.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.DispatchProxy.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Emit.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Emit.ILGeneration.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Emit.Lightweight.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Extensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Metadata.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Reflection.TypeExtensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Resources.Reader.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Resources.ResourceManager.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Resources.Writer.dll" -r:"C:\work\nuget\packages\system.runtime.compilerservices.unsafe\6.0.0\lib\netcoreapp3.1\System.Runtime.CompilerServices.Unsafe.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.CompilerServices.VisualC.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Extensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Handles.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.InteropServices.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.InteropServices.RuntimeInformation.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.InteropServices.WindowsRuntime.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Intrinsics.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Loader.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Numerics.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Serialization.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Serialization.Formatters.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Serialization.Json.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Serialization.Primitives.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Serialization.Xml.dll" -r:"C:\work\nuget\packages\system.security.accesscontrol\6.0.0\lib\netstandard2.0\System.Security.AccessControl.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Claims.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Cryptography.Algorithms.dll" -r:"C:\work\nuget\packages\system.security.cryptography.cng\5.0.0\ref\netcoreapp3.0\System.Security.Cryptography.Cng.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Cryptography.Csp.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Cryptography.Encoding.dll" -r:"C:\work\nuget\packages\system.security.cryptography.pkcs\6.0.1\lib\netcoreapp3.1\System.Security.Cryptography.Pkcs.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Cryptography.Primitives.dll" -r:"C:\work\nuget\packages\system.security.cryptography.protecteddata\6.0.0\lib\netstandard2.0\System.Security.Cryptography.ProtectedData.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Cryptography.X509Certificates.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.dll" -r:"C:\work\nuget\packages\system.security.permissions\6.0.0\lib\netcoreapp3.1\System.Security.Permissions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.Principal.dll" -r:"C:\work\nuget\packages\system.security.principal.windows\5.0.0\ref\netcoreapp3.0\System.Security.Principal.Windows.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Security.SecureString.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ServiceModel.Web.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ServiceProcess.dll" -r:"C:\work\nuget\packages\system.text.encoding.codepages\6.0.0\lib\netcoreapp3.1\System.Text.Encoding.CodePages.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Text.Encoding.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Text.Encoding.Extensions.dll" -r:"C:\work\nuget\packages\system.text.encodings.web\6.0.0\lib\netcoreapp3.1\System.Text.Encodings.Web.dll" -r:"C:\work\nuget\packages\system.text.json\6.0.0\lib\netcoreapp3.1\System.Text.Json.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Text.RegularExpressions.dll" -r:"C:\work\nuget\packages\system.threading.accesscontrol\6.0.0\lib\netstandard2.0\System.Threading.AccessControl.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Channels.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Overlapped.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Tasks.Dataflow.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Tasks.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Tasks.Extensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Tasks.Parallel.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Thread.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.ThreadPool.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Threading.Timer.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Transactions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Transactions.Local.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.ValueTuple.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Web.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Web.HttpUtility.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Windows.dll" -r:"C:\work\nuget\packages\system.windows.extensions\6.0.0\lib\netcoreapp3.1\System.Windows.Extensions.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.Linq.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.ReaderWriter.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.Serialization.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.XDocument.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.XmlDocument.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.XmlSerializer.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.XPath.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Xml.XPath.XDocument.dll" -r:"C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\WindowsBase.dll" -nostdlib -out:"obj\Release\netcoreapp3.1\ikvm\expstage\1\1e13b06f85256f82731801433a36e61b\mscorlib.jar" "C:\work\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\mscorlib.dll"
The reason this one is so long is that mscorlib on Core is a reference assembly with forwarded types. That is: it contains no actual types. It only contains forwarded types.
It represents the "old" surface area of .NET Framework. With a listing of every type that "used to be" in mscorlib, but as assembly-level attributes named ForwardedTypeAttribute, that are used at runtime to resolve the "real" assembly that the type lives in. In Core, there are no types in mscorlib. Instead they're in one of 30 different other assemblies.
Opening mscorlib in dotPeek, and seeing no real types, makes me think you don't need it. It has no types, and thus can't serve as much of a use for javac or ikvmc, unless you're exporting an old assembly which links to it. For instance: say you have an old Framework assembly, that does link to mscorlib, that you want to use on Core. In that case, you would need to pass the mscorlib.jar to javac, because that assembly you're compiling against has references to mscorlib.
But, if you've got a 3.1 assembly, it should have no references to mscorlib, and thus creating a stub jar to it shouldn't require it.
If you exported this mscorlib as a jar, it would be an empty jar: no types in it.
As you can see, this is kind of insane. Hence IKVM.NET.Sdk and IkvmReference and MavenReference.
Thanks for all the feedback. I've been digging in to this more and I think IkvmReference
is the way to go for my use case. I'm about 90% of the way there now with a simple SDK project to the point I can now run my test suite. I think I need this fix https://github.com/ikvm-revived/ikvm/pull/240 to get the sqlite JDBC driver working, so I'm waiting on the next IKVM release.
The other thing I'll need is to add support to IkvmReference
for the remap ikvmc
argument. I use a remap file currently to make versions of MPXJ which are more intuitive to use from C#/VB etc (mainly the provision of properties rather than getter and setter methods).
The mscorlib
stuff comes from some work I did a long time ago to allow the MPXJ assemblies to be used from COM. There's an annotation I'm adding to methods in the Java source to make them visible to COM (this one) which comes from the mscorlib
assembly for net461 - hence the need for the ikvmstub
. I may need to think about whether I continue providing this functionality.
Anyhow, I'll close this issue now and open a new one if I find I'm battling new issues!
Didn't realize #240 effected 8.4. That calls for a hotfix.
That said, I'm a bit loath to expose things like the MapXML to IkvmReference: namely because I'm on a personal mission to remove usage of MapXML completely. My goal with IKVM is to pretty much get a perfectly functional, spec compliant, implementation of the JVM, with defaults that make sense. COM annotations are probably a reasonable use case though that I'll have to think about.
Second: I am very much against Java package authors distributing NuGets of converted Java libraries. As it goes for ecosystem building, this is incredibly harmful. Let's use MPXJ as an example. MPXJ, at least the latest version in Maven, pulls in 22 different Java dependencies. If you take a look at your net.sf.mpxj-common package on NuGet, there are 13 different IKVM converted assemblies distributed as part of your package. You don't own the code for any of those. You are distributing very common things like log4j, jsoup, commons-*, etc.
If somebody were to install your MPXJ package from NuGet, it would bring in your copies of those assemblies. If they were to ALSO install some other package on NuGet, that say, depended on log4j (which you do, and like 90% of things do), that other package would provide it's own copy of log4j. You would be clobbering that packages files, or that package would be clobbering your files. And there is no logic that exists to harmonize which should be picked. On the off chance that they're the same name: the user's app might actually start. But if you or the other guy have manipulated the assemblies in anyway, such as through MapXML, or by changing the compile options, or whatever, it is likely to break for the user at some point. Missing methods. Bad expectations. Etc.
Or, if they're different versions, say you distribute an assembly named log4j-1.2.0, and some other guy distributes log4j-1.2.1, but you have both chosen different naming conventions for the resulting assembly, they might both load at runtime. Two copies of log4j.
Back in the day when I last did lots of enterprise work with IKVM I ran into this constantly. Different people would distribute different versions of converted but conflicting assemblies.
Not to mention the licensing issues. You are, for instance, distributing modified versions of Apache License code, but just taking a quick look, I don't see a copy of the Apache License included with your modified works.
Hence MavenReference.
The idea here is to completely disincentivize people from redistributing Java libraries which are otherwise available from the primary author. The Java ecosystem already has a package manager. And it's not NuGet. It's Maven. .NET developers should just be able to access Java packages in Maven just as easily, and with the same capabilities, as they would in a Gradle or Maven project.
So the goal with MavenReference is to allow NuGet packages, and .csprojs/etc, to just depend on the Java libraries they require. The conversion process happens on the END USER'S build machine: not yours. The end user is responsible for meeting any license requirements they might have to (as they are anyways). And there is One Right Way to run ikvmc to handle any specific assembly. One Right naming convention. One Right set of options to pass to ikvmc. Because we need the produced assemblies to be named properly, versioned properly, and not have different expectations based on their consumers.
And as part of that we can rely on Maven's version unification and dependency system. If two NuGet packages depend on the same Maven package, but at different versions, Maven has rules for that (just as NuGet does). Pick the latest. Or show a warning if there is a pinning issue. And the upstream author is responsible for annotating his dependencies properly.
This is a much better situation to be in. My view is basically that MPXJ (the Java components) should not even be in NuGet.
That said, you can have a NuGet package that depends on the Java packages, and provides things like extension methods, etc. This is the best pattern. Anybody can install net.sf.mpxj right now in their project, totally skipping your NuGet package, by using MavenReference (because you have a Maven package). And if they want your extensions, they could install a helper package of some sort from NuGet which provides them.
For MPXJ, however, this does raise some questions. The COM stuff. And I noticed you have an ikvm specific JAR file in Maven. I would much appreciate help in understanding those, as whatever you're doing might be able to be done differently and fit in better.
I totally buy in to what you are doing with MavenReference
and in an ideal world this will be my first choice for making MPXJ available to the .NET ecosystem.
The problem I have to solve is that I have been distributing a .NET version of MPXJ since the beginning of 2009 more-or-less in the form that it is today, so I need to be careful about how I make changes to features users are currently working with. The big issues are properties wrapping getter and setter methods and method renaming to match C# conventions (all via remap) and then to a lesser degree COM accessibility.
Transitioning to the use of MavenReference
for a future version of MPXJ without maintaining properties and renamed methods would cause my existing users a significant amount of rework to revert back to using "Java style" code in their applications. I'd like to avoid that if at all possible.
Although "renamed methods" (e.g. doSomething()
to DoSomething()
) is possible through the use of extension methods, extension properties do not appear to be a thing (so I can't convert x.getSomething()
to x.Something
etc by an extension). Partial classes might be a solution, but the original class would need to be labelled as partial
and any new code would need to be compiled in to the same assembly.
If it were possible to apply a remap file to an assembly generated by MavenReference
, that would solve my problem. Alternatively, if there were Java syntax or an annotation which IKVM recognised as "this is a property" that would also work.
Finally, some kind of hybrid solution which allowed me to ship an IKVM version of the MPXJ JAR (with all my remapping in place) but with the dependencies acquired using MavenReference
might be a useful compromise.
Lots of things to consider... let me know what you think. (happy to jump on a call at some point if that's easier than corresponding like this).
Gotcha.
The problem with applying a remap file to a Maven reference, or any changes at all, is you're altering an assembly other people may have built dependencies on. It's an ABI change. For instance, if you remap stuff on log4net, then your version of log4net would be different than the one some other package depends on.
So anything like this has to be very carefully considered. Part of global IKVM policy. Such as "we always generate properties for beans".
Even with you as the author of MPXJ, we have stuff to consider. For instance, let's say there exists a Java library: org.planner.ProjectManager, which extends MPXJ. And it's not released by you. And say it depends on MPXJ.
If our .NET version has a different API surface, that isn't automatically translatable, then how can IKVM run on ProjectManager, and hook those symbols back up to something in a .NET library it has no knowledge of because it hasn't been produced yet.
One of the things I'm thinking about right now is whether there is certain room for including IKVM specific code in otherwise native Java libraries. In those cases, such as yours, where the author of that library is known, approves, and in such a way as to be communicable upgraph.
Lets say IKVM had a special annotation.... @ikvm.attributes.ClrProperty or something. And it served as a marker to IKVM that a getter and setter should be tied together as a property. IKVM would always respect it. And as the author of MPXJ you could be responsible for decorating your MPXJ Java classes with it. And it would have no effect on other VMs.
So ikvmc running anywhere in the dependency graph, on anybody's computer, would have enough metadata to make the decision. And it would have zero effect on real Java code, thus allowing Java libraries to continue viewing the API surface as they normally would.
Things like this need to be thought through.
Or, alternatively, if there was an official Java standard for metadata to tie getter and setter together: we could respect that.
I do think I've convinced myself that it should be fine to add MapXML as a metadata item on IkvmReference though. It's already available in IKVM.NET.Sdk. And IkvmReference really should be exporting the full power of IKVM, even if we recommend against it's usage in favor of MavenReference (which uses IkvmReference under the covers anyways).
There is also the possibility, and this one kinda makes me feel a bit sick..... needs more thought.... of allowing a JAR author to embed a MapXML file into a JAR itself, perhaps with a MANIFEST.MF section for IKVM related things. Thus controlling the conversion process downstream to any consumer. Authors would have to take ABI seriously with this. Massively advanced feature.
Dude. That last thought reminded me of something I saw in the source but haven't dug into yet.
There is already a ikvm.lang.Property annotation. Wonder how it works.
Yup. That does it.
Stick it on a field, and you specify the name of the getter and setter method, and it generates a CLR property in the output.
Okay. So. Problems I see with that. It lives in the IKVM.Java produced assembly. You'd need those class files to actually consume it with javac. Looks like it's original intention was just to expose some things inside the base library as properties.
To make this into something real, we'd need to take it out of IKVM.Java, and make it something consumable in a normal Java compile workflow.
Maybe we need a net.ikvm:ikvm-lang Maven package. Publish this annotation to Maven, as a real java lib, so real java authors can use it.
I think you could make use of it now though... you would need to grab the .class file from an IKVM build to do so, however. I think though that would work, and be fine.
Actually, this is Java. It's a bit more loosely goosey. You can probably just declare it in your own code and it'll work fine.
Actually, this is Java. It's a bit more loosely goosey. You can probably just declare it in your own code and it'll work fine.
Interesting! This might solve both the issue with providing properties to C# users, and also potentially making the assemblies available to COM. I'm hoping that if a hand-written version of the ClassInterfaceType
enum is provided, which is used as the annotation to enable COM, rather than the version from the jar I was creating using ikvmstub
than might "just work".
I need to get the JNI stuff working first (see the issues opened this morning), but once I'm there I can experiment with including the IKVM property annotation and ClassInterfaceType
directly in my own code. Fingers crossed...
Some background: I'm looking at migrating MPXJ to use a current release version of IKVM. I started out with the original IKVM version back when Jeroen was still working on it, then switched to a hand-built version of IKVM from the
ikvm-revived
repo back in December 2021 to get .NET Core support before we had official builds and packages deployed to Nuget. Now I'm looking to use the official releases and leverage the packages deployed to Nuget.I'm trying to get to the point where I can replicate the same setup I have with original IKVM and my current hand-built version: I have a directory with the IKVM tools, I can run
ikvmstub
andikvmc
, generate assemblies and with those create Nuget packages. (I'm aware ofikvm-maven
, which looks promising for future use although I want to get the basics working first before I explore this).So my first stab at this is to run
ikvmstub
fornet461
:My initial assumption is that I'm missing
IKVM.Runtime.dll
, so I've downloadedIKVM-8.3.3-bin-net461.zip
, extracted the contents and copied them into the tools directory, but unfortunately I'm getting the same result.Moving on to
netcoreapp3.1
, I get a slightly different issue:netstandard.dll
appears to be present in the same directory asikvmstub
so I'm not sure what's happening here.Any advice you can offer to get me up and running would be gratefully received!