io7m | single-page | multi-page | epub | Montarre User Manual 0.0.5

Montarre User Manual

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
The montarre package provides tools for producing platform-specific native executables and installation media from a single platform-independent source package.
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].
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:
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.
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!
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
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-0.0.5-main.jar" whenever the documentation mentions the montarre command.
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/0.0.5/com.io7m.montarre.cmdline-0.0.5-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/0.0.5/com.io7m.montarre.cmdline-0.0.5-main.jar
Verify the signature:

2.2.7. Shaded Jar Signature Verification

$ gpg --verify com.io7m.montarre.cmdline-0.0.5-main.jar.asc
Run the jar using an appropriate Java runtime:

2.2.9. Shaded Jar Execution

$ java -jar com.io7m.montarre.cmdline-0.0.5-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/
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.
In a similar manner to how a jar file is simply a zip file containing the Java bytecode of an application along with some metadata, a montarre package is simply a zip 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.
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 the zip file entry named META-INF/MONTARRE/PACKAGE.XML, which is also expected to be the first entry in the file. As a concrete example, this is the package declaration taken from the montarre package itself:

3.3.4. Montarre Package Declaration

$ unzip -p com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk META-INF/MONTARRE/PACKAGE.XML

<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"></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-01-01" Number="0.0.1-SNAPSHOT"></Version>
    </Metadata>
    <Manifest>
        <Module File="lib/com.io7m.anethum.api-1.1.1.jar" HashAlgorithm="SHA-256" HashValue="bef5e82eeac406d93b993858e575ba304366ad333d54134969951d1223ff2ce8"></Module>
        <Module File="lib/com.io7m.blackthorne.core-2.0.2.jar" HashAlgorithm="SHA-256" HashValue="48b994b273dddd8a2a410c43db3efcd0d91a71910fc27189a24736313fb2bb23"></Module>
        <Module File="lib/com.io7m.blackthorne.jxe-2.0.2.jar" HashAlgorithm="SHA-256" HashValue="bfcf0e162aa3b636f29f933de5d80f01a1ee1ebb32780f1ff8ca96d56a75ecdf"></Module>
        <Module File="lib/com.io7m.jaffirm.core-4.0.1.jar" HashAlgorithm="SHA-256" HashValue="dc02592647284de9b985a3852e3ad967e9ee561d44772d3e4ecd99afbbc22f18"></Module>
        <Module File="lib/com.io7m.jcip-2.0.1.jar" HashAlgorithm="SHA-256" HashValue="f103daf09059c6969efb7e87dbd427da9dd2b9088224f3aca36e76865edd8ba2"></Module>
        <Module File="lib/com.io7m.jdownload.core-1.0.0.jar" HashAlgorithm="SHA-256" HashValue="807ec26e9b987dd7e5e475f64494501582af0a89375ec106a8307102a269095d"></Module>
        <Module File="lib/com.io7m.jlexing.core-3.2.0.jar" HashAlgorithm="SHA-256" HashValue="e26c6046de6cf41819fe2ed15e38279ce3447cf45430166b0f25a3f589d55c93"></Module>
        <Module File="lib/com.io7m.jmulticlose.core-1.1.3.jar" HashAlgorithm="SHA-256" HashValue="c0e5164f515e530dc210772d98120bbf8f60c9933b9e178e3ad4dbbf4ef43b92"></Module>
        <Module File="lib/com.io7m.junreachable.core-4.0.2.jar" HashAlgorithm="SHA-256" HashValue="979cb909924e8ea64e17b03340c601a8e6b6e1620c4e751a0bd74a34ffb9d5e9"></Module>
        <Module File="lib/com.io7m.jxe.core-2.0.0.jar" HashAlgorithm="SHA-256" HashValue="3520d03a2606787c4e88625f151c9dbbc853bd4987e752c509e6030a83238b67"></Module>
        <Module File="lib/com.io7m.jxtrand.api-2.1.0.jar" HashAlgorithm="SHA-256" HashValue="53c1a2cc739b6359441ba7aacc2aee74166ea416060b197ef6530e8a60052b27"></Module>
        <Module File="lib/com.io7m.jxtrand.vanilla-2.1.0.jar" HashAlgorithm="SHA-256" HashValue="c1bbcea8b4ec0a99093e1ec745036e7849f98687158ad3b777179618052ce9b2"></Module>
        <Module File="lib/com.io7m.lanark.core-1.2.0.jar" HashAlgorithm="SHA-256" HashValue="c725d2de4b82b9632cc2d72219b27f5d4c4700dde3dd2905f965f06894f04503"></Module>
        <Module File="lib/com.io7m.montarre.api-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="57cd2bf03e9b80f1ee78011d4a1ee45a5a6051ef8652917b89c5e368ea1d538f"></Module>
        <Module File="lib/com.io7m.montarre.cmdline-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="6e8b6e26827c9d46a678742aa5981cb9060d0ea68a295466a173481a7b0cf441"></Module>
        <Module File="lib/com.io7m.montarre.io-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="61bf500d463fac19cbe595bb6e3612936ba2f68aedf1ec9107ebd7addf37eeda"></Module>
        <Module File="lib/com.io7m.montarre.nativepack-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="f2d9ffcd1080036d47f2759a6bc174818d7fd73bbe4188141889d895f630deb1"></Module>
        <Module File="lib/com.io7m.montarre.schema-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="1027ae156398734ee4124839189361255b58b98bdd7dab2036dbfde231eaf3af"></Module>
        <Module File="lib/com.io7m.montarre.xml-0.0.1-SNAPSHOT.jar" HashAlgorithm="SHA-256" HashValue="9c614cda97071bef22da7fdcaeb446ccf6f4f5e29f654eab874b99725d01c124"></Module>
        <Module File="lib/com.io7m.quarrel.core-1.6.1.jar" HashAlgorithm="SHA-256" HashValue="20047834fc6d68a57ea251bccc52822de8bac068c4a13dcb6ae99111e542be90"></Module>
        <Module File="lib/com.io7m.quarrel.ext.logback-1.6.1.jar" HashAlgorithm="SHA-256" HashValue="48827e4267a6e85c5900649381bf73ddfb0ccee9e4e181834d3c17bd12e4fb48"></Module>
        <Module File="lib/com.io7m.seltzer.api-1.1.0.jar" HashAlgorithm="SHA-256" HashValue="1097d2d28fcf12e6a9699fc9b527712f954ebe8d25467ccfa8201e445eeadf96"></Module>
        <Module File="lib/com.io7m.streamtime.core-1.0.0.jar" HashAlgorithm="SHA-256" HashValue="d062c6142754e507c51a3e127b449ae2d95cf30afb65b4cfd6fffa7f7717a0c8"></Module>
        <Module File="lib/com.io7m.verona.core-1.0.1.jar" HashAlgorithm="SHA-256" HashValue="b6c2fb9858a9736c32e05513f0c0801ebcf38d7226d5c70f62dd7ba4dbd311e2"></Module>
        <Module File="lib/commons-codec-1.17.1.jar" HashAlgorithm="SHA-256" HashValue="f9f6cb103f2ddc3c99a9d80ada2ae7bf0685111fd6bffccb72033d1da4e6ff23"></Module>
        <Module File="lib/commons-compress-1.27.1.jar" HashAlgorithm="SHA-256" HashValue="293d80f54b536b74095dcd7ea3cf0a29bbfc3402519281332495f4420d370d16"></Module>
        <Module File="lib/commons-io-2.17.0.jar" HashAlgorithm="SHA-256" HashValue="4aa4ca48f3dfd30b78220b7881d8cb93eac4093ec94361b6befa9487998a550b"></Module>
        <Module File="lib/commons-lang3-3.17.0.jar" HashAlgorithm="SHA-256" HashValue="6ee731df5c8e5a2976a1ca023b6bb320ea8d3539fbe64c8a1d5cb765127c33b4"></Module>
        <Module File="lib/logback-classic-1.5.8.jar" HashAlgorithm="SHA-256" HashValue="89b0f7bec5fa8a9c9246acd1e99f0e84d6cb3bbadaa5b095a14c2cd0f4732d05"></Module>
        <Module File="lib/logback-core-1.5.8.jar" HashAlgorithm="SHA-256" HashValue="a698e4cff3eac45eec9b2755df93bb7a9725d853f7938030654ce5430b37c41d"></Module>
        <Module File="lib/slf4j-api-2.0.16.jar" HashAlgorithm="SHA-256" HashValue="a12578dde1ba00bd9b816d388a0b879928d00bab3c83c240f7013bf4196c579a"></Module>
        <Resource File="meta/bom.xml" HashAlgorithm="SHA-256" HashValue="822512da044a72e5e851f73347027c802e90f21468235266b32fca6cd7193bcc" Role="BOM"></Resource>
        <Resource File="meta/icon.ico" HashAlgorithm="SHA-256" HashValue="a36ce859182d76a764bfdb2260b05e0c00580a191e7bc36155a00062ccd06b0e" Role="ICO_WINDOWS"></Resource>
        <Resource File="meta/icon128.png" HashAlgorithm="SHA-256" HashValue="404b0d848df4c98a02804b6e7566b4c4bf27430f7c584381d32cf43a0b3e4028" Role="ICON_128"></Resource>
        <Resource File="meta/icon16.png" HashAlgorithm="SHA-256" HashValue="47734e7530a565bca0d8b3c2015600441b31fe151c59855b4f0af535360e1cf9" Role="ICON_16"></Resource>
        <Resource File="meta/icon24.png" HashAlgorithm="SHA-256" HashValue="7597832ef6ebff7f4fa8ac0c8774552f54b47391f8db8479ea96e395556c7da0" Role="ICON_24"></Resource>
        <Resource File="meta/icon32.png" HashAlgorithm="SHA-256" HashValue="e3ea34ef4296b538d7ef5d58ad511ab5bd4b4b078a30f1910e9789143c98776a" Role="ICON_32"></Resource>
        <Resource File="meta/icon48.png" HashAlgorithm="SHA-256" HashValue="35d5ada26910c3f707f9b8cfb016b1dca9a575c940018fa5048d71258581b0fc" Role="ICON_48"></Resource>
        <Resource File="meta/icon64.png" HashAlgorithm="SHA-256" HashValue="c30a14e51ade414a6110daa447e8d44cfa10808fa9ce06b4bb67f37def7fd04e" Role="ICON_64"></Resource>
        <Resource File="meta/license.txt" HashAlgorithm="SHA-256" HashValue="cb2db7e26966764c369e6fb4ca08a989e752d926016dd132661a8c64b25149f4" Role="LICENSE"></Resource>
        <Resource File="meta/screenshot.png" HashAlgorithm="SHA-256" HashValue="8341f4b229fea93885c52d7ad3797da8803d4e291b3a9e6f8c2c4d4d641637aa" Role="SCREENSHOT">
            <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.
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
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.tgz
-rw-r--r--  1 montarre   montarre   81923503 Oct 15 12:11 com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.tgz
-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.tgz, a shell distribution named com.io7m.montarre-0.0.1-SNAPSHOT-any.tgz, 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
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>0.0.5</version>
</plugin>
The package goal produces a montarre package from the current module's dependencies.
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>
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>
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>
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>
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.5.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>
The humanName element specifies a humanly-readable application name.

4.2.1.2.6.2. Example

<humanName>Montarre</humanName>
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.7.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>
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.8.2. Example

<license>ISC</license>
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.9.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>
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.10.3. Example

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

4.2.1.2.10.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>
...
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.11.2. Example

<mainModule>com.io7m.montarre.cmdline/com.io7m.montarre.cmdline.MMain</mainModule>
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.12.2. Example

<outputFile>com.io7m.montarre.cmdline-0.0.5.mpk</mainModule>
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.13.3. Example

<packageName>com.io7m.montarre</packageName>
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.14.3. Example

<version>
  <number>0.0.5</number>
  <date>2024-10-06</date>
</version>
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.15.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>
The requiredJDKVersion element specifies the minimum Java version required to run the application.

4.2.1.2.16.2. Example

<requiredJDKVersion>21</requiredJDKVersion>
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.17.2. Example

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

<shortName>montarre</requiredJDKVersion>
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.19.2. Example

<vendor>
  <id>com.io7m</id>
  <name>io7m</name>
</vendor>
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
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.
help - Show usage information for a command.
The help command shows the help for a given command.

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.
maven-central download - Download a package from Maven Central
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.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.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
native create - Create native packages.
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.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.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.tgz
-rw-r--r--  1 montarre   montarre   81923503 Oct 13 12:11 com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.tgz
-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
native packagers - List native packagers.
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.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.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
--
package check - Check a package file.
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.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.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
package extract-declaration - Extract a package declaration from a file without validation.
The package extract-declaration command prints the serialized package declaration from the given package file.

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.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>
...
package pack - Pack a package file.
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.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.1. Example

$ montarre package pack --input-directory /tmp/out2 --output-file montarre.mpk
package schema - Show the package schema.
The package schema command prints the currently-supported package schema.

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.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>
...
package unpack - Unpack a package file.
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.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.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/
package validate - Validate a package file.
The package validate command runs validation on the given package file.

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.1. Example

$ montarre package validate --file com.io7m.montarre.distribution/target/com.io7m.montarre.distribution-0.0.1-SNAPSHOT.mpk
version - Show the application version.
The version command shows the current application version.

5.12.3.1. Example

$ montarre version
com.io7m.montarre 0.0.1-SNAPSHOT f47e12fd7363837c6358eeec53b3122645b06df5
wix xml - Generate WiX XML.
The wix xml command generates a WiX toolset file from a given package and directory hierarchy.

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.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>
...
The com.io7m.montarre.app_image packager creates jpackage "app image" executables.
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.
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}.tgz on POSIX-like platforms.
An example output of the packager is com.io7m.montarre-0.0.1-SNAPSHOT-x86_64-linux.tgz.
The com.io7m.montarre.deb packager creates Debian packages.
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.
The com.io7m.montarre.flatpak packager creates Flatpaks.
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.
The com.io7m.montarre.msi packager creates MSI installers.
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.
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.
The com.io7m.montarre.shell packager creates platform-independent shell distributions.
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.
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
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 \
  "$@"
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.
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
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
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)
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
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.tgz unconditionally.
An example output of the packager is com.io7m.montarre-0.0.1-SNAPSHOT-any.tgz.

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
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 Coq 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.
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}.
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}").
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".
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
}.
A hash is a record consisting of an algorithm and a value.

7.6.1.2. Hash

Inductive HashT := Hash {
  hashAlgorithm : HashAlgorithmT;
  hashValue     : HashValueT
}.
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.
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.
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.
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.
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
}.
A montarre package contains a single package declaration which specifies metadata and a manifest.
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
}.
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
  .
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".
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
}.
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".
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".
A description is a short translated text that provides a summary of the package.

7.11.5.2. Description

Definition DescriptionT :=
  TranslatedTextT.
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
}.
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
  .
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".
The java info information for a package is a record consisting of a required JDK version and a main module.

7.11.7.1.2. Java Info

Inductive JavaInfoT := JavaInfo {
  requiredJDKVersion : nat;
  mainModule         : string
}.
The required JDK version specifies the lower bound of the major version of the Java runtime required to use this package.
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".
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
}.
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
  .
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
}.
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.
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.
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
}.
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".
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".
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".
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
}.
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.
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".
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
}.
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
}.
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".
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.
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.
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.3.2. Module

Inductive ModuleT :=
  Module : FileNameT -> HashT -> ModuleT.
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.4.2. PlatformModule

Inductive PlatformModuleT :=
  PlatformModule : FileNameT -> HashT -> PlatformT -> PlatformModuleT.
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.5.2. Resource

Inductive ResourceT :=
  Resource : FileNameT -> HashT -> ResourceRoleT -> CaptionT -> ResourceT.
A resource has an associated role that describes the purpose of the resource.

7.12.5.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.5.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.5.8. Resource Caption

Definition CaptionT :=
  TranslatedTextT.
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 a ZIP file with some extra restrictions on the entries. Extra restrictions are applied to the ZIP container and the XML data to assist with ensuring that montarre packages are reproducible.
montarre packages are ZIP files with the file extension .mpk. The following restrictions are applied to the entries of the ZIP file:

7.13.2.2. ZIP Entry Restrictions

  • All entry names in the ZIP file must be valid file names.
  • All entry names in the ZIP file must be transformed to uppercase in a neutral locale.
  • All entries must be written with creation, modification, and last access dates of 2024-10-14T00:00:00Z.
  • All entries, except for the first entry, must be written such that their names appear in ascending alphabetical order.
  • The first entry in the file must be META-INF/MONTARRE/PACKAGE.XML.
The package declaration is serialized to XML and stored in the META-INF/MONTARRE/PACKAGE.XML entry in the ZIP file.
An example valid ZIP listing of a package is as follows:

7.13.2.5. Example ZIP Listing

Length      Date    Time    Name
---------  ---------- -----   ----
     9147  2024-10-14 00:00   META-INF/MONTARRE/PACKAGE.XML
    15052  2024-10-14 00:00   LIB/COM.IO7M.ANETHUM.API-1.1.1.JAR
    42944  2024-10-14 00:00   LIB/COM.IO7M.BLACKTHORNE.CORE-2.0.2.JAR
     5166  2024-10-14 00:00   LIB/COM.IO7M.BLACKTHORNE.JXE-2.0.2.JAR
    38355  2024-10-14 00:00   LIB/COM.IO7M.JAFFIRM.CORE-4.0.1.JAR
     5569  2024-10-14 00:00   LIB/COM.IO7M.JCIP-2.0.1.JAR
    21462  2024-10-14 00:00   LIB/COM.IO7M.JDOWNLOAD.CORE-1.0.0.JAR
    12841  2024-10-14 00:00   LIB/COM.IO7M.JLEXING.CORE-3.2.0.JAR
    10227  2024-10-14 00:00   LIB/COM.IO7M.JMULTICLOSE.CORE-1.1.3.JAR
     4505  2024-10-14 00:00   LIB/COM.IO7M.JUNREACHABLE.CORE-4.0.2.JAR
    21622  2024-10-14 00:00   LIB/COM.IO7M.JXE.CORE-2.0.0.JAR
     6730  2024-10-14 00:00   LIB/COM.IO7M.JXTRAND.API-2.1.0.JAR
     9797  2024-10-14 00:00   LIB/COM.IO7M.JXTRAND.VANILLA-2.1.0.JAR
    10609  2024-10-14 00:00   LIB/COM.IO7M.LANARK.CORE-1.2.0.JAR
   131113  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.API-0.0.1-SNAPSHOT.JAR
    48154  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.CMDLINE-0.0.1-SNAPSHOT.JAR
    35065  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.IO-0.0.1-SNAPSHOT.JAR
   175186  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.NATIVEPACK-0.0.1-SNAPSHOT.JAR
     7016  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.SCHEMA-0.0.1-SNAPSHOT.JAR
    55257  2024-10-14 00:00   LIB/COM.IO7M.MONTARRE.XML-0.0.1-SNAPSHOT.JAR
   109688  2024-10-14 00:00   LIB/COM.IO7M.QUARREL.CORE-1.6.1.JAR
     5985  2024-10-14 00:00   LIB/COM.IO7M.QUARREL.EXT.LOGBACK-1.6.1.JAR
     9077  2024-10-14 00:00   LIB/COM.IO7M.SELTZER.API-1.1.0.JAR
     9750  2024-10-14 00:00   LIB/COM.IO7M.STREAMTIME.CORE-1.0.0.JAR
    11838  2024-10-14 00:00   LIB/COM.IO7M.VERONA.CORE-1.0.1.JAR
   372687  2024-10-14 00:00   LIB/COMMONS-CODEC-1.17.1.JAR
  1087319  2024-10-14 00:00   LIB/COMMONS-COMPRESS-1.27.1.JAR
   515978  2024-10-14 00:00   LIB/COMMONS-IO-2.17.0.JAR
   673587  2024-10-14 00:00   LIB/COMMONS-LANG3-3.17.0.JAR
   304513  2024-10-14 00:00   LIB/LOGBACK-CLASSIC-1.5.8.JAR
   619394  2024-10-14 00:00   LIB/LOGBACK-CORE-1.5.8.JAR
    69435  2024-10-14 00:00   LIB/SLF4J-API-2.0.16.JAR
   262317  2024-10-14 00:00   META/BOM.XML
   102134  2024-10-14 00:00   META/ICON.ICO
    41273  2024-10-14 00:00   META/ICON128.PNG
      544  2024-10-14 00:00   META/ICON16.PNG
      732  2024-10-14 00:00   META/ICON24.PNG
     1973  2024-10-14 00:00   META/ICON32.PNG
     5461  2024-10-14 00:00   META/ICON48.PNG
    10050  2024-10-14 00:00   META/ICON64.PNG
      768  2024-10-14 00:00   META/LICENSE.TXT
    16002  2024-10-14 00:00   META/SCREENSHOT.PNG
---------                     -------
  4896322                     42 files
Package declarations must be serialized according to the included schema with the following restrictions:

7.13.3.2. ZIP Entry Restrictions

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:element name="JavaInfo">
    <xsd:annotation>
      <xsd:documentation xml:lang="en">
        Information relative to the Java runtime.
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <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="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="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="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="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>
The full sources of the specification model are provided here.

7.14.2. Montarre/Package.v

Require Import Coq.Unicode.Utf8_core.
Require Import Coq.Strings.String.
Require Import Coq.Strings.Ascii.
Require Import Coq.FSets.FMapInterface.
Require Import Coq.FSets.FMapWeakList.
Require Import Coq.FSets.FMapFacts.
Require Import Coq.Structures.Equalities.

(** 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 JavaInfoT := JavaInfo {
  requiredJDKVersion : nat;
  mainModule         : string
}.

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.

(** 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 : FileNameT -> HashT -> ModuleT.

Inductive PlatformModuleT :=
  PlatformModule : FileNameT -> HashT -> PlatformT -> PlatformModuleT.

Inductive ResourceT :=
  Resource : FileNameT -> HashT -> ResourceRoleT -> CaptionT -> ResourceT.

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

Definition itemFileName (i : ItemT) : FileNameT :=
  match i with
  | ItemModule         (Module f _)           => f
  | ItemPlatformModule (PlatformModule f _ _) => f
  | ItemResource       (Resource f _ _ _)     => f
  end.

Definition itemHash (i : ItemT) : HashT :=
  match i with
  | ItemModule         (Module _ h)           => h
  | ItemPlatformModule (PlatformModule _ h _) => h
  | ItemResource       (Resource _ h _ _)     => h
  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))).

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
io7m | single-page | multi-page | epub | Montarre User Manual 0.0.5