Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add jlink & jpackage Java examples #4038

Merged
merged 17 commits into from
Dec 2, 2024

Conversation

ayewo
Copy link
Contributor

@ayewo ayewo commented Nov 27, 2024

This intended to close #3638.

The JlinkModule creates a runtime image in two steps:

  1. it creates a jlink.jmod file for the module containing the mainClass using the jmod tool;
  2. it then uses the jlink tool, to link the previously created jlink.jmod with a runtime image.

The generated runtime image can be executed with:

./out/foo/jlinkAppImage.dest/jlink-runtime/bin/jlink

As for the JpackageModule implementation, I decided to reuse most of the JpackageModule code @lefou linked to the original issue. Of course his code completely avoids the jmod dance by using jpackage to create a native package/installer directly.

jpackage supports up to 3 different package/installer outputs on macOS:

jpackageType = "dmg"
./out/foo/jpackageAppImage.dest/image/foo-1.0.dmg

jpackageType = "pkg"
./out/foo/jpackageAppImage.dest/image/foo-1.0.pkg

jpackageType = "app-image"
./out/foo/jpackageAppImage.dest/image/foo.app

Would be interested to hear your thoughts on the slight difference between how the 2 traits are implemented.

@lihaoyi
Copy link
Member

lihaoyi commented Nov 28, 2024

What happens after I run the foo-1.0.pkg installer? I assume it puts the file on disk somewhere, but I couldn't find it

@lihaoyi
Copy link
Member

lihaoyi commented Nov 28, 2024

Overall the code looks reasonable I think. Some nits and some tweaks likely necessary to get it working reliably in CI and on my laptop.

One area that needs to be fleshed out is the english docs surrounding the examples. We should have a short explanation of what is going on, how these traits and the output files can be used from a user perspective, and with links to upstream documentation for more details

CC @lefou @alexarchambault

@lihaoyi
Copy link
Member

lihaoyi commented Nov 28, 2024

Managed to find the foo program in Applications after installing the .pkg, but running it seems to exit immediately before doing anything. Maybe we can make it pop up a Swing window or something just so it's visible to the user the program works?

@lefou
Copy link
Member

lefou commented Nov 28, 2024

As for the JpackageModule implementation, I decided to reuse most of the JpackageModule code @lefou linked to the original issue.

Please add me as co-author to the relevant git commit.

Co-authored-by: Tobias Roeser <[email protected]>

@ayewo
Copy link
Contributor Author

ayewo commented Nov 28, 2024

@lefou
As requested, I've added you as a co-author. Since there's only 1 commit so far, I amended my last commit.

@ayewo
Copy link
Contributor Author

ayewo commented Nov 28, 2024

Managed to find the foo program in Applications after installing the .pkg, but running it seems to exit immediately before doing anything. Maybe we can make it pop up a Swing window or something just so it's visible to the user the program works?

OK, I'll update the example code to be a basic desktop app in Swing.

One area that needs to be fleshed out is the english docs surrounding the examples. We should have a short explanation of what is going on, how these traits and the output files can be used from a user perspective, and with links to upstream documentation for more details

In the original issue description, I interpreted your mention of "/** Usage */ tests and textual explanations" as referring to adding illustrative examples inside build.mill, which I have done. Sounds like this is referring to updating the Mill documentation. Can you please point me to an example of what you have in mind?

@ayewo
Copy link
Contributor Author

ayewo commented Nov 28, 2024

@lihaoyi

What happens after I run the foo-1.0.pkg installer? I assume it puts the file on disk somewhere, but I couldn't find it

Managed to find the foo program in Applications after installing the .pkg, but running it seems to exit immediately before doing anything. Maybe we can make it pop up a Swing window or something just so it's visible to the user the program works?

Double-clicking or doing an open foo-1.0.pkg in Terminal should show the installer.

I've updated the jpackage example to show a Swing GUI when the app is launched either from a .dmg or .pkg (after installing it to /Applications).

For the app-image package, launching from the CLI (via ./out/foo/jpackageAppImage.dest/image/foo.app/Contents/MacOS/foo) should also show the Swing GUI.

@lihaoyi
Copy link
Member

lihaoyi commented Nov 28, 2024

@ayewo for an example of the inline docs for the example tests, see https://github.com/com-lihaoyi/mill/blob/main/example/scalalib/basic/3-multi-module/build.mill. Basically the examples should contain their own explanations in // line comments, and the entire example with code/doc-line-comments/usage-block-comments can get included wholesale in the documentation as a end-user-understandable page

@ayewo ayewo requested a review from lihaoyi November 29, 2024 11:43
@ayewo
Copy link
Contributor Author

ayewo commented Nov 29, 2024

@lihaoyi I’ve addressed all of your feedback.

@lihaoyi
Copy link
Member

lihaoyi commented Nov 30, 2024

Thanks, will take a look

@lihaoyi
Copy link
Member

lihaoyi commented Nov 30, 2024

Just looked through this, I think it looks pretty good.

Some last requests:

  • Can you include your new examples into the documentation in https://github.com/com-lihaoyi/mill/blob/main/docs/modules/ROOT/pages/javalib/module-config.adoc?plain=1#L56-L58, and use ./mill docs.fastPages to check that it looks good to you

  • I imagine a common use case would be to generate jpackage outputs for all platforms, which the current trait JpackageModule makes difficult. Let's make a def jpackageAppImage0 anonymous task that takes the jpackageType: String as a parameter, and then have jpackageAppImage/jpackageDmg/jpackagePkg/jpackageExe/jpackageMsi/jpackageRpm/jpackageDeb tasks that use jpackageAppImage0, and maybe a jpackageAll task that aggregates all the results. This should make it easier for the common use case where someone wants to generate all possible executable packages for the same Java module

@ayewo
Copy link
Contributor Author

ayewo commented Nov 30, 2024

@lihaoyi

Thanks for the feedback.

  • I imagine a common use case would be to generate jpackage outputs for all platforms, which the current trait JpackageModule makes difficult. Let's make a def jpackageAppImage0 anonymous task that takes the jpackageType: String as a parameter, and then have jpackageAppImage/jpackageDmg/jpackagePkg/jpackageExe/jpackageMsi/jpackageRpm/jpackageDeb tasks that use jpackageAppImage0, and maybe a jpackageAll task that aggregates all the results. This should make it easier for the common use case where someone wants to generate all possible executable packages for the same Java module

Unfortunately, jpackage is not a cross-platform tool the way you imagine it.

From the docs:

It will be able to produce a native package in a platform-specific format, such as an exe on Windows or a dmg on macOS. Each format must be built on the platform it runs on, there is no cross-platform support. The tool will have options that allow packaged applications to be customized in various ways.

@lihaoyi
Copy link
Member

lihaoyi commented Nov 30, 2024

Ah ok, I see. That's fine then

@lihaoyi
Copy link
Member

lihaoyi commented Nov 30, 2024

We can leave it as is

@ayewo
Copy link
Contributor Author

ayewo commented Nov 30, 2024

Quick question regarding some test failures in CI:

One of the usage example tests for jpackage looks like this:

java -jar ./out/foo/assembly.dest/out.jar
Nov 28, 2024 12:45:43 PM foo.Foo readConf
INFO: Loaded application.conf from resources: Foo Application Conf

Nov 28, 2024 12:45:44 PM foo.Bar lambda$main$0
INFO: Hello World application started successfully

In other words, it uses a logger that prints the current timestamp. I'm wondering if UtestExampleTestSuite is doing a string match against this for its expected output which might be why I'm seeing failures?

I'm guessing I'll need to remove the timestamp, right?

@ayewo
Copy link
Contributor Author

ayewo commented Nov 30, 2024

@lihaoyi changes are ready to be merged.

@lihaoyi
Copy link
Member

lihaoyi commented Nov 30, 2024

@ayewo looks like some of the test failures are legit

@ayewo
Copy link
Contributor Author

ayewo commented Dec 1, 2024

@lihaoyi I believe I've fixed all the legit failures related to my changes.

@lihaoyi lihaoyi merged commit 50ee2e7 into com-lihaoyi:main Dec 2, 2024
27 checks passed
@lihaoyi
Copy link
Member

lihaoyi commented Dec 2, 2024

Looks great, thanks @ayewo ! Please email me your international bank transfer details and I can close out the bounty

@ayewo
Copy link
Contributor Author

ayewo commented Dec 2, 2024

Looks great, thanks @ayewo ! Please email me your international bank transfer details and I can close out the bounty

Thanks @lihaoyi! I've just emailed you using the email on your GH profile.

@lefou lefou added this to the 0.12.4 milestone Dec 2, 2024
@lefou
Copy link
Member

lefou commented Dec 2, 2024

While merging, you forgot to keep me in the co-authors. 😟

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add javalib examples on using jlink, jpackage, and producing JPMS modules (500USD Bounty)
3 participants