Montarre User Manual

Book Metadata

CREATOR | Mark Raynsford
DATE | 2024-10-03T17:13:28+00:00
DESCRIPTION | User manual for the Montarre package.
IDENTIFIER | f51d65bd-fc7b-4cc8-85bf-dbed171a9550
LANGUAGE | en
RIGHTS | Public Domain
TITLE | Montarre User Manual

Table Of Contents

Cover

Colophon

Table Of Contents

1. Overview

1.1. Introduction

1.2. Motivation

1.3. Features

2. Installation

2.1. Overview

2.2. Shaded Jar

3. Usage

3.1. Introduction

3.2. Packages

3.3. Package Declaration

3.4. Maven Plugin

3.5. Command-Line Native Packages

4. Maven Plugin

4.1. Usage

4.1.1. Overview

4.2. Goals

4.2.1. package

4.2.1.1. Description

4.2.1.2. Configuration Parameters

4.2.1.2.1. applicationKind

4.2.1.2.2. categories

4.2.1.2.3. copyright

4.2.1.2.4. description

4.2.1.2.5. enableNativeAccess

4.2.1.2.6. extraOptions

4.2.1.2.7. flatpak

4.2.1.2.8. humanName

4.2.1.2.9. libraries

4.2.1.2.10. license

4.2.1.2.11. links

4.2.1.2.12. longDescriptions

4.2.1.2.13. mainModule

4.2.1.2.14. outputFile

4.2.1.2.15. packageName

4.2.1.2.16. version

4.2.1.2.17. platformLibraries

4.2.1.2.18. requiredJDKVersion

4.2.1.2.19. runtimeImageKind

4.2.1.2.20. resources

4.2.1.2.21. shortName

4.2.1.2.22. vendor

4.2.1.3. Skipping

5. Command Line

5.1. Overview

5.2. help

5.2.1. Name

5.2.2. Description

5.2.3. Examples

5.3. maven-central download

5.3.1. Name

5.3.2. Description

5.3.3. Parameters

5.3.4. Examples

5.4. native create

5.4.1. Name

5.4.2. Description

5.4.3. Parameters

5.4.4. Examples

5.5. native packagers

5.5.1. Name

5.5.2. Description

5.5.3. Parameters

5.5.4. Examples

5.6. package check

5.6.1. Name

5.6.2. Description

5.6.3. Parameters

5.6.4. Examples

5.7. package extract-declaration

5.7.1. Name

5.7.2. Description

5.7.3. Parameters

5.7.4. Examples

5.8. package pack

5.8.1. Name

5.8.2. Description

5.8.3. Parameters

5.8.4. Examples

5.9. package schema

5.9.1. Name

5.9.2. Description

5.9.3. Parameters

5.9.4. Examples

5.10. package unpack

5.10.1. Name

5.10.2. Description

5.10.3. Parameters

5.10.4. Examples

5.11. package validate

5.11.1. Name

5.11.2. Description

5.11.3. Parameters

5.11.4. Examples

5.12. version

5.12.1. Name

5.12.2. Description

5.12.3. Examples

5.13. wix xml

5.13.1. Name

5.13.2. Description

5.13.3. Parameters

5.13.4. Examples

6. Packagers

6.1. com.io7m.montarre.app_image

6.1.1. Overview

6.1.2. Description

6.1.3. Outputs

6.2. com.io7m.montarre.deb

6.2.1. Overview

6.2.2. Outputs

6.3. com.io7m.montarre.flatpak

6.3.1. Overview

6.3.2. Outputs

6.4. com.io7m.montarre.msi

6.4.1. Overview

6.4.2. Requirements

6.4.3. Outputs

6.5. com.io7m.montarre.shell

6.5.1. Overview

6.5.2. Description

6.5.3. Batch File

6.5.4. Shell Script

6.5.5. Launch Jar

6.5.5.1. Overview

6.5.5.2. Get-Arch

6.5.5.3. Get-OS

6.5.5.4. Check-Java-Version

6.5.5.5. Get-Module-Path

6.5.6. Outputs

7. Package Format 1.0 Specification

7.1. Overview

7.2. Regular Expressions

7.3. Dotted Strings

7.4. Language

7.5. TranslatedText

7.6. Hash

7.6.1. Overview

7.6.2. Algorithm

7.6.3. Value

7.7. Architecture Name

7.8. Operating System Name

7.9. Platform

7.10. Package

7.11. Metadata

7.11.1. Overview

7.11.2. ApplicationKind

7.11.3. Categories

7.11.4. Copying

7.11.4.1. Overview

7.11.4.2. License

7.11.4.3. Copyright

7.11.5. Description

7.11.6. Flatpak

7.11.6.1. Overview

7.11.6.2. Runtimes

7.11.6.3. Permissions

7.11.7. JavaInfo

7.11.7.1. Overview

7.11.7.2. Required JDK Version

7.11.7.3. Main Module

7.11.7.4. JDK Runtime Image Type

7.11.7.5. Native Access

7.11.7.6. Extra Options

7.11.8. Links

7.11.8.1. Overview

7.11.8.2. Roles

7.11.9. LongDescription

7.11.9.1. Overview

7.11.9.2. Paragraph

7.11.9.3. Feature

7.11.10. Names

7.11.10.1. Overview

7.11.10.2. Package Name

7.11.10.3. Human Name

7.11.10.4. Short Name

7.11.11. Vendor

7.11.11.1. Overview

7.11.11.2. Name

7.11.11.3. ID

7.11.12. Version

7.11.12.1. Overview

7.11.12.2. Number

7.11.12.3. Date

7.12. Manifest

7.12.1. Overview

7.12.2. FileName

7.12.3. Size

7.12.4. Modules

7.12.5. PlatformModules

7.12.6. Resources

7.13. Serialization

7.13.1. Overview

7.13.2. Entomos

7.13.3. XML

7.13.4. XML Schema

7.14. Model Sources

1. Overview

1.1. Introduction

1.2. Motivation

1.3. Features

1.1. Introduction

The montarre package provides tools for producing platform-specific native executables and installation media from a single platform-independent source package.

1.2. Motivation

In traditional programming environments, prior to Java, compilers typically produced native code for the platform upon which they were running. If you were on hardware architecture A, using operating system O, then unless you were willing to go through the pain and suffering of configuring a cross-compiler, you could only produce native executables that would run on hardware architecture A, using operating system O.

As a consequence of this, if you wanted to distribute a program for a range of hardware architectures and operating systems, you would have to maintain at most M * N systems to build code (where M is the number of operating systems and N is the number of hardware architectures). Worse, all of these systems had to be trusted to actually produce code that was correct given a single package of source code. Even worse, because each platform would inevitably have its own set of tools, the singled shared build procedure for the code would become exponentially complicated with lots of branching logic in order to get it to run correctly on all platforms [1].

1.2.3. N by M Native Compilation

Java, with varying degrees of success, opted to follow a write once run anywhere paradigm: The output of the compiler is platform-neutral bytecode, and end-consumers would simply load this bytecode into their locally installed Java Virtual Machine. It therefore wouldn't matter on what hardware architecture and/or on which operating system the code was compiled, as the output of the process would ostensibly be the same regardless. This would essentially collapse the above diagram to one that looked like this:

1.2.5. Java To Bytecode Compilation

This was theoretically absolutely ideal from a developer perspective. A developer could maintain a single machine and use it to produce code for any number of completely different platforms. The developer could offer a single download link online for the program instead of having to offer one per platform.

In practice, there were some issues with this. Using the above system, it is not possible to know ahead of time which version of the Java VM is installed on end-user systems. Java bytecode is versioned, and a given Java VM has a stated upper bound on the bytecode versions it can support. If a user has a Java 21 VM installed, and is given Java bytecode targeting Java 23, the bytecode will simply not run. Worse, on many operating systems, the Java VM will print an error message about the bytecode version, but the desktop environment will simply hide/discard the message. This leaves users with silently failing programs.

In Java 14, the jpackage tool was introduced. The jpackage tool can be handed Java bytecode, and a Java VM, and the tool will produce a native executable for the current platform that runs the given bytecode. This is both a benefit and a curse; a benefit because it is now possible to package Java code in a manner that makes it immune to the problem of not having a suitable Java VM installed, but a curse because it could indicate somewhat of a return to the N by M compilation model.

Let's consider what might be an ideal build setup that would keep our nice, simple, straightforward platform-neutral builds, but would also be able to produce platform-specific artifacts on demand without introducing any complexity into the build.

In an ideal world, we would have our Java compilation process stay completely platform-independent, and produce identical results regardless of the platform upon which it is run. The output of this process would be a completely platform-neutral artifact that a user could theoretically run if they had an appropriate runtime installed. The platform-neutral artifact could be signed, published and that would be the end of it from the perspective of our build system.

We would then like a second process, completely isolated and decoupled from the first, where that platform-independent artifact could be downloaded from a repository and transformed into something more familiar and suitable for the platform upon which it is running. Ideally, the second process would leave the bytecode of the original platform-independent artifact completely intact so that we could trust that the code is still "correct" and hasn't been broken in some platform-specific way. The jpackage tool can achieve this, but requires a lot of per-platform configuration in order to get good results. In practice, the jpackage tool really requires knowledge of your original build process as it will not otherwise have all the information it needs to, for example, categorize any platform-dependent native libraries included in the original artifact, or have access to other metadata such as license information.

1.2.12. Decoupled Compilation

The montarre package attempts to provide tools to achieve the above in relatively painless manner. It attempts to adhere to a paradigm of compile once, transform anywhere!

1.3. Features

The montarre package provides the following features:

1.3.2. Features

A rich, strictly-defined, and well-specified packaging format that remains platform-independent whilst allowing straightforward zero-configuration transformations to a wide range of platform-specific package formats.

Extensive, type-driven, ahead-of-time checking; if your package validates, you should get working native packages on all platforms.

Reproducible builds by default.

Support for producing simple jpackage "app-image" executables on any platform.

Support for producing Debian .deb packages.

Support for producing Windows MSI installers.

Support for producing Flatpaks.

A carefully-engineered Java API for creating, manipulating, and transforming packages.

A full command-line interface built on top of the Java API.

A Maven plugin for producing packages from any Maven module.

Footnotes

1 | See practically any C or C++ project written in the past thirty years for examples of just how bad this can get. References to this footnote: 1

2. Installation

2.1. Overview

2.2. Shaded Jar

2.1. Overview

There are several ways to install the montarre tool. Regardless of the installation method, the included command-line tool will present the same interface. The documentation is written in terms of executing a command-line tool named montarre. Some installation methods, however, won't result in an executable named montarre being installed. For example, the shaded jar is, unsurprisingly, a jar file. When using this installation method, one should mentally substitute "java -jar com.io7m.montarre.cmdline-1.0.0-SNAPSHOT-main.jar" whenever the documentation mentions the montarre command.

2.2. Shaded Jar

The shaded jar distribution is simply a so-called onejar consisting of all of the application bytecode packed into a single jar file.

Download the jar file signature from Maven Central.

2.2.3. Shaded Jar Signature Download

$ wget https://repo1.maven.org/maven2/com/io7m/montarre/com.io7m.montarre.cmdline/1.0.0-SNAPSHOT/com.io7m.montarre.cmdline-1.0.0-SNAPSHOT-main.jar.asc

Download the jar file from Maven Central.

2.2.5. Shaded Jar Download

$ wget https://repo1.maven.org/maven2/com/io7m/montarre/com.io7m.montarre.cmdline/1.0.0-SNAPSHOT/com.io7m.montarre.cmdline-1.0.0-SNAPSHOT-main.jar

Verify the signature:

2.2.7. Shaded Jar Signature Verification

$ gpg --verify com.io7m.montarre.cmdline-1.0.0-SNAPSHOT-main.jar.asc

Run the jar using an appropriate Java runtime:

2.2.9. Shaded Jar Execution

$ java -jar com.io7m.montarre.cmdline-1.0.0-SNAPSHOT-main.jar
montarre: usage: montarre [command] [arguments ...]

  The montarre command-line application.

  Use the "help" command to examine specific commands:

    $ montarre help help.

  Command-line arguments can be placed one per line into a file, and
  the file can be referenced using the @ symbol:

    $ echo help > file.txt
    $ echo help >> file.txt
    $ montarre @file.txt

  Commands:
    help             Show usage information for a command.
    maven-central    Maven Central commands.
    native           Native package commands.
    package          Package commands.
    version          Show the application version.
    wix              WiX commands.

  Documentation:
    https://www.io7m.com/software/montarre/

3. Usage

3.1. Introduction

3.2. Packages

3.3. Package Declaration

3.4. Maven Plugin

3.5. Command-Line Native Packages

3.1. Introduction

This section of the documentation describes how to use the montarre package whilst attempting to explain as little as possible of exactly how the package works. The specification section, on the other hand, goes into detail on exactly how everything works internally.

3.2. Packages

A montarre package is simply an entomos file containing the jar files that comprise an application along with detailed metadata that provides enough information to allow for easily transforming that package to any number of platform-specific package formats. A montarre package is platform-independent and thus contains the superset of all code that the application might use on all of the platforms upon which it might run. Assuming that one has a suitable Java VM installed, a montarre package can simply be unzipped and then run using the java command [1]. This, obviously, is not particularly interesting in itself, and isn't really the way montarre packages are intended to be used. The interesting aspect of a montarre package is that, with no other configuration required, the package can be used to produce a range of native packages and/or executables relevant to the current platform. For example, a user examining the package on Linux can use a single invocation of the montarre native create command to produce a Debian .deb package, a Flatpak, and/or a simple application image executable.

The first step in using montarre is to have your build system produce a montarre package as one of the outputs. In general, this will be accomplished with a single invocation of the Maven Plugin, but it is also possible to use the command-line tools.

3.3. Package Declaration

Every montarre package contains a package declaration. A package declaration is an XML file with an extremely strict schema, with almost no optional elements [2]. The package declaration serves two purposes:

3.3.2. Package Declaration Purposes

It provides all of the metadata that is used by the tools to produce native packages. For example, the metadata contains Category elements that are used to categorize applications when converting them to Flatpaks.

It provides a list of all of the files included in the package, along with their cryptographic hashes for integrity checks, and type information such as "this file is an icon", "this file is a platform-dependent library that is only used on Linux x86_64", and etc.

In a montarre package, the package declaration is always stored in a special section at the start of the file. As a concrete example, this is the package declaration taken from the montarre package itself:

3.3.4. Montarre Package Declaration

<Package xmlns="urn:com.io7m.montarre.package:1">
    <Metadata ApplicationKind="CONSOLE">
        <Category Name="Building"></Category>
        <Category Name="Development"></Category>
        <Copying Copyright="Copyright © 2024 Mark Raynsford &lt;code@io7m.com> https://www.io7m.com" License="ISC"></Copying>
        <Description>
            <Text Language="en">Package Java applications</Text>
        </Description>
        <Flatpak>
            <FlatpakPermission Value="--share=network"></FlatpakPermission>
            <FlatpakPermission Value="--filesystem=home:rw"></FlatpakPermission>
            <FlatpakRuntime Name="org.freedesktop.Sdk" Role="SDK" Version="24.08"></FlatpakRuntime>
            <FlatpakRuntime Name="org.freedesktop.Platform" Role="PLATFORM" Version="24.08"></FlatpakRuntime>
        </Flatpak>
        <JavaInfo MainModule="com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain" RequiredJDKVersion="21" RuntimeImageKind="JDK"></JavaInfo>
        <Link Role="SCM" Target="https://www.github.com/io7m-com/montarre"></Link>
        <Link Role="ISSUES" Target="https://www.github.com/io7m-com/montarre/issues"></Link>
        <Link Role="HOME_PAGE" Target="https://www.io7m.com/software/montarre"></Link>
        <LongDescription Language="en">
            <Paragraph>The Montarre package provides a set of tools for producing native platform artifacts from platform-independent Java packages.</Paragraph>
            <Feature>A rich, strictly-defined, and well-specified packaging format that remains platform-independent whilst allowing straightforward zero-configuration transformations to a wide range of platform-specific package formats.</Feature>
            <Feature>Extensive, type-driven, ahead-of-time checking; if your package validates, you should get working native packages on all platforms.</Feature>
            <Feature>Reproducible builds by default.</Feature>
            <Feature>Support for producing simple jpackage "app-image" executables on any platform.</Feature>
            <Feature>Support for producing Debian .deb packages.</Feature>
            <Feature>Support for producing Windows MSI installers.</Feature>
            <Feature>Support for producing Flatpaks.</Feature>
            <Feature>A carefully-engineered Java API for creating, manipulating, and transforming packages.</Feature>
            <Feature>A full command-line interface built on top of the Java API.</Feature>
            <Feature>A Maven plugin for producing packages from any Maven module.</Feature>
        </LongDescription>
        <Names HumanName="Montarre" Name="com.io7m.montarre" ShortName="montarre"></Names>
        <Vendor ID="com.io7m" Name="io7m"></Vendor>
        <Version Date="2024-10-06" Number="1.0.0-SNAPSHOT"></Version>
    </Metadata>
    <Manifest>
        <Module File="lib/com.io7m.anethum.api-1.1.1.jar" HashAlgorithm="SHA-256" HashValue="bef5e82eeac406d93b993858e575ba304366ad333d54134969951d1223ff2ce8" Size="15052"></Module>
        <Module File="lib/com.io7m.blackthorne.core-2.0.2.jar" HashAlgorithm="SHA-256" HashValue="48b994b273dddd8a2a410c43db3efcd0d91a71910fc27189a24736313fb2bb23" Size="42944"></Module>
        <Module File="lib/com.io7m.blackthorne.jxe-2.0.2.jar" HashAlgorithm="SHA-256" HashValue="bfcf0e162aa3b636f29f933de5d80f01a1ee1ebb32780f1ff8ca96d56a75ecdf" Size="5166"></Module>
        <Module File="lib/com.io7m.entomos.core-1.0.0.jar" HashAlgorithm="SHA-256" HashValue="dc1a78fdcbb8738054f283b56fea4a9c795a81be7d785495e48b680b998ec089" Size="47780"></Module>
        <Module File="lib/com.io7m.ieee754b16.core-3.0.1.jar" HashAlgorithm="SHA-256" HashValue="dcc74c6914dc3c91c85d5c68a72b7993df791257938dea463897bf1783694bb6" Size="7772"></Module>
        <Module File="lib/com.io7m.jaffirm.core-4.0.1.jar" HashAlgorithm="SHA-256" HashValue="dc02592647284de9b985a3852e3ad967e9ee561d44772d3e4ecd99afbbc22f18" Size="38355"></Module>
        <Module File="lib/com.io7m.jbssio.api-3.0.0.jar" HashAlgorithm="SHA-256" HashValue="dbcf6e45d3df3360c64c748733fce458a3800d4fb6208ded61a56819b4c7e011" Size="21659"></Module>
        <Module File="lib/com.io7m.jbssio.vanilla-3.0.0.jar" HashAlgorithm="SHA-256" HashValue="822f4ad434527728e34d2c44babaef3d57e0d75b7d09c8a9190cce8a24433c76" Size="57643"></Module>
        <Module File="lib/com.io7m.jcip-2.0.1.jar" HashAlgorithm="SHA-256" HashValue="f103daf09059c6969efb7e87dbd427da9dd2b9088224f3aca36e76865edd8ba2" Size="5569"></Module>
        <Module File="lib/com.io7m.jdownload.core-1.0.0.jar" HashAlgorithm="SHA-256" HashValue="807ec26e9b987dd7e5e475f64494501582af0a89375ec106a8307102a269095d" Size="21462"></Module>
        <Module File="lib/com.io7m.jlexing.core-3.2.0.jar" HashAlgorithm="SHA-256" HashValue="e26c6046de6cf41819fe2ed15e38279ce3447cf45430166b0f25a3f589d55c93" Size="12841"></Module>
        <Module File="lib/com.io7m.jmulticlose.core-1.1.3.jar" HashAlgorithm="SHA-256" HashValue="c0e5164f515e530dc210772d98120bbf8f60c9933b9e178e3ad4dbbf4ef43b92" Size="10227"></Module>
        <Module File="lib/com.io7m.junreachable.core-4.0.2.jar" HashAlgorithm="SHA-256" HashValue="979cb909924e8ea64e17b03340c601a8e6b6e1620c4e751a0bd74a34ffb9d5e9" Size="4505"></Module>
        <Module File="lib/com.io7m.jxe.core-2.0.0.jar" HashAlgorithm="SHA-256" HashValue="3520d03a2606787c4e88625f151c9dbbc853bd4987e752c509e6030a83238b67" Size="21622"></Module>
        <Module File="lib/com.io7m.jxtrand.api-2.1.0.jar" HashAlgorithm="SHA-256" HashValue="53c1a2cc739b6359441ba7aacc2aee74166ea416060b197ef6530e8a60052b27" Size="6730"></Module>
        <Module File="lib/com.io7m.jxtrand.vanilla-2.1.0.jar" HashAlgorithm="SHA-256" HashValue="c1bbcea8b4ec0a99093e1ec745036e7849f98687158ad3b777179618052ce9b2" Size="9797"></Module>
        <Module File="lib/com.io7m.lanark.core-1.2.0.jar" HashAlgorithm="SHA-256" HashValue="c725d2de4b82b9632cc2d72219b27f5d4c4700dde3dd2905f965f06894f04503" Size="10609"></Module>
        <Module File="lib/com.io7m.montarre.adoptium-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="4e0c79dbe18d20786f92d6c8978b3213a94b48114772db93f52388f3dce8f99b" Size="33774"></Module>
        <Module File="lib/com.io7m.montarre.api-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="f8a827f86ce9d1bc6cde54e4db17a2a432677c2f7877117d0d123e1710a1858c" Size="137507"></Module>
        <Module File="lib/com.io7m.montarre.cmdline-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="e347bd89dfb53e41c78a1e19a8ed1473e2d9c07e11fce2d0519053efeba7605c" Size="53616"></Module>
        <Module File="lib/com.io7m.montarre.io-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="9892a515defae620f7ee6d3fbc8f2887a277335947f4058e53d4391bab7ebd1c" Size="41291"></Module>
        <Module File="lib/com.io7m.montarre.nativepack-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="04518a5eb1da4df6b545d8f08b4bb83c0c689a497434491132ac2e5720b75354" Size="177400"></Module>
        <Module File="lib/com.io7m.montarre.schema-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="d71defab3dfedabdd4649fb75a60a7cbd0d9c7cced2700b70b7d3090e7d356ee" Size="7271"></Module>
        <Module File="lib/com.io7m.montarre.xml_format-1.0.0-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="6003245560a450b37c6141c50695c5c90b7fc1c1e567cf6c0aaef2eb16ef67c8" Size="63358"></Module>
        <Module File="lib/com.io7m.quarrel.core-1.8.0.jar" HashAlgorithm="SHA-256" HashValue="1102266623a53a5b18b58ff84bdd1eae31d96052635ed3d9b59bb9948a06274e" Size="110771"></Module>
        <Module File="lib/com.io7m.quarrel.ext.logback-1.8.0.jar" HashAlgorithm="SHA-256" HashValue="5497e3eae18c0b622f92af6dcb87bc45ad5fcb87220c504a34acff43f43cd6d6" Size="5986"></Module>
        <Module File="lib/com.io7m.seltzer.api-1.3.0.jar" HashAlgorithm="SHA-256" HashValue="f7840b70ffaa925b6325ff7536188ed4984b60395f8e301e3676ad142f08eb37" Size="9085"></Module>
        <Module File="lib/com.io7m.seltzer.io-1.1.0.jar" HashAlgorithm="SHA-256" HashValue="689065a9ac0f11862c4cd8b432133626302ab39d8f145d7fffd5c4261106a371" Size="6926"></Module>
        <Module File="lib/com.io7m.streamtime.core-1.0.0.jar" HashAlgorithm="SHA-256" HashValue="d062c6142754e507c51a3e127b449ae2d95cf30afb65b4cfd6fffa7f7717a0c8" Size="9750"></Module>
        <Module File="lib/com.io7m.verona.core-1.1.0.jar" HashAlgorithm="SHA-256" HashValue="7c77d2e5e30a44991e0b31a0208c56e7f4398ce31956b2bc0b15841632468df8" Size="11849"></Module>
        <Module File="lib/com.io7m.wendover.core-1.0.2.jar" HashAlgorithm="SHA-256" HashValue="ca694244a9ad2365d2ad19c150e749877d0240f7b60343fde26b330eb181da1c" Size="15615"></Module>
        <Module File="lib/commons-codec-1.19.0.jar" HashAlgorithm="SHA-256" HashValue="5c3881e4f556855e9c532927ee0c9dfde94cc66760d5805c031a59887070af5f" Size="374716"></Module>
        <Module File="lib/commons-compress-1.28.0.jar" HashAlgorithm="SHA-256" HashValue="e1522945218456f3649a39bc4afd70ce4bd466221519dba7d378f2141a4642ca" Size="1117221"></Module>
        <Module File="lib/commons-io-2.21.0.jar" HashAlgorithm="SHA-256" HashValue="7d643a2afea8b058b762aa6fb90e5b256f6c729739f8b3784c3370ddc609e88d" Size="585274"></Module>
        <Module File="lib/commons-lang3-3.20.0.jar" HashAlgorithm="SHA-256" HashValue="69e5c9fa35da7a51a5fd2099dfe56a2d8d32cf233e2f6d770e796146440263f4" Size="713862"></Module>
        <Module File="lib/jackson-annotations-2.21.jar" HashAlgorithm="SHA-256" HashValue="53ca085f4a150f703f49e1aabd935bd03b43e1ea3d55d135438292af22cef56b" Size="82104"></Module>
        <Module File="lib/jackson-core-3.1.0.jar" HashAlgorithm="SHA-256" HashValue="4dd383f96b51b9b9ac4b74bdf1c150df0100443e1da1fba480f57da09a2dcef7" Size="600360"></Module>
        <Module File="lib/jackson-databind-3.1.0.jar" HashAlgorithm="SHA-256" HashValue="1bf5454a1d589a27ddbb91ee16f31f169b08530843f52f5e83f62c650c64516b" Size="1937846"></Module>
        <Module File="lib/jul-to-slf4j-2.0.17.jar" HashAlgorithm="SHA-256" HashValue="a7afcd23b9cfd1475e55c94f943b808c5922035e7e2c2a5c65a487a4106bc538" Size="6349"></Module>
        <Module File="lib/logback-classic-1.5.32.jar" HashAlgorithm="SHA-256" HashValue="2d4cf592db78be2de4d6140434c2fec170dcb16a09e8c8b7b207dbf5e31b848a" Size="286451"></Module>
        <Module File="lib/logback-core-1.5.32.jar" HashAlgorithm="SHA-256" HashValue="6a904d5778d0e361a9692f9cbe68b1b0620ae0f3eda2ec2ed09102755bf036c4" Size="644407"></Module>
        <Module File="lib/slf4j-api-2.0.16.jar" HashAlgorithm="SHA-256" HashValue="a12578dde1ba00bd9b816d388a0b879928d00bab3c83c240f7013bf4196c579a" Size="69435"></Module>
        <Module File="lib/xz-1.12.jar" HashAlgorithm="SHA-256" HashValue="3e158a87bd73d8afb4b6e8239c013b7d049c48563f45860ce99cd2e448cf4a6b" Size="168792"></Module>
        <Resource File="meta/bom.xml" HashAlgorithm="SHA-256" HashValue="1dcbcb2d0153cfc3ae68b988ebc6ece3ca2a604d34cce4c616fa7e87564d93c4" Role="BOM" Size="354765"></Resource>
        <Resource File="meta/icon.ico" HashAlgorithm="SHA-256" HashValue="a36ce859182d76a764bfdb2260b05e0c00580a191e7bc36155a00062ccd06b0e" Role="ICO_WINDOWS" Size="102134"></Resource>
        <Resource File="meta/icon128.png" HashAlgorithm="SHA-256" HashValue="404b0d848df4c98a02804b6e7566b4c4bf27430f7c584381d32cf43a0b3e4028" Role="ICON_128" Size="41273"></Resource>
        <Resource File="meta/icon16.png" HashAlgorithm="SHA-256" HashValue="47734e7530a565bca0d8b3c2015600441b31fe151c59855b4f0af535360e1cf9" Role="ICON_16" Size="544"></Resource>
        <Resource File="meta/icon24.png" HashAlgorithm="SHA-256" HashValue="7597832ef6ebff7f4fa8ac0c8774552f54b47391f8db8479ea96e395556c7da0" Role="ICON_24" Size="732"></Resource>
        <Resource File="meta/icon32.png" HashAlgorithm="SHA-256" HashValue="e3ea34ef4296b538d7ef5d58ad511ab5bd4b4b078a30f1910e9789143c98776a" Role="ICON_32" Size="1973"></Resource>
        <Resource File="meta/icon48.png" HashAlgorithm="SHA-256" HashValue="35d5ada26910c3f707f9b8cfb016b1dca9a575c940018fa5048d71258581b0fc" Role="ICON_48" Size="5461"></Resource>
        <Resource File="meta/icon64.png" HashAlgorithm="SHA-256" HashValue="c30a14e51ade414a6110daa447e8d44cfa10808fa9ce06b4bb67f37def7fd04e" Role="ICON_64" Size="10050"></Resource>
        <Resource File="meta/license.txt" HashAlgorithm="SHA-256" HashValue="cb2db7e26966764c369e6fb4ca08a989e752d926016dd132661a8c64b25149f4" Role="LICENSE" Size="768"></Resource>
        <Resource File="meta/screenshot.png" HashAlgorithm="SHA-256" HashValue="8341f4b229fea93885c52d7ad3797da8803d4e291b3a9e6f8c2c4d4d641637aa" Role="SCREENSHOT" Size="16002">
            <Caption>
                <Text Language="en">The main command-line entry point.</Text>
            </Caption>
        </Resource>
    </Manifest>
</Package>

You are not usually expected to write a package declaration by hand. Instead, the Maven plugin can be used to collect all of the (transitive) dependencies of a project, generate an appropriate manifest, and fill in all of the package declaration information that can be inferred from the Maven POM alone. Anything that cannot be inferred from the POM must be included as configuration parameters to the plugin.

3.4. Maven Plugin

To use the Maven plugin, simply add a plugin execution to the main module in your project:

3.4.2. Maven Plugin Execution

<plugin>
  <groupId>com.io7m.montarre</groupId>
  <artifactId>com.io7m.montarre.maven_plugin</artifactId>
  <version>...</version>
  <executions>
    <execution>
      <id>make-distribution</id>
      <goals>
        <goal>package</goal>
      </goals>
      <phase>package</phase>
      <configuration>
        <validationWarningsAreErrors>true</validationWarningsAreErrors>

        <applicationKind>CONSOLE</applicationKind>

        <categories>
          <category>Development</category>
          <category>Building</category>
        </categories>

        <copyright>Copyright © 2024 Mark Raynsford &lt;code@io7m.com> https://www.io7m.com</copyright>

        <humanName>Montarre</humanName>
        <packageName>com.io7m.montarre</packageName>
        <shortName>montarre</shortName>

        <description>Package Java applications</description>

        <version>
          <number>${project.version}</number>
          <date>2024-10-06</date>
        </version>

        <vendor>
          <id>com.io7m</id>
          <name>io7m</name>
        </vendor>

        <longDescriptions>
          <longDescription>${project.basedir}/src/main/meta/description-en.xml</longDescription>
        </longDescriptions>

        <mainModule>com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain</mainModule>

        <requiredJDKVersion>21</requiredJDKVersion>

        <flatpak>
          <runtimes>
            <runtime>
              <name>org.freedesktop.Sdk</name>
              <version>24.08</version>
              <role>SDK</role>
            </runtime>
            <runtime>
              <name>org.freedesktop.Platform</name>
              <version>24.08</version>
              <role>PLATFORM</role>
            </runtime>
          </runtimes>
          <permissions>
            <permission>--share=network</permission>
            <permission>--filesystem=home:rw</permission>
          </permissions>
        </flatpak>

        <libraries>
          <excludes>
            <exclude>com\.io7m\.montarre\.cmdline-.*-main\.jar</exclude>
            <exclude>com\.io7m\.montarre\.distribution-.*</exclude>
            <exclude>maven-.*</exclude>
            <exclude>com\.io7m\.montarre\.maven_plugin-.*</exclude>
          </excludes>
        </libraries>

        <resources>
          <resource>
            <role>BOM</role>
            <file>${project.build.directory}/bom.xml</file>
            <entryName>bom.xml</entryName>
          </resource>
          <resource>
            <role>ICON_16</role>
            <file>${project.basedir}/src/main/meta/icon16.png</file>
            <entryName>icon16.png</entryName>
          </resource>
          <resource>
            <role>ICON_24</role>
            <file>${project.basedir}/src/main/meta/icon24.png</file>
            <entryName>icon24.png</entryName>
          </resource>
          <resource>
            <role>ICON_32</role>
            <file>${project.basedir}/src/main/meta/icon32.png</file>
            <entryName>icon32.png</entryName>
          </resource>
          <resource>
            <role>ICON_48</role>
            <file>${project.basedir}/src/main/meta/icon48.png</file>
            <entryName>icon48.png</entryName>
          </resource>
          <resource>
            <role>ICON_64</role>
            <file>${project.basedir}/src/main/meta/icon64.png</file>
            <entryName>icon64.png</entryName>
          </resource>
          <resource>
            <role>ICON_128</role>
            <file>${project.basedir}/src/main/meta/icon128.png</file>
            <entryName>icon128.png</entryName>
          </resource>
          <resource>
            <role>SCREENSHOT</role>
            <file>${project.basedir}/src/main/meta/screenshot.png</file>
            <entryName>screenshot.png</entryName>
            <captions>
              <caption>
                <language>en</language>
                <text>The main command-line entry point.</text>
              </caption>
            </captions>
          </resource>
          <resource>
            <role>ICO_WINDOWS</role>
            <file>${project.basedir}/src/main/meta/icon.ico</file>
            <entryName>icon.ico</entryName>
          </resource>
          <resource>
            <role>LICENSE</role>
            <file>${project.basedir}/../README-LICENSE.txt</file>
            <entryName>license.txt</entryName>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Many of the parameters are optional and are inferred from the hosting Maven project if not specified. All parameters are documented in the Maven Plugin documentation.

Upon running the build, a montarre package will be produced and attached to the build. Look for a file with the suffix .mpk:

3.4.5. mpk File

$ ls com.io7m.montarre.distribution/target/*.mpk
com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk

3.5. Command-Line Native Packages

Assuming that you have an existing montarre package (we'll pretend that it's called montarre.mpk), it's possible to produce every type of native package supported by the current system with a single command. Assuming that the current system is Linux, and we're running on the x86_64 hardware architecture, we need to tell the command-line where to get a suitable Java runtime that can be used as the basis for a native package. At the time of writing, there seems to be little reason to use anything other than Eclipse Adoptium as they produce TCK certified runtimes for the widest range of platforms. We call the native create subcommand of the command-line montarre tool, passing it a couple of temporary directories that will be used for temporary files and the outputs of packaging, and a link to a suitable Temurin JRE:

3.5.2. Native Creation

$ montarre native create \
  --package montarre.mpk \
  --work-directory /tmp/work0 \
  --output-directory /tmp/work0-output \
  --java-runtime-download-uri https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.4%2B7/OpenJDK21U-jdk_x64_linux_hotspot_21.0.4_7.tar.gz \
  --java-runtime-sha256 51fb4d03a4429c39d397d3a03a779077159317616550e4e71624c9843083e7b9 \
  --java-runtime-format TAR_GZ

The output of the command is a set of packages in various formats:

3.5.4. Native Creation Outputs

$ ls -alF /tmp/work0-output
total 187632
drwxr-xr-x  2 montarre   montarre        120 Oct 15 12:13 ./
drwxrwxrwt 30 root       root            880 Oct 16 17:37 ../
-rw-r--r--  1 montarre   montarre    4138851 Oct 15 12:13 com.io7m.montarre-0.0.1-SNAPSHOT-any.txz
-rw-r--r--  1 montarre   montarre   81923503 Oct 15 12:11 com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.txz
-rw-r--r--  1 montarre   montarre   52665048 Oct 15 12:13 com.io7m.montarre.flatpak
-rw-r--r--  1 montarre   montarre   53400220 Oct 15 12:11 montarre-0.0.1-SNAPSHOT-x86_64-linux.deb

We can see that the process produced a Debian package named montarre-0.0.1-SNAPSHOT-x86_64-linux.deb, an app-image named com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.txz, a shell distribution named com.io7m.montarre-0.0.1-SNAPSHOT-any.txz, and a Flatpak named com.io7m.montarre.flatpak.

Had this command been run on Windows, the output would likely have included an MSI installer.

Footnotes

1

It might be necessary to adjust the module path to account for the fact that the package might have included, for example, native libraries that should not be placed on the module path on some platforms. The included package metadata contains all of the information required to make these decisions. Most applications do not include native libraries, so the point generally stands.

References to this footnote: 1

2 | The schema is so strict, in fact, that simply creating a Package element in the correct urn:com.io7m.montarre.package:1 namespace in any modern IDE will automatically create and fill in most of the elements! References to this footnote: 1

4. Maven Plugin

4.1. Usage

4.1.1. Overview

4.2. Goals

4.2.1. package

4.2.1.1. Description

4.2.1.2. Configuration Parameters

4.2.1.3. Skipping

4.1. Usage

4.1.1. Overview

4.1.1. Overview

This section of the documentation documents the goals of the montarre Maven plugin.

To use the plugin, add at least the following to your Maven project's build section:

4.1.1.3. Maven Plugin Dependency

<plugin>
  <groupId>com.io7m.montarre</groupId>
  <artifactId>com.io7m.montarre.maven_plugin</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</plugin>

4.2. Goals

4.2.1. package

4.2.1.1. Description

4.2.1.2. Configuration Parameters

4.2.1.2.1. applicationKind

4.2.1.2.2. categories

4.2.1.2.3. copyright

4.2.1.2.4. description

4.2.1.2.5. enableNativeAccess

4.2.1.2.6. extraOptions

4.2.1.2.7. flatpak

4.2.1.2.8. humanName

4.2.1.2.9. libraries

4.2.1.2.10. license

4.2.1.2.11. links

4.2.1.2.12. longDescriptions

4.2.1.2.13. mainModule

4.2.1.2.14. outputFile

4.2.1.2.15. packageName

4.2.1.2.16. version

4.2.1.2.17. platformLibraries

4.2.1.2.18. requiredJDKVersion

4.2.1.2.19. runtimeImageKind

4.2.1.2.20. resources

4.2.1.2.21. shortName

4.2.1.2.22. vendor

4.2.1.3. Skipping

4.2.1. package

4.2.1.1. Description

4.2.1.2. Configuration Parameters

4.2.1.2.1. applicationKind

4.2.1.2.2. categories

4.2.1.2.3. copyright

4.2.1.2.4. description

4.2.1.2.5. enableNativeAccess

4.2.1.2.6. extraOptions

4.2.1.2.7. flatpak

4.2.1.2.8. humanName

4.2.1.2.9. libraries

4.2.1.2.10. license

4.2.1.2.11. links

4.2.1.2.12. longDescriptions

4.2.1.2.13. mainModule

4.2.1.2.14. outputFile

4.2.1.2.15. packageName

4.2.1.2.16. version

4.2.1.2.17. platformLibraries

4.2.1.2.18. requiredJDKVersion

4.2.1.2.19. runtimeImageKind

4.2.1.2.20. resources

4.2.1.2.21. shortName

4.2.1.2.22. vendor

4.2.1.3. Skipping

4.2.1.1. Description

The package goal produces a montarre package from the current module's dependencies.

4.2.1.2. Configuration Parameters

4.2.1.2.1. applicationKind

The applicationKind element specifies the kind of the application. Some operating systems distinguish between graphical and "console" applications, and some packaging standards such as Flatpak also require this information. The element must have one of the following values:

4.2.1.2.1.2. Application Kinds

CONSOLE - The application does not have a graphical interface.

GRAPHICAL - The application has a graphical interface.

4.2.1.2.1.3. Example

<applicationKind>CONSOLE</applicationKind>

4.2.1.2.2. categories

The categories element specifies the categories for the application. The element must contain at least one category element. Each category must have text content matching one of the category values from the freedesktop.org category registry.

4.2.1.2.2.2. Example

<categories>
  <category>Development</category>
  <category>Building</category>
</categories>

4.2.1.2.3. copyright

The copyright element specifies a single-line copyright string.

4.2.1.2.3.2. Example

<copyright>Copyright © 2024 Mark Raynsford &lt;code@io7m.com> https://www.io7m.com</copyright>

4.2.1.2.4. description

The description element specifies a single-line application description.

If this element is not provided, a value is inferred from the Maven POM's description element.

4.2.1.2.4.3. Example

<description>Application packaging tools.</description>

4.2.1.2.5. enableNativeAccess

The enableNativeAccesses element specifies the modules that are permitted to use the Java FFI.

4.2.1.2.5.2. Example

<enableNativeAccesses>
  <enableNativeAccess>com.example.native0</enableNativeAccess>
  <enableNativeAccess>com.example.native1</enableNativeAccess>
</enableNativeAccesses>

4.2.1.2.6. extraOptions

The extraOptions element specifies the extra options that will be passed to the Java runtime at application startup.

4.2.1.2.6.2. Example

<extraOptions>
  <extraOption>-XX:+UseG1GC</extraOption>
</extraOptions>

4.2.1.2.7. flatpak

The flatpak element specifies a Flatpak parameters. The element accepts a runtimes element that specifies dependencies on Flatpak runtimes, and a permissions element that specifies Flatpak permissions that will be requested for the application.

If this element is not provided, a default Flatpak runtime is chosen, and no permissions are specified.

4.2.1.2.7.3. Example

<flatpak>
  <runtimes>
    <runtime>
      <name>org.freedesktop.Sdk</name>
      <version>24.08</version>
      <role>SDK</role>
    </runtime>
    <runtime>
      <name>org.freedesktop.Platform</name>
      <version>24.08</version>
      <role>PLATFORM</role>
    </runtime>
  </runtimes>
  <permissions>
    <permission>--share=network</permission>
    <permission>--filesystem=home:rw</permission>
  </permissions>
</flatpak>

4.2.1.2.8. humanName

The humanName element specifies a humanly-readable application name.

4.2.1.2.8.2. Example

<humanName>Montarre</humanName>

4.2.1.2.9. libraries

The libraries element specifies rules for including and excluding dependencies and artifacts from being included in the resulting montarre package. The element can contain at most one includes element and at most one excludes element. When the Maven plugin is deciding whether to include an artifact in a package, it will compare the filename against each of the inclusion and exclusion patterns. If the file is matched by at least one inclusion filter, and not matched by any exclusion filter, then the file will be treated as included.

The includes element contains a list of include elements, each of which provides a regular expression against which the file names of artifacts are compared.

The excludes element contains a list of exclude elements, each of which provides a regular expression against which the file names of artifacts are compared.

If no libraries element is provided, the plugin acts as if all jar files are included, and nothing is specifically excluded.

4.2.1.2.9.5. Example

<libraries>
  <excludes>
    <exclude>com\.io7m\.montarre\.cmdline-.*-main\.jar</exclude>
    <exclude>com\.io7m\.montarre\.distribution-.*</exclude>
    <exclude>maven-.*</exclude>
    <exclude>com\.io7m\.montarre\.maven_plugin-.*</exclude>
  </excludes>
</libraries>

4.2.1.2.10. license

The license element specifies license information. In particular, the contents of the element must be an SPDX license identifier such as "ISC". If no license element is provided, the license identifier is inferred from the Maven POM's license element.

4.2.1.2.10.2. Example

<license>ISC</license>

4.2.1.2.11. links

The links element specifies links to external resources. These links are used in many packaging systems to provide connections to source code repositories, issue trackers, and etc.

If no links element is provided, the plugin will make a best-effort attempt to extract links from the Maven POM's various elements.

4.2.1.2.11.3. Example

<links>
  <link>
    <role>HOME_PAGE</role>
    <target>https://www.io7m.com/software/montarre/</target>
  </link>
  <link>
    <role>SCM</role>
    <target>https://www.github.com/io7m-com/montarre/</target>
  </link>
  <link>
    <role>ISSUES</role>
    <target>https://www.github.com/io7m-com/montarre/issues/</target>
  </link>
</links>

4.2.1.2.12. longDescriptions

The longDescriptions element specifies longer descriptions of the application. Currently, this data is almost exclusively used for Flatpak applications. The text of long descriptions will be visible to users when published to services such as FlatHub.

The contents of the long description files must be XML long description elements.

4.2.1.2.12.3. Example

<longDescriptions>
  <longDescription>src/main/meta/description-en.xml</longDescription>
</longDescriptions>

4.2.1.2.12.4. Example Description

$ cat src/main/meta/description-en.xml
<?xml version="1.0" encoding="UTF-8" ?>
<LongDescription xmlns="urn:com.io7m.montarre.package:1" Language="en">
  <Paragraph>
    The Montarre package provides a set of tools for producing native platform artifacts from platform-independent Java
    packages.
  </Paragraph>
...

4.2.1.2.13. mainModule

The mainModule element specifies the fully-qualified name of the entry point of the application. The syntax is the same as that expected by the java command: <module>/<mainclass>

4.2.1.2.13.2. Example

<mainModule>com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain</mainModule>

4.2.1.2.14. outputFile

The outputFile element specifies the output file that will be created by the plugin. If not specified, this defaults to the artifact name, version, and a .mpk suffix.

4.2.1.2.14.2. Example

<outputFile>com.io7m.montarre.cmdline-1.0.0-SNAPSHOT.mpk</mainModule>

4.2.1.2.15. packageName

The packageName element specifies a globally-unique package name. This name must be in reverse DNS format conforming to the Lanark name specification.

In particular, this name is used to uniquely identify Flatpak applications and so cannot be changed after it has been published.

4.2.1.2.15.3. Example

<packageName>com.io7m.montarre</packageName>

4.2.1.2.16. version

The version element specifies version information. It must have a number child element whose text content is the full semantic version of the application, and a date child element that indicates when the version number was set.

If no version element is specified, the number child element is set to the value of the Maven POM's version element, and the date child element is set to a fixed value of 2024-10-06 [1].

4.2.1.2.16.3. Example

<version>
  <number>1.0.0-SNAPSHOT</number>
  <date>2024-10-06</date>
</version>

4.2.1.2.17. platformLibraries

The platformLibraries element is similar to the libraries element except that its purpose is to categorize matching artifacts as being platform-dependent. For example, an application might include native library jar files for a number of different platforms, and only the native library for the current platform should actually be placed on the module path when the application is run. The platformLibraries element allows for specifying rules that will mark each matching artifact with their hardware architecture and operating system.

The platformLibraries element contains zero or more platformLibrary elements that each specify a hardware architecture, operating system, and inclusion and exclusion patterns. It operates in the same manner as the libraries element except that, if an artifact is included by a pattern, that artifact is marked as having the hardware architecture and operating system of the platformLibrary element containing the pattern.

If no platformLibraries element is provided, no artifacts are marked as being platform-dependent.

4.2.1.2.17.4. Example

<platformLibraries>
  <platformLibrary>
    <architecture>x86_64</architecture>
    <operatingSystem>linux</operatingSystem>
    <includes>
      <include>lwjgl-natives-linux-amd64\.jar</include>
    </includes>
  </platformLibrary>
  <platformLibrary>
    <architecture>aarch64</architecture>
    <operatingSystem>linux</operatingSystem>
    <includes>
      <include>lwjgl-natives-linux-aarch64\.jar</include>
    </includes>
  </platformLibrary>
  <platformLibrary>
    <architecture>x86_64</architecture>
    <operatingSystem>windows</operatingSystem>
    <includes>
      <include>lwjgl-natives-windows-amd64\.jar</include>
    </includes>
  </platformLibrary>
  <platformLibrary>
    <architecture>aarch64</architecture>
    <operatingSystem>windows</operatingSystem>
    <includes>
      <include>lwjgl-natives-windows-aarch64\.jar</include>
    </includes>
  </platformLibrary>
</platformLibraries>

4.2.1.2.18. requiredJDKVersion

The requiredJDKVersion element specifies the minimum Java version required to run the application.

4.2.1.2.18.2. Example

<requiredJDKVersion>21</requiredJDKVersion>

4.2.1.2.19. runtimeImageKind

The runtimeImageKind element specifies the required time of Java runtime.

4.2.1.2.19.2. Example

<runtimeImageKind>JRE</runtimeImageKind>

4.2.1.2.19.3. Example

<runtimeImageKind>JDK</runtimeImageKind>

4.2.1.2.20. resources

The resources element specifies metadata resources that will be included in the application package. The resources element contains zero or more resource elements that each specify a role, a file, and an entry name.

4.2.1.2.20.2. Example

<resources>
  <resource>
    <role>BOM</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/target/bom.xml</file>
    <entryName>bom.xml</entryName>
  </resource>
  <resource>
    <role>ICON_16</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon16.png</file>
    <entryName>icon16.png</entryName>
  </resource>
  <resource>
    <role>ICON_24</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon24.png</file>
    <entryName>icon24.png</entryName>
  </resource>
  <resource>
    <role>ICON_32</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon32.png</file>
    <entryName>icon32.png</entryName>
  </resource>
  <resource>
    <role>ICON_48</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon48.png</file>
    <entryName>icon48.png</entryName>
  </resource>
  <resource>
    <role>ICON_64</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon64.png</file>
    <entryName>icon64.png</entryName>
  </resource>
  <resource>
    <role>ICON_128</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon128.png</file>
    <entryName>icon128.png</entryName>
  </resource>
  <resource>
    <role>ICO_WINDOWS</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/src/main/meta/icon.ico</file>
    <entryName>icon.ico</entryName>
  </resource>
  <resource>
    <role>LICENSE</role>
    <file>/workspace/io7m-com/montarre/com.io7m.montarre.documentation/../README-LICENSE.txt</file>
    <entryName>license.txt</entryName>
  </resource>
</resources>

4.2.1.2.21. shortName

The shortName element specifies the shortened name of the package. This is used in a number of places. For example, the executable produced by jpackage when producing an app-image will be named according to the short name. Additionally, packaging systems such as Debian packages will use the short name instead of the package name due to being unable to support reverse DNS notation.

4.2.1.2.21.2. Example

<shortName>montarre</requiredJDKVersion>

4.2.1.2.22. vendor

The vendor element specifies information about the vendor of the package. It must contain an id element specifying the globally unique, reverse DNS identifier of the vendor, and a name element specifying a filesystem-safe vendor name. Some packaging systems will use the vendor name as a directory name, so the name must be limited to short, filesystem-safe names. A sensible approach for vendor IDs is to use a prefix of your Maven group name (or perhaps just the entire group name if you use the same group name in every project).

4.2.1.2.22.2. Example

<vendor>
  <id>com.io7m</id>
  <name>io7m</name>
</vendor>

4.2.1.3. Skipping

The plugin execution can be skipped by setting the montarre.skip property to true.

Footnotes

1 | A fixed date value is used in order to avoid making builds non-reproducible by inserting a varying date value into packages. References to this footnote: 1

5. Command Line

5.1. Overview

5.2. help

5.2.1. Name

5.2.2. Description

5.2.3. Examples

5.3. maven-central download

5.3.1. Name

5.3.2. Description

5.3.3. Parameters

5.3.4. Examples

5.4. native create

5.4.1. Name

5.4.2. Description

5.4.3. Parameters

5.4.4. Examples

5.5. native packagers

5.5.1. Name

5.5.2. Description

5.5.3. Parameters

5.5.4. Examples

5.6. package check

5.6.1. Name

5.6.2. Description

5.6.3. Parameters

5.6.4. Examples

5.7. package extract-declaration

5.7.1. Name

5.7.2. Description

5.7.3. Parameters

5.7.4. Examples

5.8. package pack

5.8.1. Name

5.8.2. Description

5.8.3. Parameters

5.8.4. Examples

5.9. package schema

5.9.1. Name

5.9.2. Description

5.9.3. Parameters

5.9.4. Examples

5.10. package unpack

5.10.1. Name

5.10.2. Description

5.10.3. Parameters

5.10.4. Examples

5.11. package validate

5.11.1. Name

5.11.2. Description

5.11.3. Parameters

5.11.4. Examples

5.12. version

5.12.1. Name

5.12.2. Description

5.12.3. Examples

5.13. wix xml

5.13.1. Name

5.13.2. Description

5.13.3. Parameters

5.13.4. Examples

5.1. Overview

The montarre package provides a command-line interface for performing tasks such as starting the server, checking configuration files, hashing passwords, and etc. The base montarre command is broken into a number of subcommands which are documented over the following sections.

5.1.2. Command-Line Overview

montarre: usage: montarre [command] [arguments ...]

  The montarre command-line application.

  Use the "help" command to examine specific commands:

    $ montarre help help.

  Command-line arguments can be placed one per line into a file, and
  the file can be referenced using the @ symbol:

    $ echo help > file.txt
    $ echo help >> file.txt
    $ montarre @file.txt

  Commands:
    help             Show usage information for a command.
    maven-central    Maven Central commands.
    native           Native package commands.
    package          Package commands.
    version          Show the application version.
    wix              WiX commands.

  Documentation:
    https://www.io7m.com/software/montarre/

All subcommands accept a --verbose parameter that may be set to one of trace, debug, info, warn, or error. This parameter sets the lower bound for the severity of messages that will be logged. For example, at debug verbosity, only messages of severity debug and above will be logged. Setting the verbosity to trace level effectively causes everything to be logged, and will produce large volumes of debugging output.

The montarre command-line tool uses quarrel to parse command-line arguments, and therefore supports placing command-line arguments into a file, one argument per line, and then referencing that file with @. For example:

5.1.5. @ Syntax

$ montarre package check --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk
...

$ (cat <<EOF
package
check
--file
com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk
EOF
) > args.txt

$ montarre @args.txt

All subcommands, unless otherwise specified, yield an exit code of 0 on success, and a non-zero exit code on failure.

5.2. help

5.2.1. Name

5.2.2. Description

5.2.3. Examples

5.2.1. Name

help - Show usage information for a command.

5.2.2. Description

The help command shows the help for a given command.

5.2.3. Examples

5.2.3.1. Example

$ montarre help package check
montarre: usage: check [named-arguments ...]

  Check a package file.

  Named parameters:
    --check-hashes
      Description       : Whether to check file hashes.
      Type              : Boolean
      Cardinality       : [1]; Specify exactly once, or use the default.
      Default value     : true
      Syntax            : true | false
  * --file
      Description       : The input file.
      Type              : Path
      Cardinality       : [1]; Specify exactly once.
      Syntax            : <platform-specific path syntax>
    --verbose
      Description       : Set the logging level of the application.
      Type              : QLogLevel
      Cardinality       : [1]; Specify exactly once, or use the default.
      Default value     : info
      Syntax            : trace|debug|info|warn|error

  The command does not accept any positional arguments.

5.3. maven-central download

5.3.1. Name

5.3.2. Description

5.3.3. Parameters

5.3.4. Examples

5.3.1. Name

maven-central download - Download a package from Maven Central

5.3.2. Description

The maven-central download command downloads an artifact from Maven Central, or an appropriate remote Maven repository.

The command takes --base-uri-snapshots and --base-uri-releases parameters that are, by default, configured to point to the Sonatype Snapshots repository and the Maven Central releases repository. If the version number given by the --version parameter ends with the string -SNAPSHOT, the repository named by --base-uri-snapshots is used for downloads. Otherwise, the repository named by --base-uri-releases is used.

5.3.3. Parameters

5.3.3.1. --artifact

Attribute | Value
Name | --artifact
Type | java.lang.String
Default Value |
Cardinality | [1, 1]
Description | The artifact name.

5.3.3.2. --base-uri-releases

Attribute | Value
Name | --base-uri-releases
Type | java.net.URI
Default Value | https://repo1.maven.org/maven2
Cardinality | [1, 1]
Description | The base repository URI for release versions.

5.3.3.3. --base-uri-snapshots

Attribute | Value
Name | --base-uri-snapshots
Type | java.net.URI
Default Value | https://s01.oss.sonatype.org/content/repositories/snapshots
Cardinality | [1, 1]
Description | The base repository URI for -SNAPSHOT versions.

5.3.3.4. --classifier

Attribute | Value
Name | --classifier
Type | java.lang.String
Default Value |
Cardinality | [0, 1]
Description | The classifier name.

5.3.3.5. --group

Attribute | Value
Name | --group
Type | java.lang.String
Default Value |
Cardinality | [1, 1]
Description | The group name.

5.3.3.6. --output-file

Attribute | Value
Name | --output-file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output file.

5.3.3.7. --type

Attribute | Value
Name | --type
Type | java.lang.String
Default Value | jar
Cardinality | [1, 1]
Description | The artifact type.

5.3.3.8. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.3.3.9. --version

Attribute | Value
Name | --version
Type | java.lang.String
Default Value |
Cardinality | [1, 1]
Description | The version.

5.3.4. Examples

5.3.4.1. Example

$ montarre maven-central download \
--artifact com.io7m.junreachable.core \
--version 4.0.0 \
--group com.io7m.junreachable \
--output-file junreachable.jar
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: Downloading: https://repo1.maven.org/maven2/com/io7m/junreachable/com.io7m.junreachable.core/4.0.0/com.io7m.junreachable.core-4.0.0.jar
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: Checksum: https://repo1.maven.org/maven2/com/io7m/junreachable/com.io7m.junreachable.core/4.0.0/com.io7m.junreachable.core-4.0.0.jar.sha1
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: Download: 0 bytes/4 KB (0 bytes/s) ~PT0S remaining
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: Download: 0 bytes/40 bytes (0 bytes/s) ~PT0S remaining

5.4. native create

5.4.1. Name

5.4.2. Description

5.4.3. Parameters

5.4.4. Examples

5.4.1. Name

native create - Create native packages.

5.4.2. Description

The native create command creates native packages using every supported native packager on the current system.

Most native packagers require embedding a Java runtime. It is necessary to specify a runtime that will downloaded as part of producing native packages. There are currently two mutually exclusive options for this:

5.4.2.3. Runtimes

Use the --java-runtime-download-uri parameters to specify the address of a runtime. If this parameter is specified, then it is also necessary to specify the --java-runtime-format and --java-runtime-sha256 parameters.

Use the --adoptium-temurin-version parameter to specify an Eclipse Adoptium release. This will cause a runtime with a matching version to be downloaded using the Adoptium API.

As Java runtime packaging formats differ between platforms (Windows uses .zip archives, POSIX platforms use .tar.gz), and because hash values will be different for every runtime on every platform, it is generally preferable to use the Adoptium API. The API provides checksum values for integrity checking, and published artifacts are immutable, so reproducibility is not affected. The downside to using the Adoptium API is that the API does not keep runtime versions visible indefinitely, so older version numbers might disappear from the API as new runtimes are released.

The command will run every supported native packager unless the --include-packagers option is used to limit execution to only the named packagers.

5.4.3. Parameters

5.4.3.1. --adoptium-temurin-version

Attribute | Value
Name | --adoptium-temurin-version
Type | java.lang.Runtime.Version
Default Value |
Cardinality | [0, 1]
Description | The version of the Adoptium Temurin runtime to use.

5.4.3.2. --include-packagers

Attribute | Value
Name | --include-packagers
Type | java.lang.String
Default Value | []
Cardinality | [0, N]
Description | Only run the named packagers.

5.4.3.3. --java-runtime-download-uri

Attribute | Value
Name | --java-runtime-download-uri
Type | java.net.URI
Default Value |
Cardinality | [0, 1]
Description | The location for a Java runtime.

5.4.3.4. --java-runtime-format

Attribute | Value
Name | --java-runtime-format
Type | com.io7m.montarre.api.MArchiveFormat
Default Value |
Cardinality | [0, 1]
Description | The format of the Java runtime archive.

5.4.3.5. --java-runtime-sha256

Attribute | Value
Name | --java-runtime-sha256
Type | java.lang.String
Default Value |
Cardinality | [0, 1]
Description | The SHA-256 of the Java runtime.

5.4.3.6. --output-directory

Attribute | Value
Name | --output-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output directory.

5.4.3.7. --package

Attribute | Value
Name | --package
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input package.

5.4.3.8. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.4.3.9. --work-directory

Attribute | Value
Name | --work-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The work directory.

5.4.4. Examples

5.4.4.1. Example

$ montarre native create \
  --verbose info \
  --package com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk \
  --work-directory /tmp/work0 \
  --output-directory /tmp/work0-output \
  --java-runtime-download-uri https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.4%2B7/OpenJDK21U-jdk_x64_linux_hotspot_21.0.4_7.tar.gz \
  --java-runtime-sha256 51fb4d03a4429c39d397d3a03a779077159317616550e4e71624c9843083e7b9 \
  --java-runtime-format TAR_GZ
INFO com.io7m.montarre.cmdline.internal.MCNativeCreate: Opening package com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk.
INFO com.io7m.montarre.cmdline.internal.MCNativeCreate: Creating output directory /tmp/work0-output
INFO com.io7m.montarre.cmdline.internal.MCNativeCreate: Creating workspace /tmp/work0.
INFO com.io7m.montarre.cmdline.internal.MCNativeCreate: Workspace architecture: x86_64
INFO com.io7m.montarre.cmdline.internal.MCNativeCreate: Workspace OS: linux
...

$ ls -alF /tmp/work0-output/
total 187632
drwxr-xr-x  2 montarre   montarre        120 Oct 13 12:13 ./
drwxrwxrwt 29 root       root            840 Oct 13 12:12 ../
-rw-r--r--  1 montarre   montarre    4138851 Oct 13 12:13 com.io7m.montarre-0.0.1-SNAPSHOT-any.txz
-rw-r--r--  1 montarre   montarre   81923503 Oct 13 12:11 com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.txz
-rw-r--r--  1 montarre   montarre   52665048 Oct 13 12:13 com.io7m.montarre.flatpak
-rw-r--r--  1 montarre   montarre   53400220 Oct 13 12:11 montarre-0.0.1-SNAPSHOT-x86_64-linux.deb

5.5. native packagers

5.5.1. Name

5.5.2. Description

5.5.3. Parameters

5.5.4. Examples

5.5.1. Name

native packagers - List native packagers.

5.5.2. Description

The native packagers command lists all of the available native packagers along with information about why each one is or is not supported on the current platform.

5.5.3. Parameters

5.5.3.1. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.5.4. Examples

5.5.4.1. Example

$ montarre native packagers
Name: com.io7m.montarre.app_image
Description: Produces jpackage 'app-images'.
Supported: yes
--

Name: com.io7m.montarre.deb
Description: Produces Debian .deb packages.
Supported: yes
--

Name: com.io7m.montarre.flatpak
Description: Produces Flatpak packages.
Supported: yes
--

Name: com.io7m.montarre.msi_wix
Description: Produces MSI packages.
Supported: no
Reason: Cannot run program "wix": error=2, No such file or directory
Exception:
com.io7m.montarre.api.MException: Cannot run program "wix": error=2, No such file or directory
	at com.io7m.montarre.nativepack.MNativeProcesses.executeAndWait(MNativeProcesses.java:109)
	at com.io7m.montarre.nativepack.internal.msi.MNPackagerMSI.unsupportedReason(MNPackagerMSI.java:93)
	at com.io7m.montarre.cmdline.internal.MCNativePackagers.onExecute(MCNativePackagers.java:89)
	at com.io7m.quarrel.core.internal.QCommandContext.execute(QCommandContext.java:207)
	at com.io7m.quarrel.core.QApplicationType.run(QApplicationType.java:94)
	at com.io7m.montarre.cmdline.MMain.run(MMain.java:191)
	at com.io7m.montarre.cmdline.MMain.mainExitless(MMain.java:166)
	at com.io7m.montarre.cmdline.MMain.main(MMain.java:151)
Caused by: java.io.IOException: Cannot run program "wix": error=2, No such file or directory
	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1170)
	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1089)
	at com.io7m.montarre.nativepack.MNativeProcesses.executeAndWait(MNativeProcesses.java:76)
	... 7 more
Caused by: java.io.IOException: error=2, No such file or directory
	at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
	at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:295)
	at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:225)
	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1126)
	... 9 more
--

Name: com.io7m.montarre.shell
Description: Produces shell packages.
Supported: yes
--

5.6. package check

5.6.1. Name

5.6.2. Description

5.6.3. Parameters

5.6.4. Examples

5.6.1. Name

package check - Check a package file.

5.6.2. Description

The package check command checks the integrity of the contents of the given package. More precisely, it computes the checksum of every file in the package and compares the resulting checksum with the value recorded in the manifest.

5.6.3. Parameters

5.6.3.1. --check-hashes

Attribute | Value
Name | --check-hashes
Type | java.lang.Boolean
Default Value | true
Cardinality | [1, 1]
Description | Whether to check file hashes.

5.6.3.2. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input file.

5.6.3.3. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.6.4. Examples

5.6.4.1. Example

$ montarre package check --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.anethum.api-1.1.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.blackthorne.core-2.0.2.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.blackthorne.jxe-2.0.2.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jaffirm.core-4.0.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jcip-2.0.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jdownload.core-1.0.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jlexing.core-3.2.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jmulticlose.core-1.1.3.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.junreachable.core-4.0.2.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jxe.core-2.0.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jxtrand.api-2.1.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.jxtrand.vanilla-2.1.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.lanark.core-1.2.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.api-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.cmdline-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.io-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.nativepack-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.schema-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.montarre.xml-0.0.1-SNAPSHOT.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.quarrel.core-1.6.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.quarrel.ext.logback-1.6.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.seltzer.api-1.1.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.streamtime.core-1.0.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/com.io7m.verona.core-1.0.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/commons-codec-1.17.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/commons-compress-1.27.1.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/commons-io-2.17.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/commons-lang3-3.17.0.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/logback-classic-1.5.8.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/logback-core-1.5.8.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: lib/slf4j-api-2.0.16.jar: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/bom.xml: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon.ico: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon128.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon16.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon24.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon32.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon48.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/icon64.png: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/license.txt: OK
INFO com.io7m.montarre.cmdline.internal.MCPackageCheck: meta/screenshot.png: OK

5.7. package extract-declaration

5.7.1. Name

5.7.2. Description

5.7.3. Parameters

5.7.4. Examples

5.7.1. Name

package extract-declaration - Extract a package declaration from a file without validation.

5.7.2. Description

The package extract-declaration command prints the serialized package declaration from the given package file.

5.7.3. Parameters

5.7.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input file.

5.7.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.7.4. Examples

5.7.4.1. Example

$ montarre package extract-declaration --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk
<Package xmlns="urn:com.io7m.montarre.package:1">
    <Metadata ApplicationKind="CONSOLE">
        <Category Name="Building"></Category>
...

5.8. package pack

5.8.1. Name

5.8.2. Description

5.8.3. Parameters

5.8.4. Examples

5.8.1. Name

package pack - Pack a package file.

5.8.2. Description

The package pack command produces a package file from a directory hierarchy.

The command is the inverse of the package unpack command. Unpacking and then repacking should yield a byte-for-byte identical package file.

5.8.3. Parameters

5.8.3.1. --input-directory

Attribute | Value
Name | --input-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input directory.

5.8.3.2. --output-file

Attribute | Value
Name | --output-file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output file.

5.8.3.3. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.8.4. Examples

5.8.4.1. Example

$ montarre package pack --input-directory /tmp/out2 --output-file montarre.mpk

5.9. package schema

5.9.1. Name

5.9.2. Description

5.9.3. Parameters

5.9.4. Examples

5.9.1. Name

package schema - Show the package schema.

5.9.2. Description

The package schema command prints the currently-supported package schema.

5.9.3. Parameters

5.9.3.1. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.9.3.2. --version

Attribute | Value
Name | --version
Type | java.lang.Integer
Default Value | 1
Cardinality | [1, 1]
Description | The schema version.

5.9.4. Examples

5.9.4.1. Example

$ montarre package schema
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="urn:com.io7m.montarre.package:1"
            xmlns:mp="urn:com.io7m.montarre.package:1">

  <xsd:simpleType name="ApplicationKindType">
    <xsd:annotation>
...

5.10. package unpack

5.10.1. Name

5.10.2. Description

5.10.3. Parameters

5.10.4. Examples

5.10.1. Name

package unpack - Unpack a package file.

5.10.2. Description

The package unpack command unpacks every file from the given package file.

The command is the inverse of the package pack command. Unpacking and then repacking should yield a byte-for-byte identical package file.

5.10.3. Parameters

5.10.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input file.

5.10.3.2. --output-directory

Attribute | Value
Name | --output-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output directory.

5.10.3.3. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.10.4. Examples

5.10.4.1. Example

$ montarre package unpack \
  --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk \
  --output-directory /tmp/out2

$ ls -alF /tmp/out2/
total 0
drwxr-xr-x  5 montarre   montarre   100 Oct 13 12:19 ./
drwxrwxrwt 30 root       root       860 Oct 13 12:19 ../
drwxr-xr-x  3 montarre   montarre    60 Oct 13 12:19 META-INF/
drwxr-xr-x  2 montarre   montarre   660 Oct 13 12:19 lib/
drwxr-xr-x  2 montarre   montarre   240 Oct 13 12:19 meta/

5.11. package validate

5.11.1. Name

5.11.2. Description

5.11.3. Parameters

5.11.4. Examples

5.11.1. Name

package validate - Validate a package file.

5.11.2. Description

The package validate command runs validation on the given package file.

5.11.3. Parameters

5.11.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input file.

5.11.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.11.3.3. --warnings-as-errors

Attribute | Value
Name | --warnings-as-errors
Type | java.lang.Boolean
Default Value | true
Cardinality | [1, 1]
Description | Whether to treat warnings as errors.

5.11.4. Examples

5.11.4.1. Example

$ montarre package validate --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk

5.12. version

5.12.1. Name

5.12.2. Description

5.12.3. Examples

5.12.1. Name

version - Show the application version.

5.12.2. Description

The version command shows the current application version.

5.12.3. Examples

5.12.3.1. Example

$ montarre version
com.io7m.montarre 0.0.1-SNAPSHOT f47e12fd7363837c6358eeec53b3122645b06df5

5.13. wix xml

5.13.1. Name

5.13.2. Description

5.13.3. Parameters

5.13.4. Examples

5.13.1. Name

wix xml - Generate WiX XML.

5.13.2. Description

The wix xml command generates a WiX toolset file from a given package and directory hierarchy.

5.13.3. Parameters

5.13.3.1. --input-directory

Attribute | Value
Name | --input-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input directory.

5.13.3.2. --package

Attribute | Value
Name | --package
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The input package.

5.13.3.3. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

5.13.4. Examples

5.13.4.1. Example

$ montarre wix xml --input-directory /tmp/out2 --package montarre.mpk
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
    <Package Language="1033" Manufacturer="io7m" Name="com.io7m.montarre" UpgradeCode="2e11817e-7476-336d-8cc7-1baa130f30dc" Version="0.0.1-SNAPSHOT.0">
        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed."></MajorUpgrade>
        <Icon Id="Icon.ico" SourceFile="/tmp/out2/meta/icon.ico"></Icon>
        <Property Id="ARPPRODUCTICON" Value="Icon.ico"></Property>
        <MediaTemplate EmbedCab="yes"></MediaTemplate>
        <StandardDirectory Id="ProgramFilesFolder">
            <Directory Id="CompanyFolder" Name="io7m">
                <Directory Id="INSTALLLOCATION" Name="com.io7m.montarre"></Directory>
            </Directory>
...

6. Packagers

6.1. com.io7m.montarre.app_image

6.1.1. Overview

6.1.2. Description

6.1.3. Outputs

6.2. com.io7m.montarre.deb

6.2.1. Overview

6.2.2. Outputs

6.3. com.io7m.montarre.flatpak

6.3.1. Overview

6.3.2. Outputs

6.4. com.io7m.montarre.msi

6.4.1. Overview

6.4.2. Requirements

6.4.3. Outputs

6.5. com.io7m.montarre.shell

6.5.1. Overview

6.5.2. Description

6.5.3. Batch File

6.5.4. Shell Script

6.5.5. Launch Jar

6.5.5.1. Overview

6.5.5.2. Get-Arch

6.5.5.3. Get-OS

6.5.5.4. Check-Java-Version

6.5.5.5. Get-Module-Path

6.5.6. Outputs

6.1. com.io7m.montarre.app_image

6.1.1. Overview

6.1.2. Description

6.1.3. Outputs

6.1.1. Overview

The com.io7m.montarre.app_image packager creates jpackage "app image" executables.

6.1.2. Description

The com.io7m.montarre.app_image packager takes a montarre package and produces a platform-specific app image distribution using the jpackage tool.

The output of the com.io7m.montarre.app_image packager is typically used as input to other platform-specific packagers such as com.io7m.montarre.deb and com.io7m.montarre.msi, amongst others.

6.1.3. Outputs

Given a package name, version number, architecture name, and operating system name, the output of the packager will be one of the following:

6.1.3.2. Outputs

${PACKAGE_NAME}-${PACKAGE_VERSION}-${ARCH_NAME}-${OS_NAME}.zip on Windows-like platforms.

${PACKAGE_NAME}-${PACKAGE_VERSION}-${ARCH_NAME}-${OS_NAME}.txz on POSIX-like platforms.

An example output of the packager is com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.txz.

6.2. com.io7m.montarre.deb

6.2.1. Overview

6.2.2. Outputs

6.2.1. Overview

The com.io7m.montarre.deb packager creates Debian packages.

6.2.2. Outputs

Given a short name, version number, architecture name, and operating system name, the output of the packager will be ${SHORT_NAME}-${PACKAGE_VERSION}-${ARCH_NAME}-${OS_NAME}.deb unconditionally.

An example output of the packager is montarre-0.0.1-SNAPSHOT-x86_64-linux.deb.

6.3. com.io7m.montarre.flatpak

6.3.1. Overview

6.3.2. Outputs

6.3.1. Overview

The com.io7m.montarre.flatpak packager creates Flatpaks.

6.3.2. Outputs

Given a package name, the output of the packager will be ${PACKAGE_NAME}.flatpak unconditionally.

An example output of the packager is com.io7m.montarre.flatpak.

6.4. com.io7m.montarre.msi

6.4.1. Overview

6.4.2. Requirements

6.4.3. Outputs

6.4.1. Overview

The com.io7m.montarre.msi packager creates MSI installers.

6.4.2. Requirements

The packager requires the WiX toolset to be installed. At least version 4.0.0 is required, and version 5.0.0 is actively used for testing. The packager will attempt to run the wix.exe executable for all tasks, so the toolset needs to be included in the PATH variable in the environment of the JVM running the packager.

6.4.3. Outputs

Given a short name, version number, architecture name, and operating system name, the output of the packager will be ${SHORT_NAME}-${PACKAGE_VERSION}-${ARCH_NAME}-${OS_NAME}.msi unconditionally.

An example output of the packager is montarre-0.0.1-SNAPSHOT-x86_64-windows.msi. This packager currently only works on Windows, so the operating system name is arguably redundant.

6.5. com.io7m.montarre.shell

6.5.1. Overview

6.5.2. Description

6.5.3. Batch File

6.5.4. Shell Script

6.5.5. Launch Jar

6.5.5.1. Overview

6.5.5.2. Get-Arch

6.5.5.3. Get-OS

6.5.5.4. Check-Java-Version

6.5.5.5. Get-Module-Path

6.5.6. Outputs

6.5.1. Overview

The com.io7m.montarre.shell packager creates platform-independent shell distributions.

6.5.2. Description

The com.io7m.montarre.shell packager takes a montarre package and produces a platform-independent shell distribution. The term shell is used here to indicate that the distribution is really nothing more than simply running the system's java command on the jar files contained within the package using the system's shell.

A shell distribution is a tar file [1] containing the following files (where ${SHORT_NAME} is the short name of the application):

6.5.2.3. Files

File | Description
${SHORT_NAME}/META-INF/MONTARRE/PACKAGE.XML | The original package declaration taken from the input package.
${SHORT_NAME}/bin/launch.jar | The launch jar.
${SHORT_NAME}/bin/${SHORT_NAME} | The shell script for POSIX-like systems.
${SHORT_NAME}/bin/${SHORT_NAME}.bat | The batch file for Windows-like systems.
${SHORT_NAME}/lib/*.jar | The platform-neutral jar files for the application.
${SHORT_NAME}/lib/${ARCH}/${OS}/*.jar | The platform-specific jar files for the application, organized by architecture and operating system.
${SHORT_NAME}/meta/* | The metadata files taken from the input package.

Assuming that the current hardware architecture is ${ARCH}, the operating system is ${OS}, the application's main class is ${MAIN_CLASS}, and the short name of the application is ${SHORT_NAME}, then the application can be trivially executed with the following java invocation:

6.5.2.5. Example Invocation

$ java -p "${SHORT_NAME}/lib:${SHORT_NAME}/lib/${ARCH}/${OS}" -m "${MAIN_CLASS}"

However, the simplicity of the above invocation hides a few important details:

6.5.2.7. Missing Details

How does the caller assign a suitable value for ${ARCH}?

How does the caller assign a suitable value for ${OS}?

What happens on a system that uses ; as a module path separator instead of : ?

What happens on a system that uses \ as a file path separator instead of / ?

What happens if the package requires JDK 21, but the user is only running JDK 20 (or some other insufficient version)?

To solve the above problems, the packager provides a batch file (for Windows-like systems), and a shell script (for POSIX-like systems) that perform the above invocations in a platform-appropriate way, making calls into an included launch jar that knows how to fetch hardware architecture names in a system-independent manner, fetch operating system names in a system-independent manner, build module paths correctly, and check for the correct Java version.

6.5.3. Batch File

The shell distribution contains a Windows batch file that can be used to execute the application on Windows-like platforms. The batch file is generated based on the Java version requirement given in the input package, and the short name of the application. The short name is converted to uppercase and suffixed with the string _HOME to produce the name of an environment variable that will be consulted to find the location of the unpacked distribution. For example, in an application named montarre, the environment variable named MONTARRE_HOME will be consulted and is expected to contain the full path to the unpacked shell distribution. The application would therefore be executed as follows:

6.5.3.2. Example Batch

c:> cd montarre

c:\montarre> dir
 Volume in drive C has no label.
 Volume Serial Number is 187C-D7E2

 Directory of c:\montarre

13/10/2024  18:34    <DIR>          .
13/10/2024  18:34    <DIR>          ..
13/10/2024  16:03    <DIR>          bin
13/10/2024  16:03    <DIR>          lib
13/10/2024  16:03    <DIR>          meta
13/10/2024  15:34    <DIR>          META-INF
               6 Dir(s)  485,913,133,056 bytes free

c:\montarre> bin\montarre.bat
MONTARRE_HOME is unset

c:\montarre> set MONTARRE_HOME=c:\montarre

c:\montarre> bin\montarre.bat
montarre: usage: montarre [command] [arguments ...]

  The montarre command-line application.
...

As an example, the batch file generated for the montarre application looks like this:

6.5.3.4. Example Batch File

@echo off

REM Auto generated: Do not edit.
REM This is a launch script for Windows-like platforms.

if NOT DEFINED MONTARRE_HOME (
  echo MONTARRE_HOME is unset
  exit /b 1
)

REM Check that the available Java runtime is suitable.
java -jar "%MONTARRE_HOME%/bin/launch.jar" check-java-version 21
if %errorlevel% neq 0 exit /b 1

REM Build a module path.
for /f %%i in ('java -jar %MONTARRE_HOME%\bin\launch.jar get-module-path %MONTARRE_HOME%') do set MONTARRE_MODULE_PATH=%%i
if %errorlevel% neq 0 exit /b 1

REM Run the application.
java -p %MONTARRE_MODULE_PATH% -m com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain %*
if %errorlevel% neq 0 exit /b 1

6.5.4. Shell Script

The shell distribution contains a POSIX bourne shell script that can be used to execute the application on POSIX-like platforms. The shell script is generated based on the Java version requirement given in the input package, and the short name of the application. The short name is converted to uppercase and suffixed with the string _HOME to produce the name of an environment variable that will be consulted to find the location of the unpacked distribution. For example, in an application named montarre, the environment variable named MONTARRE_HOME will be consulted and is expected to contain the full path to the unpacked shell distribution. The application would therefore be executed as follows:

6.5.4.2. Example Batch

$ cd montarre

$ ls
META-INF  bin  lib  meta

$ ./bin/montarre
MONTARRE_HOME is unset

$ export MONTARRE_HOME=$(realpath .)

$ ./bin/montarre
montarre: usage: montarre [command] [arguments ...]

  The montarre command-line application.
...

As an example, the shell script generated for the montarre application looks like this:

6.5.4.4. Example Shell Script

#!/bin/sh
# Auto generated: Do not edit.
# This is a launch script for UNIX-like platforms.

if [ -z "${MONTARRE_HOME}" ]
then
  echo "MONTARRE_HOME is unset" 1>&2
  exit 1
fi

#
# Check that the available Java runtime is suitable.
#

/usr/bin/env java -jar "${MONTARRE_HOME}/bin/launch.jar" \
  check-java-version 21 || exit 1

#
# Build a module path. This is guaranteed to be:
#   ${MONTARRE_HOME}/lib
#   ${MONTARRE_HOME}/lib/${ARCH}/${OS}
#

MONTARRE_MODULE_PATH=$(/usr/bin/env java -jar "${MONTARRE_HOME}/bin/launch.jar" \
  get-module-path "${MONTARRE_HOME}") || exit 1

#
# Run the application.
#

exec /usr/bin/env java \
  -p "${MONTARRE_MODULE_PATH}" \
  -m com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain \
  "$@"

6.5.5. Launch Jar

6.5.5.1. Overview

The launch jar is a tiny jar file that exposes a command-line interface to perform some necessary startup tasks in a platform-independent manner.

The launch jar is compiled as JDK 9 bytecode and is not supported on systems running Java versions older than that.

6.5.5.2. Get-Arch

The Get-Arch command returns the name of the current hardware architecture.

6.5.5.2.2. Example

$ java -jar bin/launch.jar Get-Arch
x86_64

C:> java -jar bin\launch.jar Get-Arch
x86_64

6.5.5.3. Get-OS

The Get-OS command returns the name of the current operating system.

6.5.5.3.2. Example

$ java -jar bin/launch.jar Get-OS
linux

C:> java -jar bin\launch.jar Get-OS
windows

6.5.5.4. Check-Java-Version

The Check-Java-Version command checks to see if the current Java runtime version is greater than or equal to the provided major version argument. If the current Java runtime version is sufficient, the command says nothing.

6.5.5.4.2. Example

$ java --version
openjdk 21.0.4 2024-07-16
OpenJDK Runtime Environment (build 21.0.4+7)
OpenJDK 64-Bit Server VM (build 21.0.4+7, mixed mode, sharing)

$ java -jar bin/launch.jar Check-Java-Version 21

$ java -jar bin/launch.jar Check-Java-Version 11

$ java -jar bin/launch.jar Check-Java-Version 22
Exception in thread "main" java.lang.RuntimeException: At least Java 22 is required, but this Java runtime is version 21.0.4+7
	at com.io7m.montarre.launchstub.MLSMain.doCheckJava(MLSMain.java:102)
	at com.io7m.montarre.launchstub.MLSMain.main(MLSMain.java:70)

6.5.5.5. Get-Module-Path

The Get-Module-Path command constructs a module path given a base directory.

6.5.5.5.2. Example

$ java -jar bin/launch.jar Get-Module-Path /example
/example/lib:/example/lib/x86_64/linux

C:> java -jar bin\launch.jar Get-Module-Path c:\example
c:\example\lib;c:\example\lib\x86_64\windows

6.5.6. Outputs

Given a package name, version number, architecture name, and operating system name, the output of the packager will be ${PACKAGE_NAME}-${PACKAGE_VERSION}-${ARCH_NAME}-${OS_NAME}-any.txz unconditionally.

An example output of the packager is com.io7m.montarre-0.0.1-SNAPSHOT-any.txz.

Footnotes

1 | The tar format is used because it is necessary to preserve the executable permissions on files in the archive when running in POSIX-like systems. The more common zip format does not contain a standard mechanism to preserve this information. References to this footnote: 1

7. Package Format 1.0 Specification

7.1. Overview

7.2. Regular Expressions

7.3. Dotted Strings

7.4. Language

7.5. TranslatedText

7.6. Hash

7.6.1. Overview

7.6.2. Algorithm

7.6.3. Value

7.7. Architecture Name

7.8. Operating System Name

7.9. Platform

7.10. Package

7.11. Metadata

7.11.1. Overview

7.11.2. ApplicationKind

7.11.3. Categories

7.11.4. Copying

7.11.4.1. Overview

7.11.4.2. License

7.11.4.3. Copyright

7.11.5. Description

7.11.6. Flatpak

7.11.6.1. Overview

7.11.6.2. Runtimes

7.11.6.3. Permissions

7.11.7. JavaInfo

7.11.7.1. Overview

7.11.7.2. Required JDK Version

7.11.7.3. Main Module

7.11.7.4. JDK Runtime Image Type

7.11.7.5. Native Access

7.11.7.6. Extra Options

7.11.8. Links

7.11.8.1. Overview

7.11.8.2. Roles

7.11.9. LongDescription

7.11.9.1. Overview

7.11.9.2. Paragraph

7.11.9.3. Feature

7.11.10. Names

7.11.10.1. Overview

7.11.10.2. Package Name

7.11.10.3. Human Name

7.11.10.4. Short Name

7.11.11. Vendor

7.11.11.1. Overview

7.11.11.2. Name

7.11.11.3. ID

7.11.12. Version

7.11.12.1. Overview

7.11.12.2. Number

7.11.12.3. Date

7.12. Manifest

7.12.1. Overview

7.12.2. FileName

7.12.3. Size

7.12.4. Modules

7.12.5. PlatformModules

7.12.6. Resources

7.13. Serialization

7.13.1. Overview

7.13.2. Entomos

7.13.3. XML

7.13.4. XML Schema

7.14. Model Sources

7.1. Overview

This section specifies the format of version 1.0 montarre packages.

This specification is divided into an abstract model and a separate serialization. The purpose of the model is to describe the semantics of montarre packages; the actual meaning of the data within, and to describe properties and invariants that must be true for all valid montarre packages. The serialization section describes the on-disk formats used for distribution.

The formal specification described here is written in the Gallina specification language of the Rocq theorem prover. The language is a total, pure-functional, dependently-typed language allowing for describing systems in rigorous detail including machine-checked proofs of various chosen properties.

The full sources of the entire specification are published at the end of this section.

7.2. Regular Expressions

The specification makes use of regular expressions to specify the required formats of some string types. The regular expression language used should be assumed to be the Java regular expression language.

The specification itself axiomatizes regular expressions using the following definitions:

7.2.3. RegularExpressionT

(** The opaque, abstract type of regular expressions. *)
Parameter RegularExpressionT : string -> Set.

7.2.4. regex

(** For the sake of specification simplicity, we assume that all
    strings are valid regular expressions. *)
Parameter regex : forall (s : string), RegularExpressionT s.

7.2.5. matches

(** A proposition that states that a given regular expression
    matches a given string. *)
Parameter matches : forall (s : string) {e : string},
  RegularExpressionT e -> Prop.

7.2.6. matchesDecidable

(** Whether a string matches a regular expression is decidable. *)
Parameter matchesDecidable : forall
  (s : string)
  {e : string}
  (r : RegularExpressionT e),
    {matches s r}+{~matches s r}.

7.3. Dotted Strings

A Lanark dotted string is a string conforming to the regular expression given in the Lanark specification.

7.3.2. Dotted String

Definition lanarkDottedString :=
  forall (s : string),
    matches s (regex "([a-z][a-z0-9_-]{0,63})(\.[a-z][a-z0-9_-]{0,62}){0,15}").

7.4. Language

A language value is an IETF BCP 47 language tag identifying a language.

7.4.2. Language

Definition LanguageT :=
  string.

Example language values include: "en", "yi-Hebr", "gsw-u-sd-chzh".

7.5. TranslatedText

A translated text value is a record consisting of a piece of text in a specified language, along with a map consisting of translations of that text indexed by language.

7.5.2. Translated Text

Inductive TranslatedTextT := TranslatedText {
  language     : LanguageT;
  text         : string;
  translations : LanguageMaps.t string
}.

7.6. Hash

7.6.1. Overview

A hash is a record consisting of an algorithm and a value.

7.6.1.2. Hash

Inductive HashT := Hash {
  hashAlgorithm : HashAlgorithmT;
  hashValue     : HashValueT
}.

7.6.2. Algorithm

A hash algorithm specifies the name of a cryptographic hash algorithm. The names must be taken from the Java message digest algorithm name specification.

7.6.2.2. Algorithm

Definition HashAlgorithmT :=
  string.

7.6.3. Value

A hash value is an ASCII, lowercase, hexadecimal text serialization of the binary output of a hash algorithm.

7.6.3.2. Value

Inductive HashValueT :=
  HashValue : forall (s : string),
    matches s (regex "[a-f0-9]{2,256}")
      -> HashValueT.

7.7. Architecture Name

An architecture name is a unique name for a particular hardware architecture. It represents an attempt to provide a consistent naming convention for hardware types[3].

An architecture name is a string conforming to the regular expression [a-z][a-z0-9_-]{0,32}.

7.7.3. Architecture Name

Inductive ArchitectureNameT :=
  ArchitectureName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,32}")
      -> ArchitectureNameT.

This specification recognizes the following architecture names:

7.7.5. Architecture Names

Name | Description
aarch_64 | 64-bit ARM
arm_32 | 32-bit ARM
loongarch_64 | 64-bit LoongArch
mips_32 | 32-bit MIPS
mips_64 | 64-bit MIPS
mipsle_32 | 32-bit little-endian MIPS
mipsle_64 | 64-bit little-endian MIPS
ppc_32 | 32-bit PowerPC
ppc_64 | 64-bit PowerPC
ppcle_32 | 32-bit little-endian PowerPC
ppcle_64 | 64-bit little-endian PowerPC
riscv_32 | 32-bit RISC-V
riscv_64 | 64-bit RISC-V
s390_64 | 64-bit IBM z/Architecture
sparc_32 | 32-bit SPARC
sparc_64 | 64-bit SPARC
x86_32 | 32-bit x86
x86_64 | 64-bit x86

The special name unknown is assigned to unrecognized hardware architectures. The unknown name is not permitted to appear in package declarations.

7.8. Operating System Name

An operating system name is a unique name for a particular operating system. It represents an attempt to provide a consistent naming convention for operating systems.

An operating system name is a string conforming to the regular expression [a-z][a-z0-9_-]{0,32}.

7.8.3. Operating System Name

Inductive OperatingSystemNameT :=
  OperatingSystemName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,32}")
      -> OperatingSystemNameT.

This specification recognizes the following operating system names:

7.8.5. Architecture Names

Name | Description
aix | IBM AIX
freebsd | FreeBSD
hpux | HP-UX
linux | Linux
netbsd | NetBSD
openbsd | OpenBSD
os400 | IBM i
osx | MacOS
solaris | Oracle Solaris
windows | Microsoft Windows

The special name unknown is assigned to unrecognized operating systems. The unknown name is not permitted to appear in package declarations.

7.9. Platform

A platform is a record consisting of an architecture name and operating system name.

7.9.2. Platform

Inductive PlatformT := Platform {
  platformArch : ArchitectureNameT;
  platformOS   : OperatingSystemNameT
}.

7.10. Package

A montarre package contains a single package declaration which specifies metadata and a manifest.

7.11. Metadata

7.11.1. Overview

The metadata for the package is a record describing the package itself. It provides important information pertaining to the identity of the package, information pertaining to the runtime environment required to run the package, and information used to produce listings in packaging environments such as Flatpak.

7.11.1.2. Metadata

Inductive MetadataT := Metadata {
  metaApplicationKind  : ApplicationKindT;
  metaCategories       : list CategoryT;
  metaCopying          : CopyingT;
  metaDescription      : DescriptionT;
  metaFlatpak          : FlatpakT;
  metaJavaInfo         : JavaInfoT;
  metaLinks            : list LinkT;
  metaLongDescriptions : LanguageMaps.t LongDescriptionT;
  metaNames            : NamesT;
  metaVendor           : VendorT;
  metaVersion          : VersionT
}.

7.11.2. ApplicationKind

The application kind of a package is one of the following values:

7.11.2.2. ApplicationKind

Value | Description
CONSOLE | The application is a text-only console application.
GRAPHICAL | The application is a graphical application.

7.11.2.3. Application Kind

Inductive ApplicationKindT :=
  | CONSOLE
  | GRAPHICAL
  .

7.11.3. Categories

A category is a string conforming to the regular expression [A-Z][A-Za-z0-9_-]{0,128}. A package has zero or more categories.

7.11.3.2. Category

Inductive CategoryT :=
  Category : forall (s : string),
    matches s (regex "[A-Z][A-Za-z0-9_-]{0,128}")
      -> CategoryT.

Categories should be taken from the Freedesktop.org category registry.

Example category values include: "Building", "Development".

7.11.4. Copying

7.11.4.1. Overview

The copying information for a package is a record consisting of a license and a copyright.

7.11.4.1.2. Copying

Inductive CopyingT := Copying {
  license   : LicenseT;
  copyright : CopyrightT
}.

7.11.4.2. License

A license is an SPDX license identifier denoting the license of the package.

7.11.4.2.2. License

Definition LicenseT :=
  string.

Example license values include: "ISC", "Apache-2.0", "BSD-3-Clause", "GPL-3.0-or-later".

7.11.4.3. Copyright

A copyright is a simple copyright string that indicates the current holder of the copyright on the package.

7.11.4.3.2. Copyright

Definition CopyrightT :=
  string.

An example copyright value is: "Copyright © 2024 Mark Raynsford <code@io7m.com> https://www.io7m.com".

7.11.5. Description

A description is a short translated text that provides a summary of the package.

7.11.5.2. Description

Definition DescriptionT :=
  TranslatedTextT.

7.11.6. Flatpak

7.11.6.1. Overview

The Flatpak information for a package provides extra metadata used to produce Flatpaks.

7.11.6.1.2. Flatpak

Inductive FlatpakT := Flatpak {
  flatpakPermissions : list FlatpakPermissionT;
  flatpakRuntimes    : list FlatpakRuntimeT
}.

7.11.6.2. Runtimes

A Flatpak runtime consists of a name, a version, and a role.

7.11.6.2.2. Flatpak Runtime

Inductive FlatpakRuntimeT := FlatpakRuntime {
  flatpakRuntimeName    : string;
  flatpakRuntimeVersion : string;
  flatpakRuntimeRole    : FlatpakRuntimeRoleT
}.

Roles may be one of the following values:

7.11.6.2.4. Flatpak Roles

Value | Description
SDK | A runtime for building applications.
PLATFORM | A runtime for running applications.

7.11.6.2.5. Flatpak Runtime Role

Inductive FlatpakRuntimeRoleT :=
  | SDK
  | PLATFORM
  .

7.11.6.3. Permissions

A Flatpak permission denotes that the named permission will be granted to the application when it runs as a Flatpak.

7.11.6.3.2. Flatpak Permission

Definition FlatpakPermissionT :=
  string.

Example permission values include: "--share=net", "--socket=x11".

7.11.7. JavaInfo

7.11.7.1. Overview

The java info information for a package is a record consisting of metadata describing the application's required JDK version, main module, JDK runtime image type, and any native access and extra options.

7.11.7.1.2. Java Info

Inductive JavaInfoT := JavaInfo {
  requiredJDKVersion : nat;
  mainModule         : string;
  extraOptions       : list string;
  enableNativeAccess : list string;
  imageType          : JavaImageT
}.

7.11.7.2. Required JDK Version

The required JDK version specifies the lower bound of the major version of the Java runtime required to use this package.

7.11.7.3. Main Module

The main module specifies the fully-qualified name of the application's main class.

An example main module value is: "com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain".

7.11.7.4. JDK Runtime Image Type

The JDK runtime image type specifies the type of runtime image the application needs in order to run.

7.11.7.4.2. JavaImageT

Inductive JavaImageT :=
    JDK
  | JRE.

A value of JDK indicates the application requires the full set of jdk.* modules to be present.

A value of JRE indicates the application can work without the jdk.* modules.

7.11.7.5. Native Access

The enableNativeAccess list specifies a list of modules that are permitted to use the Java FFI.

7.11.7.6. Extra Options

The extraOptions list specifies a list of extra options that will be passed to the Java runtime on application startup.

7.11.8. Links

7.11.8.1. Overview

A link is a target reference to an external website or entity, along with a role describing the relationship between that entity and the package.

The target of a link must be a valid RFC 3986 URI.

7.11.8.1.3. Link

Inductive LinkT := Link {
  linkRole   : LinkRoleT;
  linkTarget : string
}.

7.11.8.2. Roles

A role is one of the following values:

7.11.8.2.2. Role Values

Value | Description
ISSUES | A link to an issue tracker.
HOME_PAGE | A link to a home page.
DONATION | A link to a donation page.
CONTACT | A link to a contact page.
FAQ | A link to an FAQ page.
TRANSLATE | A link to a translation page.
CONTRIBUTE | A link to a contribution page.
SCM | A link to an SCM repository.

7.11.8.2.3. Link Role

Inductive LinkRoleT :=
  | ISSUES
  | HOME_PAGE
  | DONATION
  | CONTACT
  | FAQ
  | TRANSLATE
  | CONTRIBUTE
  | SCM
  .

7.11.9. LongDescription

7.11.9.1. Overview

The long description information for a package is a set of paragraphs and features. A long description has an associated language and there may be at most one long description per language in a given package.

7.11.9.1.2. Long Description

Inductive LongDescriptionT := LongDescription {
  descriptionLanguage : LanguageT;
  descriptions        : list ParagraphT;
  features            : list FeatureT
}.

7.11.9.2. Paragraph

A paragraph is a humanly readable description of some aspect of the package for marketing purposes.

7.11.9.2.2. Paragraph

Definition ParagraphT :=
  string.

7.11.9.3. Feature

A feature is a humanly readable description of one of the features provided by the package for marketing purposes.

7.11.9.3.2. Feature

Definition FeatureT :=
  string.

7.11.10. Names

7.11.10.1. Overview

The names information for a package is a record consisting of a set of different types of names for the package.

7.11.10.1.2. Names

Inductive NamesT := Names {
  namePackage : PackageNameT;
  nameShort   : ShortNameT;
  nameHuman   : HumanNameT
}.

7.11.10.2. Package Name

The package name is a unique identifier for the package, specified as a dotted string.

7.11.10.2.2. Package Name

Definition PackageNameT :=
  lanarkDottedString.

Example package name values include: "com.io7m.montarre", "com.io7m.lanark".

7.11.10.3. Human Name

The human name is a friendly, human-readable name for the package.

7.11.10.3.2. Human Name

Definition HumanNameT :=
  string.

An example human name value is "Montarre".

7.11.10.4. Short Name

The short name is a name conforming to the regular expression [a-z][a-z0-9_-]{0,128} [2].

7.11.10.4.2. Short Name

Inductive ShortNameT :=
  ShortName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,128}")
      -> ShortNameT.

An example short name value is "montarre".

7.11.11. Vendor

7.11.11.1. Overview

The vendor information for a package is a record consisting of a vendor name and a unique vendor ID.

7.11.11.1.2. Vendor

Inductive VendorT := Vendor {
  vendorId   : VendorIDT;
  vendorName : VendorNameT
}.

7.11.11.2. Name

The vendor name is the humanly-readable name of the vendor of the package, conforming to the regular expression [a-zA-Z][A-Za-z0-9_-]{0,128} [1].

7.11.11.2.2. Vendor Name

Inductive VendorNameT :=
  VendorName : forall (s : string),
    matches s (regex "[a-zA-Z][A-Za-z0-9_-]{0,128}")
      -> VendorNameT.

7.11.11.3. ID

The vendor ID is a unique identifier for the vendor of the package, specified as a dotted string.

7.11.11.3.2. Vendor ID

Definition VendorIDT :=
  lanarkDottedString.

Example vendor ID values include: "com.io7m", "com.example".

7.11.12. Version

7.11.12.1. Overview

The version information for a package is a record consisting of a version number and a version/release date.

7.11.12.1.2. Version

Inductive VersionT := Version {
  versionNumber : VersionNumberT;
  versionDate   : VersionDateT
}.

7.11.12.2. Number

The version number is the semantic version of the package.

7.11.12.2.2. Version Number

Inductive VersionNumberT := VersionNumber {
  major     : nat;
  minor     : nat;
  patch     : nat;
  qualifier : option string
}.

7.11.12.3. Date

The version date is an ISO 8601 date string denoting the release date of this version of the package.

7.11.12.3.2. Version Date

Inductive VersionDateT :=
  VersionDate : forall (s : string),
    matches s (regex "[0-9]{4}-[0-9]{2}-[0-9]{2}")
      -> VersionDateT.

Example version date values include: "2024-10-13", "2001-01-23".

7.12. Manifest

7.12.1. Overview

A manifest consists of a set of items.

7.12.1.2. Manifest

Inductive ManifestT := Manifest {
  manifestItems : list ItemT
}.

An item is a Module, PlatformModule, or a Resource.

7.12.1.4. Item

Inductive ItemT :=
  | ItemModule         : ModuleT         -> ItemT
  | ItemPlatformModule : PlatformModuleT -> ItemT
  | ItemResource       : ResourceT       -> ItemT
  .

Items within a manifest must have unique file names. More formally, for a manifest m, there cannot exist two different items i0 and i1 in m such that i0 and i1 have filenames that are the same.

7.12.1.6. Manifest File Names

Definition manifesItemsFilenamesUnique :=
  forall (m : ManifestT),
    forall (i0 : ItemT),
      In i0 (manifestItems m)
        -> ~(exists i1 : ItemT,
               (In i1 (manifestItems m))
            /\ (i0 <> i1)
            /\ (fileNamesSame (itemFileName i0) (itemFileName i1))).

Each item carries a hash value denoting the cryptographic hash of the contents of the item within the package.

7.12.2. FileName

A file name is a unique name assigned to a manifest item. File names are case-insensitive strings that conform to the regular expression ([\p{L}\p{N}_\-.+]+)(/[\p{L}\p{N}_\-.+]+)*

7.12.2.2. FileName

Inductive FileNameT :=
  FileName : forall (s : string),
    matches s (regex "([\p{L}\p{N}_\-.+]+)(/[\p{L}\p{N}_\-.+]+)*")
      -> FileNameT.

Intuitively, a filename can be considered to be a non-empty /-separated list of file name segments that each conform to the regular expression [\p{L}\p{N}_\-.+]+. Accordingly, filenames cannot start with slashes, cannot end with trailing slashes, and cannot contain sequences of repeating slashes.

The specification axiomatizes the concept of converting a string to uppercase. The uppercase transform of a string should be understood to be a string where every character has been converted to its uppercase equivalent in a neutral locale.

7.12.2.5. Uppercase Transform

(** A function that produces an uppercase version of the given string. *)
Parameter uppercaseOf : string -> string.

A proposition that states that two strings have the same uppercase transform:

7.12.2.7. Uppercase Same

Definition uppercaseSame (s t : string) :=
  uppercaseOf s = uppercaseOf t.

Accordingly, as file names are case-insensitive, then two file names are equal if their uppercase transforms are equal:

7.12.2.9. File Names Same

(** A proposition that states that two file names are the same if their
    uppercase transformations are the same. *)
Definition fileNamesSame (s t : FileNameT) :=
  match s, t with
  | FileName fs _, FileName ft _ => uppercaseSame fs ft
  end.

7.12.3. Size

A size is a non-negative integer value denoting the size in octets of an item.

7.12.4. Modules

A module represents a platform-neutral jar file that will be placed onto the Java module path regardless of the underlying hardware architecture and operating system on which the application is running.

7.12.4.2. Module

Inductive ModuleT := Module {
  mFile : FileNameT;
  mHash : HashT;
  mSize : nat
}.

7.12.5. PlatformModules

A platform module represents a platform-specific jar file that will be placed onto the Java module path when the hardware architecture and operating system of the module matches that of the platform upon which the application is running.

7.12.5.2. PlatformModule

Inductive PlatformModuleT := PlatformModule {
  pmFile     : FileNameT;
  pmHash     : HashT;
  pmPlatform : PlatformT;
  pmSize     : nat
}.

7.12.6. Resources

A resource is an arbitrary file associated with the package. Resources are typically used to provide icons, BOMs, and screenshots for the package.

7.12.6.2. Resource

Inductive ResourceT := Resource {
  rFile    : FileNameT;
  rHash    : HashT;
  rRole    : ResourceRoleT;
  rCaption : CaptionT;
  rSize    : nat
}.

A resource has an associated role that describes the purpose of the resource.

7.12.6.4. Resource Role

Inductive ResourceRoleT :=
  | BOM
  | LICENSE
  | ICO_WINDOWS
  | ICON_16
  | ICON_24
  | ICON_32
  | ICON_48
  | ICON_64
  | ICON_128
  | ICON_256
  | ICON_512
  | ICON_SVG
  | SCREENSHOT
  .

A role has one of the following values:

7.12.6.6. Resource Role Values

Value | Description
BOM | A bill-of-materials. Recommended to be in CycloneDX format.
LICENSE | A plain text license file.
ICO_WINDOWS | A Windows application icon (".ico").
ICON_16 | A 16x16 application icon.
ICON_24 | A 24x24 application icon.
ICON_32 | A 32x32 application icon.
ICON_48 | A 48x48 application icon.
ICON_64 | A 64x64 application icon.
ICON_128 | A 128x128 application icon.
ICON_256 | A 256x256 application icon.
ICON_512 | A 512x512 application icon.
ICON_SVG | An arbitrarily scaled SVG icon.
SCREENSHOT | A screenshot.

A resource has an associated caption that provides a human-readable description of the resource. This is used, for example, to describe the contents of screenshots for use in Flatpak listings.

7.12.6.8. Resource Caption

Definition CaptionT :=
  TranslatedTextT.

7.13. Serialization

7.13.1. Overview

montarre package declarations are serialized to an XML format with a strict XSD schema. The serialized package declaration, and all the package contents, are collected into binary file format based on the Entomos file format specification. Restrictions are applied to the XML data to assist with ensuring that montarre packages are reproducible.

7.13.2. Entomos

montarre packages are entomos files with the file extension .mpk.

All entomos files have the following structure:

7.13.2.3. Entomos Structure

Files start with a 64-bit format-specific tag for easy identification.

The file tag is followed by a 32-bit major and minor version.

The rest of the file is divided into a flat array of sections.

Each section is aligned to a 16-byte boundary.

Each section starts with a 64-bit format-specific tag.

The section tag is followed by a 64-bit size value, specifying the length of the data within the section.

The section then contains size bytes of data, followed by up to 15 bytes of padding in order to ensure that any data that follows is aligned to a 16-byte boundary.

The file ends with an end section. This is a normal section where the section has a format-specific end tag, and a size of 0.

Readers are required to stop reading at the end section. Trailing data is ignored.

Readers are required to fail if there is no end section, and treat the file as corrupted and truncated.

All values are in big-endian order. The data within sections can be in any byte order as required by specific formats.

The file format is versioned according to the following rules:

7.13.2.5. Versioning

The specification is versioned via a restricted subset of the Semantic Versioning specification. The specification has a major and minor version number, with major version increments denoting incompatible changes, and minor version increments denoting new functionality. There is no patch version number. A version of the specification with major version m and minor version n is denoted as specification version (m, n).

Assuming a version of the specification m, an update to the specification that yields version n such that n > m is considered to be forwards compatible if a parser that supports format version m can read files that were written using format version n.

Assuming a version of the specification m, an update to the specification that yields version n such that n > m is considered to be backwards compatible if a parser that supports format version n can read files that were written using format version m.

The specification is designed such that a correctly-written parser implementation that supports a major version m is able to support the set of versions ∀n. (m, n). This implies full forwards and backwards compatibility for parsers when the major version is unchanged.

Changes that would cause a parser supporting an older version of the specification to fail to read a file written according to a newer version of the specification MUST imply an increment in the major version of the specification.

Changes that would cause a parser supporting a newer version of the specification to fail to read a file written according to an older version of the specification MUST imply an increment in the major version of the specification.

Every montarre package file starts with the given fixed-size header:

7.13.2.7. File Header

Definition binaryExpFileHeader : binaryExp :=
  BiRecord [
    ("id",           u64 0x894D54500D0A1A0A);
    ("versionMajor", u32 1);
    ("versionMinor", u32 0)
  ].

This version of the specification defines major version 1, minor version 0.

The package declaration is serialized to XML and stored in the manifest section of the file. There must be exactly one manifest section, and it must be the first section in the file.

7.13.2.10. Manifest Section

Definition binaryManifestSection (m : ManifestT) : binaryExp :=
  let text := utf8 (xmlSerializationOf m) in
    BiRecord [
      ("id",   u64 0x4D54505F4D414E49);
      ("size", u64 (binarySize text));
      ("text", text)
    ].

Each file listed in the manifest is stored in its own file section. A file section starts with the name of the file and is followed directly by the file data.

7.13.2.12. File Section

Definition binaryFileSection (i : ItemT) : binaryExp :=
  let nameText  := utf8 (uppercaseOf (fileNameString (itemFileName i))) in
  let nameSize  := binarySize nameText in
  let fileSize  := itemSize i in
  let totalSize := 4 + nameSize + fileSize in
    BiRecord [
      ("id",         u64 0x4D54505F46494C45);
      ("size",       u64 totalSize);
      ("nameLength", u32 nameSize);
      ("name",       nameText);
      ("data",       BiReserve fileSize)
    ].

File sections are subject to the following restrictions and observations:

7.13.2.14. File Section Restrictions / Observations

File sections must be serialized such that the names in each section appear in ascending alphabetical order. We specify a serialization order to ensure that implementations produce reproducible files.

For every file section, there must be a corresponding item declared in the manifest. It is not permitted to place "extra" file sections in the file.

For every item declared in the manifest, there must be a corresponding file section. It is not permitted to omit file sections.

The size of the data in a file section is equal to the declared size of the corresponding item in the manifest, minus the length of the UTF-8 encoded file name, and four octets to store the length of the name, and any padding required to align the following section.

Every montarre package file ends with an end section.

7.13.2.16. End Section

Definition binaryEndSection : binaryExp :=
  BiRecord [
    ("id",   u64 0x4D54505F454E4421);
    ("size", u64 0)
  ].

7.13.3. XML

Package declarations must be serialized according to the included schema with the following restrictions:

7.13.3.2. XML Restrictions

XML must be serialized indented to four spaces.

The character content of elements must be serialized using a function equivalent to XSLT's normalize-space() function.

After indenting, XML must be canonicalized using the Exclusive XML Canonicalization Version 1.0 algorithm.

7.13.4. XML Schema

The package declaration schema is as follows:

7.13.4.2. XML Schema

<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="urn:com.io7m.montarre.package:1"
            xmlns:mp="urn:com.io7m.montarre.package:1">

  <xsd:simpleType name="ApplicationKindType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        The type of application. Many packaging systems and some operating systems distinguish between "console" and
        "graphical" applications.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="CONSOLE"/>
      <xsd:enumeration value="GRAPHICAL"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="VersionType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        An arbitrary version number.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string"/>
  </xsd:simpleType>

  <xsd:simpleType name="CategoryNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A category name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[A-Z][A-Za-z0-9_-]{0,128}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="VendorIDType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A vendor ID; A Lanark dotted name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="([a-z][a-z0-9_-]{0,63})(\.[a-z][a-z0-9_-]{0,62}){0,15}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="PackageNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A package name; A Lanark dotted name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="([a-z][a-z0-9_-]{0,63})(\.[a-z][a-z0-9_-]{0,62}){0,15}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="ShortNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A short package name. Used for systems such as Debian packages.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[a-z][a-z0-9_-]{0,128}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="HashAlgorithmNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A hash algorithm name. See " Java Security Standard Algorithm Names".
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[A-Z][A-Z0-9_-]{0,128}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="HashValueType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A hex-encoded hash value.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[a-f0-9]{2,256}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="OSNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        An operating system name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[a-z][a-z0-9_-]{0,32}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="ArchitectureNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A hardware architecture name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[a-z][a-z0-9_-]{0,32}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="VendorNameType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A vendor name. Must be a filesystem-safe name as these names can be used as directories in Windows installers.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="[a-zA-Z][A-Za-z0-9_-]{0,128}"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="FlatpakPermissionType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A flatpak permission.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="--[a-z\-]+(=[a-zA-Z0-9\\._\-/:~]+)?"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:element name="Version">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        Version information.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Number"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The version number. Typically in semantic version form ("2.0.0", "1.0.0-SNAPSHOT", etc).
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Date"
                     type="xsd:date"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The date the version was set.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Vendor">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A vendor.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="ID"
                     type="mp:VendorIDType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The unique vendor ID.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Name"
                     type="mp:VendorNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The vendor name.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Category">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A category applied to an application.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Name"
                     type="mp:CategoryNameType"
                     use="required"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:simpleType name="LinkRole">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        The role of a link.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="ISSUES"/>
      <xsd:enumeration value="HOME_PAGE"/>
      <xsd:enumeration value="DONATION"/>
      <xsd:enumeration value="CONTACT"/>
      <xsd:enumeration value="FAQ"/>
      <xsd:enumeration value="TRANSLATE"/>
      <xsd:enumeration value="CONTRIBUTE"/>
      <xsd:enumeration value="SCM"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:element name="Link">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A link.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Role"
                     type="mp:LinkRole"
                     use="required"/>
      <xsd:attribute name="Target"
                     type="xsd:anyURI"
                     use="required"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Copying">
    <xsd:complexType>
      <xsd:attribute name="License"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            An SPDX license identifier such as "ISC".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Copyright"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            A copyright string such as "Copyright © 2024 Mark Raynsford &lt;code@io7m.com> https://www.io7m.com".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:simpleType name="RuntimeImageKindType">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        The type of JDK required by the application. Some applications may require a full JDK image with jdk.* modules,
        whereas other applications can work with a reduced JRE image.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="JDK"/>
      <xsd:enumeration value="JRE"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:element name="ExtraOption">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        An extra option passed to the Java runtime.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Value"
                     type="xsd:string"
                     use="required"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="EnableNativeAccess">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A Java module name.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Module"
                     type="xsd:string"
                     use="required"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="JavaInfo">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        Information relative to the Java runtime.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:choice>
          <xsd:element ref="mp:EnableNativeAccess"/>
          <xsd:element ref="mp:ExtraOption"/>
        </xsd:choice>
      </xsd:sequence>

      <xsd:attribute name="RequiredJDKVersion"
                     type="xsd:unsignedLong"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The required JDK version.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="RuntimeImageKind"
                     type="mp:RuntimeImageKindType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The required JDK runtime kind.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="MainModule"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The main application module. This should be in a fully-qualified module form such as
            "com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Names">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        Package name information.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:attribute name="Name"
                     type="mp:PackageNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The package name.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="ShortName"
                     type="mp:ShortNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The package short name. The short name is used when exporting to some native package systems such as Debian
            packages.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HumanName"
                     type="xsd:string"
                     use="optional">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The optional human-readable application name. This will default to the package name if not specified.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:simpleType name="FlatpakRuntimeRole">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="PLATFORM"/>
      <xsd:enumeration value="SDK"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:element name="FlatpakPermission">
    <xsd:complexType>
      <xsd:attribute name="Value"
                     use="required"
                     type="mp:FlatpakPermissionType">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            A flatpak permission such as "--share=network", "--share=ipc", etc.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="FlatpakRuntime">
    <xsd:complexType>
      <xsd:attribute name="Name"
                     use="required"
                     type="xsd:string">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            A flatpak runtime such as "org.freedesktop.Platform".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Version"
                     use="required"
                     type="xsd:string">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            A flatpak runtime version such as "24.08".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Role"
                     use="required"
                     type="mp:FlatpakRuntimeRole">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            A runtime role such as "PLATFORM" or "SDK".
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Flatpak">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        Metadata specific to Flatpak packages.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence minOccurs="0"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:FlatpakPermission"/>
        </xsd:sequence>
        <xsd:sequence minOccurs="0"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:FlatpakRuntime"/>
        </xsd:sequence>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Text">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A text element in a specific language.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType mixed="true">
      <xsd:attribute name="Language"
                     use="required"
                     type="xsd:NMTOKEN"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Description">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A humanly-readable package description.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:sequence minOccurs="0"
                    maxOccurs="1">
        <xsd:element ref="mp:Text"/>
      </xsd:sequence>
    </xsd:complexType>

    <xsd:unique name="DescriptionTextLanguageUnique">
      <xsd:selector xpath="mp:Text"/>
      <xsd:field xpath="@Language"/>
    </xsd:unique>
  </xsd:element>

  <xsd:element name="Feature">
    <xsd:complexType mixed="true"/>
  </xsd:element>

  <xsd:element name="Paragraph">
    <xsd:complexType mixed="true"/>
  </xsd:element>

  <xsd:element name="LongDescription">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence minOccurs="1"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:Paragraph"/>
        </xsd:sequence>
        <xsd:sequence minOccurs="0"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:Feature"/>
        </xsd:sequence>
      </xsd:sequence>

      <xsd:attribute name="Language"
                     use="required"
                     type="xsd:NMTOKEN"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Caption">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A humanly-readable resource caption.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:sequence minOccurs="1"
                    maxOccurs="unbounded">
        <xsd:element ref="mp:Text"/>
      </xsd:sequence>
    </xsd:complexType>

    <xsd:unique name="CaptionTextLanguageUnique">
      <xsd:selector xpath="mp:Text"/>
      <xsd:field xpath="@Language"/>
    </xsd:unique>
  </xsd:element>

  <xsd:element name="Metadata">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence minOccurs="0"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:Category"/>
        </xsd:sequence>
        <xsd:element ref="mp:Copying"/>
        <xsd:element ref="mp:Description"/>
        <xsd:sequence>
          <xsd:element ref="mp:Flatpak"
                       minOccurs="0"
                       maxOccurs="1"/>
        </xsd:sequence>
        <xsd:element ref="mp:JavaInfo"/>
        <xsd:sequence minOccurs="0"
                      maxOccurs="unbounded">
          <xsd:element ref="mp:Link"/>
        </xsd:sequence>
        <xsd:sequence minOccurs="0"
                      maxOccurs="1">
          <xsd:element ref="mp:LongDescription"/>
        </xsd:sequence>
        <xsd:element ref="mp:Names"/>
        <xsd:element ref="mp:Vendor"/>
        <xsd:element ref="mp:Version"/>
      </xsd:sequence>

      <xsd:attribute name="ApplicationKind"
                     type="mp:ApplicationKindType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The kind of the application.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="PlatformDependentModule">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A module that is only used when running on a specific platform.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:attribute name="File"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file name within the package.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Size"
                     type="xsd:unsignedLong"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The size of the file in octets.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashAlgorithm"
                     type="mp:HashAlgorithmNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash algorithm name.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashValue"
                     type="mp:HashValueType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash value.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="OperatingSystem"
                     type="mp:OSNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The operating system on which this module is used.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Architecture"
                     type="mp:ArchitectureNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The hardware architecture on which this module is used.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Module">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A module that is used on all platforms.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:attribute name="File"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file name within the package.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Size"
                     type="xsd:unsignedLong"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The size of the file in octets.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashAlgorithm"
                     type="mp:HashAlgorithmNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash algorithm name.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashValue"
                     type="mp:HashValueType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash value.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:simpleType name="ResourceRole">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="BOM"/>
      <xsd:enumeration value="ICON_128"/>
      <xsd:enumeration value="ICON_16"/>
      <xsd:enumeration value="ICON_24"/>
      <xsd:enumeration value="ICON_256"/>
      <xsd:enumeration value="ICON_32"/>
      <xsd:enumeration value="ICON_48"/>
      <xsd:enumeration value="ICON_64"/>
      <xsd:enumeration value="ICO_WINDOWS"/>
      <xsd:enumeration value="LICENSE"/>
      <xsd:enumeration value="SCREENSHOT"/>
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:element name="Resource">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        A metadata resource.
      </xsd:documentation>
    </xsd:annotation>

    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="mp:Caption"
                     minOccurs="0"
                     maxOccurs="1"/>
      </xsd:sequence>

      <xsd:attribute name="File"
                     type="xsd:string"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file name within the package.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Size"
                     type="xsd:unsignedLong"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The size of the file in octets.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashAlgorithm"
                     type="mp:HashAlgorithmNameType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash algorithm name.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="HashValue"
                     type="mp:HashValueType"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The file hash value.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
      <xsd:attribute name="Role"
                     type="mp:ResourceRole"
                     use="required">
        <xsd:annotation>
          <xsd:documentation xml:lang="en">
            The role of the resource.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>

  <xsd:group name="ManifestItemGroup">
    <xsd:choice>
      <xsd:element ref="mp:Module"/>
      <xsd:element ref="mp:PlatformDependentModule"/>
      <xsd:element ref="mp:Resource"/>
    </xsd:choice>
  </xsd:group>

  <xsd:element name="Manifest">
    <xsd:complexType>
      <xsd:sequence minOccurs="0"
                    maxOccurs="unbounded">
        <xsd:group ref="mp:ManifestItemGroup"/>
      </xsd:sequence>
    </xsd:complexType>

    <xsd:key name="ManifestItemUnique">
      <xsd:selector xpath="mp:Module|mp:PlatformDependentModule|mp:BOM"/>
      <xsd:field xpath="@File"/>
    </xsd:key>
  </xsd:element>

  <xsd:element name="Package">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="mp:Metadata"/>
        <xsd:element ref="mp:Manifest"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

</xsd:schema>

7.14. Model Sources

The full sources of the specification model are provided here.

7.14.2. Montarre/Package.v

(*
 * Copyright © 2026 Mark Raynsford <code@io7m.com> https://www.io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *)

From Stdlib Require Import Strings.String.
From Stdlib Require Import Strings.Ascii.
From Stdlib Require Import FSets.FMapInterface.
From Stdlib Require Import FSets.FMapWeakList.
From Stdlib Require Import FSets.FMapFacts.
From Stdlib Require Import Structures.Equalities.

Require Import com.io7m.entomos.Binary.

Import ListNotations.
Local Open Scope string_scope.

(** A mini decidable type module to instantiate maps. *)
Module StringMiniDec : MiniDecidableType
  with Definition t := string.

  Definition t        := string.
  Definition eq       := @Logic.eq t.
  Definition eq_refl  := @Logic.eq_refl t.
  Definition eq_sym   := @Logic.eq_sym t.
  Definition eq_trans := @Logic.eq_trans t.

  Theorem eq_dec : forall x y : t, {eq x y} + {~ eq x y}.
  Proof. apply string_dec. Qed.
End StringMiniDec.

(** A usual decidable type module to instantiate maps. *)
Module StringDec <: UsualDecidableType
  with Definition t := string
  with Definition eq := @Logic.eq string
:= Make_UDT StringMiniDec.

(** A Maps module with string keys. *)
Module StringMaps : FMapInterface.WS
  with Definition E.t  := string
  with Definition E.eq := @Logic.eq string
:= FMapWeakList.Make StringDec.

(** The opaque, abstract type of regular expressions. *)
Parameter RegularExpressionT : string -> Set.

(** For the sake of specification simplicity, we assume that all
    strings are valid regular expressions. *)
Parameter regex : forall (s : string), RegularExpressionT s.

(** A proposition that states that a given regular expression
    matches a given string. *)
Parameter matches : forall (s : string) {e : string},
  RegularExpressionT e -> Prop.

(** Whether a string matches a regular expression is decidable. *)
Parameter matchesDecidable : forall
  (s : string)
  {e : string}
  (r : RegularExpressionT e),
    {matches s r}+{~matches s r}.

Definition lanarkDottedString :=
  forall (s : string),
    matches s (regex "([a-z][a-z0-9_-]{0,63})(\.[a-z][a-z0-9_-]{0,62}){0,15}").

Inductive ApplicationKindT :=
  | CONSOLE
  | GRAPHICAL
  .

Inductive CategoryT :=
  Category : forall (s : string),
    matches s (regex "[A-Z][A-Za-z0-9_-]{0,128}")
      -> CategoryT.

Definition LicenseT :=
  string.

Definition CopyrightT :=
  string.

Inductive CopyingT := Copying {
  license   : LicenseT;
  copyright : CopyrightT
}.

Definition LanguageT :=
  string.

(** A Maps module with language keys. *)
Module LanguageMaps : FMapInterface.WS
  with Definition E.t  := LanguageT
  with Definition E.eq := @Logic.eq LanguageT
:= FMapWeakList.Make StringDec.

Inductive TranslatedTextT := TranslatedText {
  language     : LanguageT;
  text         : string;
  translations : LanguageMaps.t string
}.

Definition DescriptionT :=
  TranslatedTextT.

Inductive JavaImageT :=
    JDK
  | JRE.

Inductive JavaInfoT := JavaInfo {
  requiredJDKVersion : nat;
  mainModule         : string;
  extraOptions       : list string;
  enableNativeAccess : list string;
  imageType          : JavaImageT
}.

Inductive LinkRoleT :=
  | ISSUES
  | HOME_PAGE
  | DONATION
  | CONTACT
  | FAQ
  | TRANSLATE
  | CONTRIBUTE
  | SCM
  .

Inductive LinkT := Link {
  linkRole   : LinkRoleT;
  linkTarget : string
}.

Inductive VendorNameT :=
  VendorName : forall (s : string),
    matches s (regex "[a-zA-Z][A-Za-z0-9_-]{0,128}")
      -> VendorNameT.

Definition VendorIDT :=
  lanarkDottedString.

Inductive VendorT := Vendor {
  vendorId   : VendorIDT;
  vendorName : VendorNameT
}.

Inductive VersionNumberT := VersionNumber {
  major     : nat;
  minor     : nat;
  patch     : nat;
  qualifier : option string
}.

Inductive VersionDateT :=
  VersionDate : forall (s : string),
    matches s (regex "[0-9]{4}-[0-9]{2}-[0-9]{2}")
      -> VersionDateT.

Inductive VersionT := Version {
  versionNumber : VersionNumberT;
  versionDate   : VersionDateT
}.

Definition ParagraphT :=
  string.

Definition FeatureT :=
  string.

Inductive LongDescriptionT := LongDescription {
  descriptionLanguage : LanguageT;
  descriptions        : list ParagraphT;
  features            : list FeatureT
}.

Inductive FlatpakRuntimeRoleT :=
  | SDK
  | PLATFORM
  .

Definition FlatpakPermissionT :=
  string.

Inductive FlatpakRuntimeT := FlatpakRuntime {
  flatpakRuntimeName    : string;
  flatpakRuntimeVersion : string;
  flatpakRuntimeRole    : FlatpakRuntimeRoleT
}.

Inductive FlatpakT := Flatpak {
  flatpakPermissions : list FlatpakPermissionT;
  flatpakRuntimes    : list FlatpakRuntimeT
}.

Definition PackageNameT :=
  lanarkDottedString.

Inductive ShortNameT :=
  ShortName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,128}")
      -> ShortNameT.

Definition HumanNameT :=
  string.

Inductive NamesT := Names {
  namePackage : PackageNameT;
  nameShort   : ShortNameT;
  nameHuman   : HumanNameT
}.

Inductive MetadataT := Metadata {
  metaApplicationKind  : ApplicationKindT;
  metaCategories       : list CategoryT;
  metaCopying          : CopyingT;
  metaDescription      : DescriptionT;
  metaFlatpak          : FlatpakT;
  metaJavaInfo         : JavaInfoT;
  metaLinks            : list LinkT;
  metaLongDescriptions : LanguageMaps.t LongDescriptionT;
  metaNames            : NamesT;
  metaVendor           : VendorT;
  metaVersion          : VersionT
}.

Definition HashAlgorithmT :=
  string.

Inductive HashValueT :=
  HashValue : forall (s : string),
    matches s (regex "[a-f0-9]{2,256}")
      -> HashValueT.

Inductive HashT := Hash {
  hashAlgorithm : HashAlgorithmT;
  hashValue     : HashValueT
}.

Inductive ArchitectureNameT :=
  ArchitectureName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,32}")
      -> ArchitectureNameT.

Inductive OperatingSystemNameT :=
  OperatingSystemName : forall (s : string),
    matches s (regex "[a-z][a-z0-9_-]{0,32}")
      -> OperatingSystemNameT.

Inductive PlatformT := Platform {
  platformArch : ArchitectureNameT;
  platformOS   : OperatingSystemNameT
}.

(** A function that produces an uppercase version of the given string. *)
Parameter uppercaseOf : string -> string.

Definition uppercaseSame (s t : string) :=
  uppercaseOf s = uppercaseOf t.

Inductive FileNameT :=
  FileName : forall (s : string),
    matches s (regex "([\p{L}\p{N}_\-.+]+)(/[\p{L}\p{N}_\-.+]+)*")
      -> FileNameT.

Definition fileNameString (i : FileNameT) : string :=
  match i with
  | FileName s _ => s
  end.

(** A proposition that states that two file names are the same if their
    uppercase transformations are the same. *)
Definition fileNamesSame (s t : FileNameT) :=
  match s, t with
  | FileName fs _, FileName ft _ => uppercaseSame fs ft
  end.

Inductive ResourceRoleT :=
  | BOM
  | LICENSE
  | ICO_WINDOWS
  | ICON_16
  | ICON_24
  | ICON_32
  | ICON_48
  | ICON_64
  | ICON_128
  | ICON_256
  | ICON_512
  | ICON_SVG
  | SCREENSHOT
  .

Definition CaptionT :=
  TranslatedTextT.

Inductive ModuleT := Module {
  mFile : FileNameT;
  mHash : HashT;
  mSize : nat
}.

Inductive PlatformModuleT := PlatformModule {
  pmFile     : FileNameT;
  pmHash     : HashT;
  pmPlatform : PlatformT;
  pmSize     : nat
}.

Inductive ResourceT := Resource {
  rFile    : FileNameT;
  rHash    : HashT;
  rRole    : ResourceRoleT;
  rCaption : CaptionT;
  rSize    : nat
}.

Inductive ItemT :=
  | ItemModule         : ModuleT         -> ItemT
  | ItemPlatformModule : PlatformModuleT -> ItemT
  | ItemResource       : ResourceT       -> ItemT
  .

Definition itemFileName (i : ItemT) : FileNameT :=
  match i with
  | ItemModule         x => mFile x
  | ItemPlatformModule x => pmFile x
  | ItemResource       x => rFile x
  end.

Definition itemHash (i : ItemT) : HashT :=
  match i with
  | ItemModule         x => mHash x
  | ItemPlatformModule x => pmHash x
  | ItemResource       x => rHash x
  end.

Definition itemSize (i : ItemT) : nat :=
  match i with
  | ItemModule         x => mSize x
  | ItemPlatformModule x => pmSize x
  | ItemResource       x => rSize x
  end.

Inductive ManifestT := Manifest {
  manifestItems : list ItemT
}.

Definition manifesItemsFilenamesUnique :=
  forall (m : ManifestT),
    forall (i0 : ItemT),
      In i0 (manifestItems m)
        -> ~(exists i1 : ItemT,
               (In i1 (manifestItems m))
            /\ (i0 <> i1)
            /\ (fileNamesSame (itemFileName i0) (itemFileName i1))).

(** A function that produces an XML serialization of the given manifest. *)
Parameter xmlSerializationOf : ManifestT -> string.

(** The file header. *)
Definition binaryExpFileHeader : binaryExp :=
  BiRecord [
    ("id",           u64 0x894D54500D0A1A0A);
    ("versionMajor", u32 1);
    ("versionMinor", u32 0)
  ].

(** The MTP_END! section. *)
Definition binaryEndSection : binaryExp :=
  BiRecord [
    ("id",   u64 0x4D54505F454E4421);
    ("size", u64 0)
  ].

(** The MTP_MANI section. *)
Definition binaryManifestSection (m : ManifestT) : binaryExp :=
  let text := utf8 (xmlSerializationOf m) in
    BiRecord [
      ("id",   u64 0x4D54505F4D414E49);
      ("size", u64 (binarySize text));
      ("text", text)
    ].

(** The MTP_FILE section. *)
Definition binaryFileSection (i : ItemT) : binaryExp :=
  let nameText  := utf8 (uppercaseOf (fileNameString (itemFileName i))) in
  let nameSize  := binarySize nameText in
  let fileSize  := itemSize i in
  let totalSize := 4 + nameSize + fileSize in
    BiRecord [
      ("id",         u64 0x4D54505F46494C45);
      ("size",       u64 totalSize);
      ("nameLength", u32 nameSize);
      ("name",       nameText);
      ("data",       BiReserve fileSize)
    ].

Footnotes

1 | Vendor names are used in some native packaging systems as installation directories and are therefore required to be filesystem-safe. References to this footnote: 1
2 | Short names are used in some native packaging systems as executable names and are therefore required to be filesystem-safe. References to this footnote: 1
3 | Many hardware architectures have different names referring to the same thing. For example, 64-bit x86 hardware is often referred to as amd64, x64, x86_64, etc. References to this footnote: 1