{"id":26629933,"url":"https://github.com/gradlex-org/java-module-packaging","last_synced_at":"2025-10-10T07:33:27.652Z","repository":{"id":218544101,"uuid":"746661940","full_name":"gradlex-org/java-module-packaging","owner":"gradlex-org","description":"A Gradle plugin to package stand-alone Java applications for multiple operating systems and architectures with 'jpackage'.","archived":false,"fork":false,"pushed_at":"2025-10-05T09:31:59.000Z","size":296,"stargazers_count":16,"open_issues_count":4,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T07:32:35.473Z","etag":null,"topics":["gradle-plugin","java","java-modules","jpackage","jpms"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gradlex-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-22T13:12:22.000Z","updated_at":"2025-10-05T09:31:45.000Z","dependencies_parsed_at":"2024-04-22T16:39:45.964Z","dependency_job_id":"a964568c-b468-4471-9f62-7d991c8ea1d5","html_url":"https://github.com/gradlex-org/java-module-packaging","commit_stats":null,"previous_names":["gradlex-org/java-module-packaging"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/gradlex-org/java-module-packaging","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradlex-org%2Fjava-module-packaging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradlex-org%2Fjava-module-packaging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradlex-org%2Fjava-module-packaging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradlex-org%2Fjava-module-packaging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gradlex-org","download_url":"https://codeload.github.com/gradlex-org/java-module-packaging/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradlex-org%2Fjava-module-packaging/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003189,"owners_count":26083533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle-plugin","java","java-modules","jpackage","jpms"],"created_at":"2025-03-24T13:16:16.691Z","updated_at":"2025-10-10T07:33:27.647Z","avatar_url":"https://github.com/gradlex-org.png","language":"Java","readme":"# Java Module Packaging Gradle plugin\n\n[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fgradlex-org%2Fjava-module-packaging%2Fbadge%3Fref%3Dmain\u0026style=flat)](https://actions-badge.atrox.dev/gradlex-org/java-module-packaging/goto?ref=main)\n[![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v?label=Plugin%20Portal\u0026metadataUrl=https%3A%2F%2Fplugins.gradle.org%2Fm2%2Forg%2Fgradlex%2Fjava-module-packaging%2Forg.gradlex.java-module-packaging.gradle.plugin%2Fmaven-metadata.xml)](https://plugins.gradle.org/plugin/org.gradlex.java-module-packaging)\n\nA Gradle plugin to package modular Java application as standalone bundles/installers for Windows, macOS and Linux with [jpackage](https://docs.oracle.com/en/java/javase/21/docs/specs/man/jpackage.html). \n\nThis [GradleX](https://gradlex.org) plugin is maintained by me, [Jendrik Johannes](https://github.com/jjohannes).\nI offer consulting and training for Gradle and/or the Java Module System - please [reach out](mailto:jendrik.johannes@gmail.com) if you are interested.\nThere is also my [YouTube channel](https://www.youtube.com/playlist?list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE) on Gradle topics.\n\nIf you have a suggestion or a question, please [open an issue](https://github.com/gradlex-org/java-module-packaging/issues/new).\n\n# Java Modules with Gradle\n\nIf you plan to build Java Modules with Gradle, you should consider using these plugins on top of Gradle core:\n\n- [`id(\"org.gradlex.java-module-dependencies\")`](https://github.com/gradlex-org/java-module-dependencies)  \n  Avoid duplicated dependency definitions and get your Module Path under control\n- [`id(\"org.gradlex.jvm-dependency-conflict-resolution\")`](https://github.com/gradlex-org/jvm-dependency-conflict-resolution)  \n  Additional metadata for widely-used modules and patching facilities to add missing metadata\n- [`id(\"org.gradlex.java-module-testing\")`](https://github.com/gradlex-org/java-module-testing)  \n  Proper test setup for Java Modules\n- [`id(\"org.gradlex.extra-java-module-info\")`](https://github.com/gradlex-org/extra-java-module-info)  \n  Only if your (existing) project cannot avoid using non-module legacy Jars\n- [`id(\"org.gradlex.java-module-packaging\")`](https://github.com/gradlex-org/java-module-packaging)  \n  Package standalone applications for Windows, macOS and Linux\n\n[In episodes 31, 32, 33 of Understanding Gradle](https://github.com/jjohannes/understanding-gradle) I explain what these plugins do and why they are needed.\n[\u003cimg src=\"https://onepiecesoftware.github.io/img/videos/31.png\" width=\"260\"\u003e](https://www.youtube.com/watch?v=X9u1taDwLSA\u0026list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE)\n[\u003cimg src=\"https://onepiecesoftware.github.io/img/videos/32.png\" width=\"260\"\u003e](https://www.youtube.com/watch?v=T9U0BOlVc-c\u0026list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE)\n[\u003cimg src=\"https://onepiecesoftware.github.io/img/videos/33.png\" width=\"260\"\u003e](https://www.youtube.com/watch?v=6rFEDcP8Noc\u0026list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE)\n\n[Full Java Module System Project Setup](https://github.com/jjohannes/gradle-project-setup-howto/tree/java_module_system) is a full-fledged Java Module System project setup using these plugins.  \n[\u003cimg src=\"https://onepiecesoftware.github.io/img/videos/15-3.png\" width=\"260\"\u003e](https://www.youtube.com/watch?v=uRieSnovlVc\u0026list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE)\n\n# How to use?\n\nWorking example projects to inspect:\n- [java-module-system](https://github.com/jjohannes/java-module-system) contains a compact sample and further documentation\n- [gradle-project-setup-howto](https://github.com/jjohannes/gradle-project-setup-howto/tree/java_module_system) is a full-fledged Java Module System project setup\n\nFor general information about how to structure Gradle builds and apply community plugins like this one to all subprojects\nyou can check out my [Understanding Gradle video series](https://www.youtube.com/playlist?list=PLWQK2ZdV4Yl2k2OmC_gsjDpdIBTN0qqkE).\n\n## Plugin dependency\n\nAdd this to the build file of your convention plugin's build\n(e.g. `build-logic/build.gradle(.kts)` or `buildSrc/build.gradle(.kts)`).\n\n```\ndependencies {\n    implementation(\"org.gradlex:java-module-packaging:1.1\")\n}\n```\n\n## Apply and use the plugin\n\nIn your convention plugin, apply the plugin and configure the _targets_.\n\n```\nplugins {\n    id(\"org.gradlex.java-module-packaging\")\n}\n\njavaModulePackaging {\n    target(\"ubuntu-22.04\") {\n        operatingSystem = OperatingSystemFamily.LINUX\n        architecture = MachineArchitecture.X86_64\n    }\n    target(\"macos-13\") {\n        operatingSystem = OperatingSystemFamily.MACOS\n        architecture = MachineArchitecture.X86_64\n    }\n    target(\"macos-14\") {\n        operatingSystem = OperatingSystemFamily.MACOS\n        architecture = MachineArchitecture.ARM64\n    }\n    target(\"windows-2022\") {\n        operatingSystem = OperatingSystemFamily.WINDOWS\n        architecture = MachineArchitecture.X86_64\n    }\n}\n```\n\nYou can now run _target-specific_ builds:\n\n```shell\n./gradlew jpackageWindows\n```\n\n```shell\n./gradlew runWindows\n```\n\nOr, for convenience, let the plugin pick the target fitting the machine you run on:\n\n```shell\n./gradlew jpackage\n```\n\n```shell\n./gradlew run\n```\n\nThere are some additional configuration options that can be used if needed.\nAll options have a default. Only configure what you need in addition.\nFor more information about the available options, consult the\n[jpackage](https://docs.oracle.com/en/java/javase/24/docs/specs/man/jpackage.html) and\n[jlink](https://docs.oracle.com/en/java/javase/24/docs/specs/man/jlink.html)\n(for `jlinkOptions`) documentation.\n\n```kotlin\njavaModulePackaging {\n  // global options\n  applicationName = \"app\" // defaults to project name\n  applicationVersion = \"1.0\" // defaults to project version\n  applicationDescription = \"Awesome App\"\n  vendor = \"My Company\" \n  copyright = \"(c) My Company\" \n  jlinkOptions.addAll(\"--no-header-files\", \"--no-man-pages\", \"--bind-services\")\n  addModules.addAll(\"additional.module.to.include\")\n  jpackageResources = layout.projectDirectory.dir(\"res\") // defaults to 'src/main/resourcesPackage'\n  resources.from(layout.projectDirectory.dir(\"extra-res\"))\n  verbose = false\n\n  // target specific options\n  targetsWithOs(\"windows\") {\n    options.addAll(\"--win-dir-chooser\", \"--win-shortcut\", \"--win-menu\")\n    appImageOptions.addAll(\"--win-console\")\n    targetResources.from(\"windows-res\")\n  }\n  targetsWithOs(\"macos\") {\n    options.addAll(\"--mac-sign\", \"--mac-signing-key-user-name\", \"gradlex\")\n    singleStepPackaging = true\n  }\n}\n```\n\n## Using target specific variants of libraries (like JavaFX)\n\nThe plugin uses Gradle's [variant-aware dependency management](https://docs.gradle.org/current/userguide/variant_model.html)\nto select target-specific Jars based on the configured [targets](#apply-and-use-the-plugin).\nFor this, such a library needs to be published with [Gradle Module Metadata](https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html)\nand contain the necessary information about the available target-specific Jars.\nIf the metadata is missing or incomplete, you should use the [org.gradlex.jvm-dependency-conflict-resolution](https://github.com/gradlex-org/jvm-dependency-conflict-resolution)\nplugin to add the missing information via [addTargetPlatformVariant](https://gradlex.org/jvm-dependency-conflict-resolution/#patch-dsl-block).\n\nFor example, for JavaFX it may look like this:\n```\njvmDependencyConflicts.patch {\n  listOf(\"base\", \"graphics\", \"controls\").forEach { jfxModule -\u003e\n    module(\"org.openjfx:javafx-$jfxModule\") {\n      addTargetPlatformVariant(\"linux\", OperatingSystemFamily.LINUX, MachineArchitecture.X86_64)\n      addTargetPlatformVariant(\"linux-aarch64\", OperatingSystemFamily.LINUX, MachineArchitecture.ARM64)\n      addTargetPlatformVariant(\"mac\", OperatingSystemFamily.MACOS, MachineArchitecture.X86_64)\n      addTargetPlatformVariant(\"mac-aarch64\", OperatingSystemFamily.MACOS, MachineArchitecture.ARM64)\n      addTargetPlatformVariant(\"win\", OperatingSystemFamily.WINDOWS, MachineArchitecture.X86_64)\n    }\n  }   \n}\n```\n\n## Testing against multiple targets\n\n\u003e [!WARNING]\n\u003e Currently, the following only works in combination with [Blackbox Test Suites configured by the _org.gradlex.java-module-testing_ plugin](https://github.com/gradlex-org/java-module-testing?tab=readme-ov-file#blackbox-test-suites).\n\nTests run against the _primary_ target, which is either the local machine you run the build on, or what is configured via `javaModulePackaging.primaryTarget(...)`.\nIf you want to run the test multiple times against each target you configured, you can configure this as follows:\n\n```\njavaModulePackaging {\n    multiTargetTestSuite(testing.suites[\"test\"])\n}\n```\n\nThen, there will be a test task available for each target, such as `testWindows-2022` or `testMacos-14`.\n\n## Running on GitHub Actions\n\nTarget-specific _tasks_ such as `assembleWindows-2022` or `assembleMacos-14` only run on the fitting operating system and architecture.\nIf you want to build your software for multiple targets and have GitHub actions available, you can use different\nrunners to create packages for the different targets. A setup for this can look like this\n(assuming your targets are named: `ubuntu-22.04`, `windows-2022`, `macos-13`, `macos-14`):\n\n```\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-java@v4\n        with:\n          distribution: temurin\n          java-version-file: ./gradle/java-version.txt\n      - uses: gradle/actions/setup-gradle@v3\n      - run: \"./gradlew check\"\n\n  package:\n    needs: check\n    strategy:\n      matrix:\n        os: [ubuntu-22.04, windows-2022, macos-13, macos-14]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-java@v4\n        with:\n          distribution: temurin\n          java-version-file: ./gradle/java-version.txt\n      - uses: gradle/actions/setup-gradle@v3\n      - run: \"./gradlew assemble${{ matrix.os }}\"\n      - uses: actions/upload-artifact@v4\n        with:\n          name: Application Package ${{ matrix.os }}\n          path: build/app/packages/*/*\n```\n\nTo avoid re-compilation of the Java code on each of the runners, you can run a\n[Gradle remote cache node](https://docs.gradle.com/build-cache-node).\n\nThe [java-module-system](https://github.com/jjohannes/java-module-system) project is an example that\nuses GitHub actions with a Gradle remote build cache.\n\n## FAQ\n\n### How does the plugin interact with the `jpackage` command?\n\nBy default, dhe plugin calls `jpackage` in two steps:\n\n1. Build `--type app-image` as a package-type independent image folder. This is where `jlink` is involved.\n2. Build OS-specific packages via `--type \u003cpackage-type\u003e`.\n   This may be called several times for the same target (e.g. `exe` and `msi` on Windows).\n\nOS-independent options can be configured through the extension:\n\n```kotlin\njavaModulePackaging {\n  applicationName = \"app\" // defaults to project name\n  applicationVersion = \"1.0\" // defaults to project version\n  applicationDescription = \"Awesome App\"\n  vendor = \"My Company\" \n  copyright = \"(c) My Company\" \n  jlinkOptions.addAll(\"--no-header-files\", \"--no-man-pages\", \"--bind-services\")\n  addModules.addAll(\"additional.module.to.include\")\n  verbose = false\n}\n```\n\nOS-specific options can be defined inside a target:\n\n```kotlin\njavaModulePackaging {\n  target(\"windows-2022\") { // address target by name\n    options.addAll(\"--win-dir-chooser\", \"--win-shortcut\", \"--win-menu\")\n  }\n  targetsWithOs(\"windows\") { // all targets of for a certain os\n    // ...\n  }\n}\n```\n\nYou can tell the plugin to perform packaging in one step by setting the `singleStepPackaging = true` option on a target.\n\n# Disclaimer\n\nGradle and the Gradle logo are trademarks of Gradle, Inc.\nThe GradleX project is not endorsed by, affiliated with, or associated with Gradle or Gradle, Inc. in any way.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgradlex-org%2Fjava-module-packaging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgradlex-org%2Fjava-module-packaging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgradlex-org%2Fjava-module-packaging/lists"}