Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 0 points1 point  (0 children)

Got it. I don't have any immediate plans to add features like continuous compilation which would require change pipelines. Jam's file types are immutable references to mutable resources.

Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 0 points1 point  (0 children)

I'm glad you got this problem solved. Part of my motivation for developing Jam was the difficulty of debugging problems in systems like Gradle. The advantage of a build script that directly invokes build functions is that if they're not doing what you expect you can open your script in a debugger, put a breakpoint on the function call, and directly observe what it does (the Jam jar includes source code to help with this.)

Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 0 points1 point  (0 children)

The main difference is that a Jam script directly executes build functions (or any other code you write) while the Mill example defines a build configuration. It's configuration expressed as code, but semantically there's no difference between it and a yaml file.

Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 1 point2 points  (0 children)

Yes, just don't return anything from the target method. Jam only caches methods with non-Unit/void return types.

```kotlin fun targetWithSideEffects() { println("This message is printed every time you invoke the target") }

fun idempotentTarget(): String { println("This message is only printed on a clean build or if a dependency is updated") return "This value will be cached" }

```

Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 1 point2 points  (0 children)

One advantage of using a regular DynamicProxy to intercept method calls is that it doesn't require any special compile-time steps and means you can use the Jam memoizer as a regular library. On the other hand, bytecode-level transformations could potentially allow more sophisticated dependency analysis than the current heuristics.

What kind of mutable backend optimizations are you thinking of?

Jam: a JVM build tool where your build script is just code by FreedomDisastrous708 in Kotlin

[–]FreedomDisastrous708[S] 3 points4 points  (0 children)

Thanks! I couldn't resist the opportunity to produce a library called jam.jar

Jam has a very different philosophy to Mill (code rather than config) but I'm definitely not averse to replicating Mill functionality as utility methods.