jbang icon indicating copy to clipboard operation
jbang copied to clipboard

"filters" for native dependencies

Open maxandersen opened this issue 4 months ago • 18 comments

to handle all the various variants of naming used for deps we might want to support:

//DEPS org.lwjgl:lwjgl:3.3.6:natives-macos{platform=osx} //DEPS org.lwjgl:lwjgl:3.3.6:natives-windows-arm64{platform=win_arm64}

maxandersen avatar Aug 19 '25 14:08 maxandersen

semi inspired from jreleaser notion of platform filters.

maxandersen avatar Aug 19 '25 14:08 maxandersen

The important part being that whatever we choose as the name for an os and an arch would always work regardless of what the author of the artifact called it, right?

So if we choose "osx" like in your example (would we call it "osx"??) all the following would match on a Mac (any Mac), right?

//DEPS org.lwjgl:lwjgl:3.3.6:natives-macos{platform=osx} //DEPS org.lwjgl:lwjgl:3.3.6:natives-osx{platform=osx} //DEPS org.lwjgl:lwjgl:3.3.6:natives-mac{platform=osx}

Because it has nothing to do with the classifier of the artifact but only with the filter that says platform=osx.

(just wanted this clearly stated)

Edit: or would you want to be able to filter on "old" macs (osx) and "new" macs (macos)?

quintesse avatar Aug 19 '25 22:08 quintesse

We would just need something that is consistent from jbang usage perspective. So we get to pick one - and stick with it forever more.

maxandersen avatar Aug 20 '25 04:08 maxandersen

A "filter" for runtime options would allow the -XstartOnFirstThread JVM runtime option only to be specified for macOS.

Unsure about the exact syntax, but I think

//RUNTIME_OPTIONS{platform=macos} -XstartOnFirstThread

is better than using

//RUNTIME_OPTIONS -XstartOnFirstThread{platform=macos}

But then one should consider specifying platform specific DEPS as

//DEPS{platform=macos}  org.lwjgl:lwjgl:3.3.6:natives-macos org.lwjgl:lwjgl-glfw:3.3.6:natives-macos org.lwjgl:lwjgl-opengl:3.3.6:natives-macos

So in general use

//DEPS{guard-clause}  dep1 dep2 dep3 .... depn
//RUNTIME_OPTIONS{guard-clause}  opt1 opt2 opt3 ... optn

Java library https://github.com/ezylang/EvalEx could be used to evaluate the guard clause or guard expression, but it requires Java 11+ and JBang supports Java 8+.

//DEPS{platform == 'macos'} org.lwjgl:lwjgl:3.3.6:natives-macos org.lwjgl:lwjgl-glfw:3.3.6:natives-macos org.lwjgl:lwjgl-opengl:3.3.6:natives-macos


// https://github.com/ezylang/EvalEx
//DEPS com.ezylang:EvalEx:3.5.0

// Create a new EvalEx instance
Expression expression = new Expression("platform == 'macos'");

// Set the variable 'platform' to the value Util.getPlatform()
expression.with("platform", Util.getPlatform());

// Evaluate the expression
boolean result = expression.eval().getBooleanValue();

// Print the result (true or false)
System.out.println(result);

wfouche avatar Aug 20 '25 07:08 wfouche

An aspect to consider is us being able to translate these into Gradle and maven in context of export and edit.

maxandersen avatar Aug 20 '25 08:08 maxandersen

An aspect to consider is us being able to translate these into Gradle and maven in context of export and edit.

Gradle

dependencies {
    // Other dependencies
    
    if (org.gradle.internal.os.OperatingSystem.current().isMacOs()) {
        // Specify your dependency for macOS only
        implementation 'org.lwjgl:lwjgl:3.3.6:natives-macos'
        implementation 'org.lwjgl:lwjgl-glfw:3.3.6:natives-macos'
        implementation 'org.lwjgl:lwjgl-opengl:3.3.6:natives-macos'
    }
}

Maven

<project>
  ...
  <profiles>
    <profile>
      <id>macos-only</id>
      <activation>
        <os>
          <name>Mac OS X</name>
        </os>
      </activation>
      <dependencies>
        <dependency>
          <groupId>org.lwjgl</groupId>
          <artifactId>lwjgl</artifactId>
          <version>3.3.6</version>
          <classifier>natives-macos</classifier>
        </dependency>
        ....
      </dependencies>
    </profile>
  </profiles>
  ...
</project>

wfouche avatar Aug 20 '25 09:08 wfouche

How would you get to that from that list of filters?

maxandersen avatar Aug 20 '25 10:08 maxandersen

How would you get to that from that list of filters?

A simpler gaurd-clause expression syntax would help. Instead of using a general expression format the guard-clause could be restricted to only allow <osType> or <osType>,<archType> to be specified, for example:

//DEPS{macos}  org.lwjgl:lwjgl:3.3.6:natives-macos org.lwjgl:lwjgl-glfw:3.3.6:natives-macos org.lwjgl:lwjgl-opengl:3.3.6:natives-macos

or

//DEPS{macos,arm64}  org.lwjgl:lwjgl:3.3.6:natives-macos-arm64 org.lwjgl:lwjgl-glfw:3.3.6:natives-macos-arm64 org.lwjgl:lwjgl-opengl:3.3.6:natives-macos-arm64

A secondary data structure for dependencies would be created. It could be a hashmap with key=guard-clause and value a List<String> of deps. But this structure might not fit into JBang's current design.

Map the secondary dependencies data structure to Gradle or Maven build file content.

build.gradle

if (org.gradle.internal.os.OperatingSystem.current().isMacOs() && System.getProperty("os.arch") == "aarch64") {
        println "Detected macOS ARM64. Adding LWJGL natives for macOS ARM64."
        runtimeOnly "org.lwjgl:lwjgl:3.3.6:natives-macos-arm64"
}

pom.xml

<profiles>
    <!-- Profile to activate specifically for macOS ARM64 -->
    <profile>
        <id>macos-arm64-natives</id>
        <activation>
            <os>
                <family>mac</family>
                <arch>aarch64</arch>
            </os>
        </activation>
        <dependencies>
            <!-- LWJGL natives for macOS ARM64 -->
            <dependency>
                <groupId>org.lwjgl</groupId>
                <artifactId>lwjgl</artifactId>
                <version>3.3.6</version>
                <classifier>natives-macos-arm64</classifier>
            </dependency>
            <dependency>
                <groupId>org.lwjgl</groupId>
                <artifactId>lwjgl-glfw</artifactId>
                <version>3.3.6</version>
                <classifier>natives-macos-arm64</classifier>
            </dependency>
            <dependency>
                <groupId>org.lwjgl</groupId>
                <artifactId>lwjgl-opengl</artifactId>
                <version>3.3.6</version>
                <classifier>natives-macos-arm64</classifier>
            </dependency>
        </dependencies>
    </profile>
</profiles>

The same can be done for RUNTIME_OPTIONS.

//RUNTIME_OPTIONS{macos}  -XstartOnFirstThread

wfouche avatar Aug 20 '25 11:08 wfouche

Alternatively, the guard expressions could be viewed as a filter to be applied to restrict dependencies or runtime options to the current platform that is being used. This would simplify an initial implementation, and export to maven or gradle will not have to be changed as it will only support a single platform (the current one).

wfouche avatar Aug 20 '25 19:08 wfouche

In a parallel universe JBangX exists supporting TOML as an embedded configuration language (smile)

java = "21+"
deps = ["org.apache.commons:commons-lang3:3.12.0", "org.slf4j:slf4j-api:2.0.7"]
runtimeOptions = ["-Xmx2g"]

[platform.macos.opt]
runtimeOptions = ["-XstartOnFirstThread"]

[platform.macos.cpu.arm64]
deps = ["org.lwjgl:lwjgl:3.3.6:natives-macos-arm64", "org.lwjgl:lwjgl-glfw:3.3.6:natives-macos-arm64", "org.lwjgl:lwjgl-opengl:3.3.6:natives-macos-arm64"]

[platform.macos.cpu.x86_64]
deps = ["org.lwjgl:lwjgl:3.3.6:natives-macos", "org.lwjgl:lwjgl-glfw:3.3.6:natives-macos", "org.lwjgl:lwjgl-opengl:3.3.6:natives-macos"]

The same config in YAML (converted from TOML).

java: 21+
deps:
  - org.apache.commons:commons-lang3:3.12.0
  - org.slf4j:slf4j-api:2.0.7
runtimeOptions:
  - -Xmx2g
platform:
  macos:
    opt:
      runtimeOptions:
        - -XstartOnFirstThread
    cpu:
      arm64:
        deps:
          - org.lwjgl:lwjgl:3.3.6:natives-macos-arm64
          - org.lwjgl:lwjgl-glfw:3.3.6:natives-macos-arm64
          - org.lwjgl:lwjgl-opengl:3.3.6:natives-macos-arm64
      x86_64:
        deps:
          - org.lwjgl:lwjgl:3.3.6:natives-macos
          - org.lwjgl:lwjgl-glfw:3.3.6:natives-macos
          - org.lwjgl:lwjgl-opengl:3.3.6:natives-macos

The same config but expressed as JSON (converted from TOML).

{
  "deps": [
    "org.apache.commons:commons-lang3:3.12.0",
    "org.slf4j:slf4j-api:2.0.7"
  ],
  "java": "21+",
  "runtimeOptions": [
    "-Xmx2g"
  ],
  "platform": {
    "macos": {
      "cpu": {
        "arm64": {
          "deps": [
            "org.lwjgl:lwjgl:3.3.6:natives-macos-arm64",
            "org.lwjgl:lwjgl-glfw:3.3.6:natives-macos-arm64",
            "org.lwjgl:lwjgl-opengl:3.3.6:natives-macos-arm64"
          ]
        },
        "x86_64": {
          "deps": [
            "org.lwjgl:lwjgl:3.3.6:natives-macos",
            "org.lwjgl:lwjgl-glfw:3.3.6:natives-macos",
            "org.lwjgl:lwjgl-opengl:3.3.6:natives-macos"
          ]
        }
      },
      "opt": {
        "runtimeOptions": [
          "-XstartOnFirstThread"
        ]
      }
    }
  }
}

wfouche avatar Aug 20 '25 20:08 wfouche

No amount of toml helps to map this to maven/gradle.

The point is about ensuring the selections aren't open-ended so we can with high likelihood map to maven/gradle when needed. Doesn't have to be perfect but "close enough".

maxandersen avatar Aug 20 '25 21:08 maxandersen

No amount of toml helps to map this to maven/gradle.

Parsing the source file is a non-issue when using toml. That's nice benefit.

wfouche avatar Aug 21 '25 18:08 wfouche

The design explored with the TOML config could be retrofitted to the current version of JBang as:

//RUNTIME_OPTIONS[platform.macos.opt]  -XstartOnFirstThread`
//DEPS[platform.macos.cpu.x86_64]  org.lwjgl:lwjgl:3.3.6:natives-macos org.lwjgl:lwjgl-glfw:3.3.6:natives-macos org.lwjgl:lwjgl-opengl:3.3.6:natives-macos

wfouche avatar Aug 21 '25 18:08 wfouche

No amount of toml helps to map this to maven/gradle.

Parsing the source file is a non-issue when using toml. That's nice benefit.

sorry - but I'm not following what any of this (filtering of native deps) has to do with TOML.

maxandersen avatar Aug 22 '25 05:08 maxandersen

The design explored with the TOML config could be retrofitted to the current version of JBang as:

//RUNTIME_OPTIONS[platform.macos.opt]  -XstartOnFirstThread`
//DEPS[platform.macos.cpu.x86_64]  org.lwjgl:lwjgl:3.3.6:natives-macos org.lwjgl:lwjgl-glfw:3.3.6:natives-macos org.lwjgl:lwjgl-opengl:3.3.6:natives-macos

how is this better/worse than the notion {key0,key1=value2,key2=value2} implemented at #2133 ?

maxandersen avatar Aug 22 '25 05:08 maxandersen

how is this better/worse than the notion {key0,key1=value2,key2=value2} implemented at https://github.com/jbangdev/jbang/pull/2133 ?

This concept is orthogonal to what is proposed in #2133. It provides a mechanism for grouping JBang directives into a hierarchical namespace. #2133 is only concerned with dependencies and adds additional attributes to individual dependencies. Thus two completely different concepts. I'll open a new issue for the hierarchical namespace proposal.

wfouche avatar Aug 22 '25 06:08 wfouche

@wfouche I get that you are suggesting to put the {attrlist} at the directive level instead of individual deps - thats fine - its what is in the original proposal (//DEPS{compile} g:a:v) on https://github.com/jbangdev/jbang/issues/2126 but PR didn't start with that as it prevents one from declaring these properties on commandline.

You are proposing a different syntax - and I'm trying to understand why. Wether it its intentional or you simply missed that the original proposal suggests to allow specifying the {attrlist} on the directive?

maxandersen avatar Aug 22 '25 06:08 maxandersen

Whether it its intentional

Yes, I'm thinking of a different (more limited) grouping mechanism. Have created https://github.com/jbangdev/jbang/issues/2188 to discuss it in more detail.

But I can see how //DEPS{os=macos,cpu=arm64} would accomplish the same.

wfouche avatar Aug 22 '25 07:08 wfouche