ikvmnet / ikvm-maven

Support for adding dependencies on Maven artifacts to .NET projects, using IKVM.
MIT License
53 stars 5 forks source link

Don't get .NET dll for certain MavenReference #16

Closed martin-honnen closed 11 months ago

martin-honnen commented 2 years ago

When I write a Java project with Maven dependencies

   <dependencies>
        <dependency>
            <groupId>org.exist-db.thirdparty.xerces</groupId>
            <artifactId>xercesImpl</artifactId>
            <version>2.12.2</version>
            <classifier>xml-schema-1.1</classifier>
        </dependency>

        <!-- xpath2 and java-cup are needed at runtime
                for xercesImpl Schema 1.1 support -->
        <dependency>
            <groupId>org.exist-db.thirdparty.org.eclipse.wst.xml</groupId>
            <artifactId>xpath2</artifactId>
            <version>1.2.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>edu.princeton.cup</groupId>
            <artifactId>java-cup</artifactId>
            <version>10k</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

then part of the used jars is e.g. C:\Users\marti\.m2\repository\edu\princeton\cup\java-cup\10k\java-cup-10k.jar.

However, with IKVM Maven, when I use e.g.

<ItemGroup>
    <PackageReference Include="IKVM.Maven.Sdk" Version="1.0.1" />
    <MavenReference Include="org.exist-db.thirdparty.xerces:xercesImpl" Version="2.12.2" Classifier="xml-schema-1.1"/>
    <MavenReference Include="org.exist-db.thirdparty.org.eclipse.wst.xml:xpath2" Version="1.2.0" />
    <MavenReference Include="edu.princeton.cup:java-cup" Version="10k" />
  </ItemGroup>

and build, I don't seem to get any dll for java-cup, I only get e.g. xercesImpl.dll, xml.apis.dll and xpath2.dll.

Is that due to the odd Version="10k"? Any idea how to fix that, other than to not use MavenReference but include the jar file?

NightOwl888 commented 2 years ago

I believe so. Although version numbers in Java are alphanumeric (i.e. 1.0-SNAPSHOT is a valid version), in .NET they are strictly numeric.

When passed through NormalizeAssemblyVersion, we will end up with a null version number because the .NET Version class will fail to parse it. I don't know if that specifically applies to IkvmReference, but it is definitely a bug to assume Version.TryParse can normalize any Java version number.

NightOwl888 commented 2 years ago

More examples of version numbers that won't pass the Version.TryParse validation.

I can't seem to locate any official docs on what formats are supported in Java, but it is clear that there are few limitations. But it appears safe to assume the start of the string will always contain the numbers.

Getting a Valid .NET Version Number

To get a valid .NET version number, it seems the best way would be to analyze the version string from the beginning and capture everything that matches [0-9.], stopping at the first character that doesn't match. If the string then ends in a ., append a 0. Then run it through Version.TryParse as we are currently doing.

Handling Uniqueness (for cache)

Discarding characters from the version number increases the chances of there being collisions in the cache. This will be an issue for successive prereleases (1.0.0-RC1 vs 1.0.0-RC2).

The way to fix this would be to pass through the actual version number from Java to the cache so we can be sure it is in a unique folder. It would also be ideal to put the actual version number into the AssemblyInformationalVersion field so it is possible to examine a compiled DLL and determine what Java version (including prereleases) it corresponds to.

@wasabii - I attempted to look for the code that caches the compiled DLLs that you previously mentioned when dealing with IkvmReference, but couldn't find it. Nor could I find a cache in my /user folder. Was this cut from the project?

wasabii commented 2 years ago

https://github.com/ikvm-revived/ikvm/blob/eccfef126220d8dd339bdf27fa4b1de4bae949ed/src/IKVM.Util/Modules/ModuleVersion.cs

Maven versions are irrelevant.

wasabii commented 2 years ago

~/.ikvm/cache

wasabii commented 2 years ago

This appears to be https://github.com/ikvm-revived/ikvm/issues/100, which is fixed in IKVM/develop (8.2.2).

As the problem exists in IkvmReference itself, and MavenReference automatically creates IkvmReferences, and does not allow passthrough metadata (to prevent users overriding stuff that Maven has to be responsible for for the ecosystem to work), working around the bug until the next release is a little harder than just putting on some metadata.

You'll need to alter the MSBuild script (a custom target) to rewrite the IkvmReferenceItem.AssemblyVersion metadata.

You can do this by creating a target that runs immediately after GetMavenIkvmReferenceItems, and alters the contents of the IkvmReferenceItem item group.

Something like this (not tested):

<Target Name="FixIkvmReference" AfterTargets="GetMavenIkvmReferenceItems">
<IkvmReferenceItem Update="maven$edu.princeton.cup:java-cup:10k">
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</IkvmReferenceItem>
</Target>
wasabii commented 11 months ago

So..... I think this is probably fixed. Not exactly sure, but I thought it was last year. So, closing until somebody reopens.