{"id":13505512,"url":"https://github.com/kuiperzone/PupNet-Deploy","last_synced_at":"2025-03-30T00:30:56.080Z","repository":{"id":151029914,"uuid":"608784167","full_name":"kuiperzone/PupNet-Deploy","owner":"kuiperzone","description":"PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.","archived":false,"fork":false,"pushed_at":"2024-05-21T12:06:52.000Z","size":8080,"stargazers_count":215,"open_issues_count":16,"forks_count":10,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-28T19:09:46.076Z","etag":null,"topics":["appimage","csharp","debian","deploy","dotnet","flatpak","installation-automation","linux","package","rpm","setup","windows"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kuiperzone.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-02T18:21:10.000Z","updated_at":"2025-03-26T09:12:36.000Z","dependencies_parsed_at":"2023-04-12T04:32:16.394Z","dependency_job_id":"1da33229-c547-48e5-8c1b-406dfcbe1bc5","html_url":"https://github.com/kuiperzone/PupNet-Deploy","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuiperzone%2FPupNet-Deploy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuiperzone%2FPupNet-Deploy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuiperzone%2FPupNet-Deploy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kuiperzone%2FPupNet-Deploy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kuiperzone","download_url":"https://codeload.github.com/kuiperzone/PupNet-Deploy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246262490,"owners_count":20749170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appimage","csharp","debian","deploy","dotnet","flatpak","installation-automation","linux","package","rpm","setup","windows"],"created_at":"2024-08-01T00:01:09.234Z","updated_at":"2025-03-30T00:30:56.056Z","avatar_url":"https://github.com/kuiperzone.png","language":"C#","readme":"\u003cp style=\"text-align:center;margin-bottom:4em;\"\u003e\n    \u003cimg src=\"Media/PupNet.1280x388.png\" style=\"width:100%;\"/\u003e\n\u003c/p\u003e\n\n# PupNet Deploy - Publish \u0026 Package for .NET #\n\n**PupNet Deploy** is a cross-platform deployment utility which packages your .NET project as a ready-to-ship\ninstallation file in a single step.\n\n## Announcement 2024 ##\nI'd like to take a moment to thank recent contributors, but also say that I'm not in position to maintain this\nproject on a timely basis. That doesn't mean that it's abandoned and I do, in fact, plan on making updates in the\nfuture, especially around AppImage. I've just got other commitments at the moment which take up a lot of my time.\nThank you. Kuiper\n\n## CONTENTS ##\n\n* [INTRODUCTION](#introduction)\n    * [General Principles](#general-principles)\n\n* [INSTALL \u0026 PREREQUISITES](#install-prerequisites)\n    * [AppImage Out of the Box](#appimage-out-of-the-box)\n    * [Flatpaks on Linux](#flatpak-on-linux)\n    * [Debian Packages on Linux](#debian-packages-on-linux)\n    * [RPM Packages on Linux](#rpm-packages-on-linux)\n    * [Setup Files on Windows](#setup-files-on-windows)\n\n* [PUPNET CONFIGURATION](#pupnet-configuration)\n    * [Desktop File](#desktop-file)\n    * [AppStream Metadata](#appstream-metadata)\n    * [Icons](#icons)\n    * [Dotnet Project Path](#dotnet-project-path)\n    * [Dotnet Publish Arguments](#dotnet-publish-arguments)\n    * [Application Versioning \u0026 Changelog](#application-versioning-changelog)\n        * [Application Version (AppVersionRelease)](#application-version)\n        * [Changelog (AppChangeFile)](#changelog)\n    * [Terminal vs GUI Applications](#terminal-vs-gui-applications)\n        * [GUI Application](#gui-application)\n        * [Terminal Application](#terminal-application\")\n    * [Custom Post-Publish Operations](#custom-post-publish-operations)\n        * [Non-Dotnet Projects](#non-dotnet-projects)\n    * [Debian \u0026 RPM Considerations](#debian-rpm-considerations)\n        * [Install Location](#debian-rpm-install-location)\n        * [Dependencies](#debian-rpm-dependencies)\n\n* [BUILDING THE HELLO WORLD DEMO](#building-the-hello-world-demo)\n    * [On Linux](#on-linux)\n    * [On Windows](#on-windows)\n\n* [CREATING NEW PUPNET PROJECT FILES](#creating-new-pupnet-project-files)\n\n* [BACKWARD COMPATIBILITY \u0026 UPGRADING YOUR CONFIGURATION](#backward-compatibility-upgrading-your-configuration)\n    * [Version 1.4 Changes](#version-1.4-changes)\n\n* [HELP SYSTEM REFERENCE](#help-system-reference)\n    * [Command Arguments](#command-arguments)\n    * [Macro Reference](#macro-reference)\n    * [Configuration Reference](#configuration-reference)\n\n* [FAQs \u0026 GOTCHAS](#faqs-gotchas)\n    * [NETSDK1194: The \"--output\" option isn't supported](#NETSDK1194)\n    * [Virtual Box \u0026 Symlinks](#virtual-box-symlinks)\n    * [Package Naming is not Consistent](#package-naming-is-not-consistent)\n    * [Package Cannot be Removed using Gnome Software Center](#package-cannot-be-removed-using-gnome-software-center)\n\n* [ADDITIONAL INFORMATION](#additional-information)\n    * [Brief Discussion on Past \u0026 Future](#brief-discussion-on-past-future)\n    * [Notes on Extending PupNet](#notes-on-extending-pupnet)\n    * [An Application which uses PupNet Deploy](#an-application-which-uses-pupnet-deploy)\n    * [Copyright \u0026 License](#copyright-license)\n\n\n## INTRODUCTION \u003ca name=\"introduction\"/\u003e\n\nIt has been possible to cross-compile console C# applications for sometime now. More recently, the cross-platform\n[Avalonia](https://github.com/AvaloniaUI/Avalonia) replacement for WPF allows fully-featured GUI applications to target\na range of platforms, including: Linux, Windows, MacOS and Android.\n\nNow, **PupNet Deploy** allows you to ship your dotnet application as:\n\n* AppImage for Linux\n* Setup File for Windows\n* Flatpak for Linux\n* Debian Binary Package\n* RPM Binary Package\n* Plain old Zip\n\nTo create an installation file, you fill out the parameters in a simple `pupnet.conf` file and, from within your project,\nrun a command like so:\n\n    pupnet --runtime linux-x64 --kind appimage\n\nIn this case, PupNet calls `dotnet publish` on your project and generates a distributable [AppImage](https://github.com/AppImage/AppImageKit)\nfile fo use on Linux systems. Additionally, you may optionally provide `.desktop` and AppStream metadata files.\nThere is no need to write complex build-specific manifests, RPM spec or Debian control files. You need only supply your\ndeployment configuration once as a single `pupnet.conf` file, and PupNet takes care of the underlying build-specific tasks.\n\nLikewise, to package the same project for Windows:\n\n    pupnet -r win-x64 -k setup\n\nPupNet has good support for internationalization, desktop icons, publisher metadata and custom build operations.\nAlthough developed for .NET, it is also possible to use it to deploy C++ and other kinds of applications.\n\nThe output of PupNet is a distributable file, such as an AppImage, flatpak or Windows Setup.exe file -- it does\nnot auto-submit your project to repositories. Note also that, in order to build a Linux deployment, the build system\nmust be a Linux box and, likewise to build a Windows Setup file, a Windows system (virtual machines are handy).\n\nHowever, it is possible to build a Debian package on an RPM machine, and viceversa.\n\n### General Principles \u003ca name=\"general-principles\"/\u003e\n\n#### Single App per Install Package ####\nIt is assumed that you are building a deployment package containing a single application. AppImages also work this way\nand, from .NET7 onward, it is no longer possible to `publish` a dotnet solution containing multiple projects.\n\nThis may be something investigated in the future but, for the moment, PupNet is not suitable for deploying a suit of\napplications as a single package.\n\n#### Read-only Access to Installation ####\nAs a general principle when deploying your software, it should be assumed that your application has read-only access to\nits installation folder. Your application should use the `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData`\nlocation or other suitable special folder to write data.\n\n\n## INSTALL \u0026 PREREQUISITES \u003ca name=\"install-prerequisites\"/\u003e\n\nTo install as a dotnet tool:\n\n    dotnet tool install -g KuiperZone.PupNet\n\nCurrently, the \"PupNet tool\" targets .NET8 LTS (this does not restrict the dotnet version of your own projects).\nThe last version of PupNet built against .NET6 was 1.7.1.\n\nAlternatively, for self-contained installers:\n\n**[DOWNLOAD \u0026 INSTALL](https://github.com/kuiperzone/PupNet/releases/latest)**\n\nIf you are using the AppImage deployment of PupNet, add it to your path and consider renaming the AppImage file to `pupnet`\nso that the instructions below will match your system.\n\n### AppImage Out of the Box \u003ca name=\"appimage-out-of-the-box\"/\u003e\nOut of the box, PupNet can create AppImages on Linux and Zip files on all platforms. **There is no need to install any\nAppImage tools therefore.** In order to build other deployments, however, you must first install the appropriate\nthird-party builder tool against which PupNet will call.\n\n### Flatpaks on Linux \u003ca name=\"flatpak-on-linux\"/\u003e\n\nPupNet requires `flatpak` and `flatpak-builder`. It will also be necessary to install a flatpak platform SDK and runtime.\nAs appropriate, use:\n\n    sudo dnf install flatpak flatpak-builder\n\nor:\n\n    sudo apt install flatpak flatpak-builder\n\nAnd then use flatpak to install:\n\n    sudo flatpak install flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08\n\nHere, the version number (23.08) was the latest at the time of writing, but will be subject to update.\nSee [Flatpak Available Runtimes](https://docs.flatpak.org/en/latest/available-runtimes.html).\n\n### Debian Packages on Linux \u003ca name=\"debian-packages-on-linux\"/\u003e\n\nPupNet requires `dpkg-deb`. So, as appropriate:\n\n    sudo apt install dpkg\n\nor:\n\n    sudo dnf install dpkg\n\nIt is possible to build Debian packages using `dpkg-deb` on an RPM based system. However, it is not recommended to\ntest install a Debian package on an RPM machine (use a virtual machines to test it).\n\n### RPM Packages on Linux \u003ca name=\"rpm-packages-on-linux\"/\u003e\n\nPupNet requires `rpmbuild`. As appropriate:\n\n    sudo dnf install rpmdevtools\n\nor:\n\n    sudo apt install rpm\n\nIt is possible to build RPM packages using `rpmbuild` on a Debian system. However, as above, it is not recommended to\ntest install an RPM package on a Debian machine (use a virtual machines to test it).\n\n### Setup Files on Windows \u003ca name=\"setup-files-on-windows\"/\u003e\n\nPupNet leverages [InnoSetup](https://jrsoftware.org/isinfo.php) on Windows. Download and install it.\n\nIt will also be necessary to manually add the InnoSetup location to the user's PATH variable\nso that PupNet can call the `iscc` compiler. See screenshot below below:\n\n\u003cp style=\"text-align:left;margin-top:2em;margin-bottom:2em;\"\u003e\n    \u003cimg src=\"Media/Screenie-InnoPath.png\" style=\"width:40%;max-width:400px;\"/\u003e\n\u003c/p\u003e\n\n\n## PUPNET CONFIGURATION \u003ca name=\"pupnet-configuration\"/\u003e\n\n**Hello World for PupNet** is a demonstration project for PupNet Deploy. It will be instructive to discuss\nthe major configuration elements with reference to this simple project, as it demonstrates all the major\nfeatures of building distributable packages.\n\nThe Hello World project lives in [a separate git repo](https://github.com/kuiperzone/PupNet-HelloWorld) of its own:\n\n\u003cp style=\"text-align:left;margin-bottom:4em;\"\u003e\n    \u003ca href=\"https://github.com/kuiperzone/PupNet-HelloWorld\" style=\"outline-style:none;\"\u003e\n        \u003cimg src=\"Media/HelloWorld.1280x388.png\" style=\"width:40%;max-width:400px;\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nHead over to this project in a different browser tab, or download it to your local drive.\n\nNow, take a look at the `HelloWorld.pupnet.conf` in the root of the project.\n\n\u003cp style=\"text-align:left;margin-top:2em;margin-bottom:2em;\"\u003e\n    \u003cimg src=\"Media/Screenie-Configuration.png\" style=\"width:60%;max-width:400px;\"/\u003e\n\u003c/p\u003e\n\nThis is a simple ini file in which the deployment project is configured. Where local paths are given, they are local\nto the `.conf` file, rather than your current working directory. Always use the forward-slash '/' as a path separator\nfor cross-platform compatibility.\n\nYou will see that each parameter is documented. However, we will discuss key properties and issues below.\n\n### Desktop File \u003ca name=\"desktop-file\"/\u003e\n\nNote the `DesktopFile` parameter which provides a path to a Linux `.desktop` file. *If you leave it blank, one will\nbe generated automatically.* In the Hello World demo, we have specified a file in order to show the default contents...\n\nOpen the file `Deploy/app.desktop`, and you will see:\n\n    [Desktop Entry]\n    Type=Application\n    Name=${APP_FRIENDLY_NAME}\n    Icon=${APP_ID}\n    Comment=${APP_SHORT_SUMMARY}\n    Exec=${INSTALL_EXEC}\n    TryExec=${INSTALL_EXEC}\n    NoDisplay=${DESKTOP_NODISPLAY}\n    X-AppImage-Integrate=${DESKTOP_INTEGRATE}\n    Terminal=${DESKTOP_TERMINAL}\n    Categories=${PRIME_CATEGORY}\n    MimeType=\n    Keywords=\n\nNote that the contents above are entirely populated using macro variables (more below on these). However, you can\neasily extend this file to specify a `MimeType` and `Keywords`, as well as adding international translations and\nadditional entries.\n\nIMPORTANT: While you can edit this file as you wish, the file must contain the line below with its macro:\n\n    Exec=${INSTALL_EXEC}\n\nOr, if you prefer:\n\n    Exec=${INSTALL_BIN}/app-name\n\nThe reason for this is that the actual path on installation will depend on the package type. You cannot hard code this\nhere as different packages will install to different paths. It is important also that you use macros as shown with\ntheir braces, i.e. `${INSTALL_EXEC}` and not `$INSTALL_EXEC`, as a simple search-and-replace operation is\nused to populate them.\n\nIn the event that you wish there be no desktop entry (i.e. a command-line application), you should declare:\n`DesktopNoDisplay = true`. The file itself is ignored for Windows `Setup`, although if you set `DesktopNoDisplay`, then\nno entry for your application's main executable will be added under the Windows Start Menu (i.e. synonymous\nbehavior on Windows with that on Linux).\n\n**Hint:** You can use PupNet itself to generate a Linux desktop file for a new project:\n\n    pupnet [name] --new desktop\n\nThis will create a new file for you under: `name.desktop`\n\n### AppStream Metadata \u003ca name=\"appstream-metadata\"/\u003e\n\nThe `MetaFile` parameter specifies the path to a local AppStream metadata XML file. This applies to Linux only and\nis optional. This metadata is used by software centers to display information about installed applications. For\ndetail information, see [AppStream Metadata Quick Start](https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html).\n\nIf you omit the `MetaFile` property, no `.metainfo.xml` file is shipped with your application. But let's assume you\nwish to provide metadata, so take a look at the file provided under: `Deploy/app.metainfo.xml` in the Hello World demo.\n\nAgain, you will notice that macro variables are used. These are entirely optional here and simply mean that, as far\nas possible, deployment configuration data is specified in one place only (i.e. your `pupnet.conf` file). However,\nyou may still wish to edit and extend this file to provide a screenshot, international language translations and\nadditional information such as keywords.\n\n**IMPORTANT:** Since PupNet version 1.4.0, the macros `${APPSTREAM_DESCRIPTION_XML}` and `${APPSTREAM_CHANGELOG_XML}`\nmay be used to auto-populate the default application description, and change (release) information. The latter is\ndescribed in more detail below under [Application Versioning](#application-versioning-changelog).\n\n**Hint:** You can use PupNet itself to generate a metadata template file for a new project:\n\n    pupnet [name] --new meta\n\nThis will create a new file for you under: `name.metainfo.xml`\n\n\n### Icons \u003ca name=\"icons\"/\u003e\n\nMultiple desktop icons are provided with the `IconPaths` parameter. You can use semi-colon as a separator, such as:\n`IconPaths = icon1.ico;icon2.64x64.png;icon3.svg`, or present them in multi-line form as shown in the Hello World demo:\n\n    IconFiles = \"\"\"\n        Deploy/HelloWorld.16x16.png\n        Deploy/HelloWorld.24x24.png\n        Deploy/HelloWorld.32x32.png\n        Deploy/HelloWorld.48x48.png\n        Deploy/HelloWorld.64x64.png\n        Deploy/HelloWorld.svg\n        Deploy/HelloWorld.ico\n    \"\"\"\n\nNote the use of *triple quotes* here for multi-line values.\n\nUse only the `svg`, `png` and `ico` file types. On Linux, `svg` and `png` files will be installed appropriately and the\nWindows `ico` file ignored. For Windows `Setup` packages, on the other hand, only the `ico` file is used, and PNG and SVG\nfiles are ignored.\n\n**IMPORTANT:** It is necessary to specify the size of PNG files by embedding their size in the filename, as shown above,\nor simply as: `name.64.png`.\n\n\n### Dotnet Project Path \u003ca name=\"dotnet-project-path\"/\u003e\n\nWhen building the deployment, PupNet first calls `dotnet publish` on your project. To do this, it needs to know where\nyour project lives. In `HelloWorld.pupnet.conf`, you may note that file is at the solution level, but `DotnetProjectPath`\nvalue provides the project directory.\n\nIf your `pupnet.conf` files shares the same directory as your `.csproj` file, you may leave `DotnetProjectPath`\nempty. Otherwise use this field to specify the path to your project file or directory relative to the location\nof the configuration file.\n\n\n### Dotnet Publish Arguments \u003ca name=\"dotnet-publish-arguments\"/\u003e\n\nThe `DotnetPublishArgs` parameter is used to specify values to supply to the `dotnet publish` call:\n\n    DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false\n\nDo NOT include '-r' (runtime), or '-c' (configuration) here as they will be added automatically according to\nconfiguration and command line arguments.\n\nAs an absolute minimum, we always want to include `--self-contained true`, as this will cause dotnet not only to\ncompile the application, but to publish all dependencies into a single directory. (From .NET8 onward you may wish to\nconsider using Native AOT).\n\n\n### Application Versioning \u0026 Changelog \u003ca name=\"application-versioning-changelog\"/\u003e\n\n#### Application Version (AppVersionRelease) \u003ca name=\"application-version\"/\u003e\nThe application version (plus release number) is specified in the `pupnet.conf` file, for example:\n\n    AppVersionRelease = 3.2.1[5]\n\nHere we are using the semantic version `3.2.1` plus a \"package release number\" in square brackets. The release number\napplies specifically to the deployment package itself and is used by `rpm` and `deb` package kinds. If you omit the\nrelease number, and just give `3.2.1` for example, it defaults to 1.\n\nIf you prefer, you can override the version in the configuration file from the command line using:\n\n    pupnet --runtime linux-arm64 --kind deb --app-version 4.0.0[1]\n\nCrucially, look again at the `DotnetPublishArgs` configuration value we gave above above and note `${APP_VERSION}`:\n\n    DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false\n\nHere, we can see that the version from our configuration is supplied to the build process as a variable (only the\napplication part is supplied, i.e. `3.2.1`). This is optional and you may remove it if you wish, although you will\nthen need to specify the version both in application code and the `pupnet.conf` file in this case.\n\n#### Changelog (AppChangeFile) \u003ca name=\"changelog\"/\u003e\nPupNet version 1.4 introduced the `AppChangeFile` configuration property. This gives the path to a changelog file\nwhich must use a predefined but simple format, or a README file which contains such formatted changelog information.\n\nPupNet will parse the file and extract relevant change information. This is used to expand the `${APPSTREAM_CHANGELOG_XML}`\nmacro variable which may optionally be used within the `\u003crelease\u003e` element of your AppStream metadata file. This means\nthat lengthy version change information need only be specified once (in a changelog or README file).\n\nVersion change information is to be provided as one or more version release sections prefixed with '+' and a leading\nversion number, and suffixed with trailing date. Subsequent change items are prefixed with '-', as shown below.\nNote that ';' is used as a separator.\n\n    + VERSION;[Other fields ignored;]yyyy-MM-dd\n    - Change feature 3\n    - Change feature 4\n\n    + VERSION;[Other fields ignored;]yyyy-MM-dd\n    - Change feature 1\n    - Change feature 2\n\nAdditional fields, between the VERSION number and trailing date, may used as you wish, i.e. to give a version title\nand/or maintainer contact information, as below.\n\n    + VERSION 1.3.1; Patch Release; nobody@kuiper.zone; 2023-05-01\n    - Bugfix: Fix package creation when file path of contents contain spaces (enclose file path with quotes when executing chmod)\n\nHere, the version title and contact information will be ignored and are not used in AppStream data.\n\nIt is possible for change items to span multiple lines, as follows, but a change item should not be broken with an\nempty line (otherwise the parser will think it is reading plain superfluous text).\n\nThe following two examples are \"legal\":\n\n    + 1.3.1;2023-05-01\n    - Long change line\n      describing feature 3\n    - Change feature 4\n\n\n    + 1.3.1;2023-05-01\n\n    - Long change line\n      describing feature 1\n\n    - Change feature 2\n\nThe following example is \"illegal\" and will result in version information loss:\n\n    + 1.3.1;2023-05-01\n    - Long change line\n\n      describing feature 1\n    - Change feature 2\n\nThe changelog parser should do a robust job at parsing version information while ignoring superfluous README text,\nbut care should be taken to ensure that version information is correctly formatted. You may review the final AppStream\nmetadata (after macro expansion) by using `--verbose` command line option when building your deployment.\n\nFinally, it should be stressed that this feature is entirely optional. If it does not suit your project, leave\n`AppChangeFile` blank and specify version release information in your AppStream metadata file yourself (or just omit it).\n\n### Terminal vs GUI Applications \u003ca name=\"terminal-vs-gui-applications\"/\u003e\n\nWhile the Hello World demo is a terminal application, it was envisaged that a typical use case for PupNet\nwould be to deploy GUI applications built with Avalonia that are integrated with the desktop.\n\n#### GUI Application \u003ca name=\"gui-application\"/\u003e\nFor a GUI application, you will want to ensure the following:\n\n    DesktopNoDisplay = false\n    DesktopTerminal = false\n\nYou may typically leave `StartCommand` empty, but may set it if you wish.\n\n#### Terminal Application  \u003ca name=\"terminal-application\"/\u003e\nIMPORTANT: Your terminal application will not be in the user's path by default, so note `StartCommand` and\n`SetupCommandPrompt` below. Note, also, that Flatpak is not suitable for command-line centric applications.\n\n    DesktopNoDisplay = true\n    DesktopTerminal = true\n    StartCommand = command-name\n    SetupCommandPrompt = Command Prompt\n\nFor command line only apps, you would typically set `DesktopNoDisplay` true, but you may give your application a desktop\nentry by setting it to false if you wish.\n\nWith `StartCommand`, you should set a simple command name for application which will be located in the user's path after\ninstallation. This will actually be realized via a tiny bash script on Linux, or bat file on Windows, which will launch\nyour main application (the rest of your application will not be in the path). If, for example, your runnable file is\nsomething like 'Zone.Kuiper.HelloWorld', you may set `StartCommand` simply to 'helloworld'.\n\nOn Windows, a different approach is taken. The `SetupCommandPrompt` is a Windows only option which ensures that a\nConsole entry is written to the Program Files menu (using the title you supply) which, when launched, will open a\ndedicated command window with your application directory in the path for the session.\n\n\n### Custom Post-Publish Operations \u003ca name=\"custom-post-publish-operations\"/\u003e\n\nIn `HelloWorld.pupnet.conf`, we see the lines:\n\n    DotnetPostPublish = Deploy/PostPublish.sh\n    DotnetPostPublishOnWindows = Deploy/PostPublish.bat\n\nThis is an advanced feature which allows you to call a command or script in order to perform additional operations after\n`dotnet publish` has been called, but prior to building the package output. The above commands are called only on their\nrespective build systems, and should perform equivalent operation.\n\nSuch scripts may employ macro variables which are exported to the environment. The Hello World bash and batch scripts above,\nfor example, create a subdirectory and dummy file within the application build directory, the path of which is supplied\nas the `${BUILD_APP_BIN}` environment variable (see below for a complete reference).\n\nHere are the contents of our example bash script:\n\n    #!/bin/bash\n    # This is a dummy bash script used for demonstration and test. It outputs a few variables\n    # and creates a dummy file in the application directory which will be detected by the program.\n\n    echo\n    echo \"===========================\"\n    echo \"POST_PUBLISH BASH SCRIPT\"\n    echo \"===========================\"\n    echo\n\n    # Some useful macros / environment variables\n    echo \"BUILD_ARCH: ${BUILD_ARCH}\"\n    echo \"BUILD_TARGET: ${BUILD_TARGET}\"\n    echo \"BUILD_SHARE: ${BUILD_SHARE}\"\n    echo \"BUILD_APP_BIN: ${BUILD_APP_BIN}\"\n    echo\n\n    # Directory and file will be detected by HelloWorld Program\n    echo \"Do work...\"\n    set -x #echo on\n    mkdir -p \"${BUILD_APP_BIN}/subdir\"\n    touch \"${BUILD_APP_BIN}/subdir/file.test\"\n    set +x #echo off\n\n    echo\n    echo \"===========================\"\n    echo \"POST_PUBLISH END\"\n    echo \"===========================\"\n    echo\n\nLikewise, in the Hello World demo bat file which does the equivalent job on Windows.\n\n#### Non-Dotnet Projects \u003ca name=\"non-dotnet-projects\"/\u003e\nAdditionally, you may leverage the post-publish operations (above) to perform the actual build operation itself\nand populate the `${BUILD_APP_BIN}` directory with the output of your build process -- whatever that may be. In\nprinciple, therefore, you could use this to package a C++ or Python application, provided that it is satisfactory\nthat the application and all its associated libraries are contained in a single target directory.\n\nIMPORTANT: If you do this, you will need to disable PupNet from calling `dotnet publish`, which can be done by setting\n`DotnetProjectPath = NONE`.\n\n\n### Debian \u0026 RPM Considerations \u003ca name=\"debian-rpm-considerations\"/\u003e\n\n#### Install Location \u003ca name=\"debian-rpm-install-location\"/\u003e\nWith Debian and RPM deployments, your application will be installed to the `/opt` directory, rather than `/usr/bin`.\nIf you set `StartCommand`, a tiny bash script will also be installed to `/usr/bin` in order to launch your application.\n\n#### Dependencies \u003ca name=\"debian-rpm-dependencies\"/\u003e\nAlthough publishing a \"self-contained\" dotnet app should ideally produce a truly *self-contained* package, in reality\nit may have additional dependencies which create complexity when building RPM and Debian deployments.\n\nMicrosoft list additional dependencies for these, although note that they may also be distro specific also:\nhttps://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#rpm-dependencies\n\nFrom PupNet version 1.3.0 onward, the pupnet.conf file supports the ability to define such additional dependencies\nusing the `RpmRequires` and `DebRecommends` properties. By default, they are populated with typically expected values\n(below), although these may be subject to change and you should review them for your application.\n\n    RpmRequires = \"\"\"\n        krb5-libs\n        libicu\n        openssl-libs\n        zlib\n    \"\"\"\n\n    DebianRecommends = \"\"\"\n        libc6\n        libgcc1\n        libgcc-s1\n        libgssapi-krb5-2\n        libicu\n        libssl\n        libstdc++6\n        libunwind\n        zlib1g\n    \"\"\"\n\n*You should test RPM and Debian packages against your target distributions.*\n\n\n## BUILDING THE HELLO WORLD DEMO \u003ca name=\"building-the-hello-world-demo\"/\u003e\n\n**Hello World for PupNet** can be built for all package kinds, including `appimage`, `flatpak`, `deb`, `rpm`, `zip`\nand `setup` for Windows.\n\nIf you wish to build and try the demo, clone or download the [PupNet Hello World Project](https://github.com/kuiperzone/PupNet-HelloWorld)\nto your local drive. Ensure that you have installed the prerequisites above, or at least those you wish to use.\n\nIn the terminal, CD into the root of the project directory.\n\n### On Linux \u003ca name=\"on-linux\"/\u003e\n\nAssuming you're on Linux, type:\n\n    pupnet --kind appimage\n\nThis will show the following information and ask for confirmation before building the deployment file.\n\n    ============================================================\n    APPLICATION: HelloWorld 1.0.3 [1]\n    ============================================================\n\n    AppBaseName: HelloWorld\n    AppId: zone.kuiper.helloworld\n    AppVersion: 1.0.3\n    PackageRelease: 1\n    StartCommand: helloworld [Not Supported]\n\n    ============================================================\n    OUTPUT: APPIMAGE\n    ============================================================\n\n    PackageKind: AppImage\n    Runtime: linux-x64\n    Arch: Auto (x86_64)\n    Build: Release\n    OutputName: HelloWorld.x86_64.AppImage\n    OutputDirectory: /mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/bin\n\n    ============================================================\n    DESKTOP: app.desktop\n    ============================================================\n\n    [Desktop Entry]\n    Type=Application\n    Name=Hello World\n    Icon=zone.kuiper.helloworld\n    Comment=A Hello World application\n    Exec=usr/bin/HelloWorld\n    TryExec=usr/bin/HelloWorld\n    NoDisplay=false\n    X-AppImage-Integrate=true\n    Terminal=true\n    Categories=Utility\n    MimeType=\n    Keywords=\n\n    ============================================================\n    CHANGELOG: CHANGES\n    ============================================================\n\n    + Version 1.0.3;2023-05-04\n    - The pupnet.conf file upgraded to version 1.4.0\n    - Added ${APPSTREAM_CHANGELOG_XML} to app.metainfo.xml\n    - Added ${APPSTREAM_DESCRIPTION_XML} to app.metainfo.xml\n    - Other minor corrections and changes\n    - This line is deliberate test of escaping XML \u003c\u003e/\" characters\n\n    + Version 1.0.2;2023-04-18\n    - The pupnet.conf file upgraded to version 1.3.0\n    - Now builds using .NET6, rather than .NET7 (you can change this in csproj file if needed)\n    - Reinstated key-press to exit on all deployments\n\n    + Version 1.0.1;2023-03-26\n    - Programs now asks for key-press only on Windows\n    - Reports version correctly as 1.0.1\n\n    + Version 1.0.0;2023-03-22\n    - Initial release\n    - Reports version as \"3.2.1\". This was intentional at the time by way of demonstration.\n\n    ============================================================\n    BUILD PROJECT: PupNet-HelloWorld\n    ============================================================\n\n    dotnet publish \"/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld\" -r linux-x64 -c Release -p:Version=1.0.3 --self-contained true -p:DebugType=None -p:DebugSymbols=false -o \"/tmp/KuiperZone.PupNet/zone.kuiper.helloworld-linux-x64-Release-AppImage/AppDir/usr/bin\"\n\n    /mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/PostPublish.sh\n\n    ============================================================\n    BUILD PACKAGE: HelloWorld.x86_64.AppImage\n    ============================================================\n\n    /tmp/.mount_PupNetPJRwcO/usr/bin/appimagetool-x86_64.AppImage  --runtime-file=\"/tmp/.mount_PupNetPJRwcO/usr/bin/runtime-x86_64\" \"/tmp/KuiperZone.PupNet/zone.kuiper.helloworld-linux-x64-Release-AppImage/AppDir\" \"/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/bin/HelloWorld.x86_64.AppImage\"\n\n    ============================================================\n    ISSUES\n    ============================================================\n\n    NONE\n\n    Continue? [N/y]:\n\nThis tells us that it will create a file called `HelloWorld.x86_64.AppImage`, under the `Deploy/bin` directory.\nMoreover, it shows the expanded contents of the desktop file, and gives the `dotnet publish` call it will make so\nthat we may ensure that everything looks correct before hitting \"y\".\n\nWe can view more information, including the AppStream metadata contents, by using:\n\n    pupnet --kind appimage --verbose\n\nThe `--verbose` option is useful in other areas too, as we will see below.\n\n### On Windows \u003ca name=\"on-windows\"/\u003e\n\nOn a Windows machine with InnoSetup installed, type:\n\n    pupnet --kind setup\n\nThis will generate the file: `HelloWorld.x64.exe`, which may be launched to install the program.\n\n\u003cp style=\"text-align:left;margin-top:2em;margin-bottom:2em;\"\u003e\n    \u003cimg src=\"Media/Screenie-Setup.png\" style=\"width:50%;max-width:600px;\"/\u003e\n\u003c/p\u003e\n\nOn installation, we find we have a new Program Menu entry, as shown below. We can see that it has also\nincluded a link to our home page, which is optional.\n\n\u003cp style=\"text-align:left;margin-top:2em;margin-bottom:2em;\"\u003e\n    \u003cimg src=\"Media/Screenie-StartMenu.png\" style=\"width:40%;max-width:800px;\"/\u003e\n\u003c/p\u003e\n\nMoreover, there is a \"Command Prompt\" option to launch a dedicated command window, as described above.\n\n\n## CREATING NEW PUPNET PROJECT FILES \u003ca name=\"creating-new-pupnet-project-files\"/\u003e\n\nIf you're starting a new project, you will wish to generate a new `pupnet.conf` file and possibly the associated\ndesktop and AppStream metadata files as well.\n\nTo generate a new `pupnet.conf` file in the current working directory:\n\n    pupnet --new conf\n\nThis will create a new file, `app.pupnet.conf`, which will be a \"light weight\" configuration file lacking the\ndocumentation comments.\n\nTo generate a \"verbose\" file with documentation under a custom name:\n\n    pupnet ProjectName --new conf --verbose\n\nIn fact, we can generate a complete set of files, as follows:\n\n    pupnet ProjectName --new all --verbose\n\nThis creates not only the `pupnet.conf` file, but the `.desktop` and a `.metainfo.xml` template as well.\n\n\n## BACKWARD COMPATIBILITY \u0026 UPGRADING YOUR CONFIGURATION \u003ca name=\"backward-compatibility-upgrading-your-configuration\"/\u003e\nWhere possible, new versions of PupNet will be backward compatible with existing pupnet.conf files. If ever this\nis not the case, it will be explicitly stated.\n\nNew configuration properties may be added and old ones removed or deprecated, however. Where a new PupNet version results\nin changes to configuration properties, you can upgrade an existing pupnet.conf file to the latest format using:\n\n    pupnet [file.pupnet.conf] --upgrade-conf\n\nor\n\n    pupnet [file.pupnet.conf] --upgrade-conf --verbose\n\nYour existing file will \"backed-up\" by appending an \".old\" extension, and a new file written containing new properties\nwith their default values.\n\nUsing the `--verbose` option (above), causes the new file to contain extensive document comments. Without it, the new file\nwill be stripped of comments.\n\nSee also version specific changes below.\n\n### Version 1.4 Changes \u003ca name=\"version-1.4-changes\"/\u003e\n\nPupNet version 1.4.0 introduced new `AppDescription` and `AppChangeFile` configuration properties. If you wish to\nmake use of them, populate `AppDescription` with a longer application description (example below), and point `AppChangeFile`\nto a changelog or README file containing formatted version information.\n\n    AppDescription = \"\"\"\n        Hello World demonstrates all the major features of building distributable packages with PupNet.\n        It can be built for all package kinds, including AppImage, Flatpak, DEB and RPM formats on Linux,\n        and as a Setup file on Windows. It provides an example of using desktop and AppStream metadata files,\n        as well as icons and post-publish scripts.\n\n        On execution, the Hello World program displays command arguments and assembly information. The assembly\n        version confirms that version information, provided in the deployment configuration, was successfully passed\n        through the build system, to the application.\n    \"\"\"\n\n    AppChangeFile = CHANGES.txt\n\nSee above for the required format of `AppChangeFile` content.\n\nAdditionally, you will need to add a couple of macros to your AppStream metadata file, as follows, in order to fully\nmake use of these new features:\n\n    \u003cdescription\u003e\n        ${APPSTREAM_DESCRIPTION_XML}\n    \u003c/description\u003e\n\nHere, you may replace your default description text, but keep any other language text. And:\n\n    \u003creleases\u003e\n        ${APPSTREAM_CHANGELOG_XML}\n    \u003c/releases\u003e\n\nWith this one, you should remove existing version release information if `${APPSTREAM_CHANGELOG_XML}` is going to be\npopulated from `AppChangeFile`.\n\nIn addition to AppStream metadata, the `AppDescription` content is now also used in the construction of RPM and DEB\npackages.\n\n\n## HELP SYSTEM REFERENCE \u003ca name=\"help-system-reference\"/\u003e\n\n### Command Arguments \u003ca name=\"command-arguments\"/\u003e\n\nType `pupnet --help` to display command arguments as expected.\n\n    PupNet Deploy 1.8.0\n    See also: https://github.com/kuiperzone/PupNet-Deploy\n\n    USAGE:\n        pupnet [\u003cfile.pupnet.conf\u003e] [--option-n value-n]\n\n    Example:\n        pupnet app.pupnet.conf -y -r linux-arm64\n\n    Always give .pupnet.conf file first. If .pupnet.conf file is omitted, the default is the one in the\n    working directory.\n\n    Build Options:\n       -k, --kind \u003czip|appimage|deb|rpm|flatpak|setup\u003e\n       Package output kind. If omitted, one is chosen according to the runtime (AppImage on linux).\n       Example: pupnet HelloWorld -k Flatpak\n\n       -r, --runtime \u003clinux-x64|linux-arm64|win-x64...\u003e\n       Dotnet publish runtime identifier. Default: linux-x64.\n       Valid examples include: 'linux-x64', 'linux-arm64' and 'win-x64' etc.\n       See: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog\n\n       -c, --build \u003cRelease|Debug\u003e\n       Optional build target (or 'Configuration' in dotnet terminology).\n       Value should be 'Release' or 'Debug' only. Default: Release.\n\n       -j, --project \u003ccsproj path\u003e\n       Optional path to the .csproj file or directory containing it. Overrides DotnetProjectPath\n       in the conf file.\n\n       -e, --clean\n       Call 'dotnet clean' prior to 'dotnet publish'. Default: false.\n\n       -v, --app-version \u003cversion[release]\u003e\n       Specifies application version-release in form 'version[release]', where value in square\n       brackets is package release. Overrides AppVersionRelease in conf file.\n       Example: 1.2.3[1].\n\n       -p, --property \u003cname=value\u003e\n       Specifies a property to be supplied to dotnet publish command. Do not use for app versioning.\n       Separate multiple values with comma. Example: -p DefineConstants=TRACE,DEBUG\n\n       --arch \u003cvalue\u003e\n       Force target architecture, i.e. as 'x86_64', 'amd64' or 'aarch64' etc. Note that this is\n       not normally necessary as, in most cases, the architecture is defined by the dotnet runtime-id\n       and will be successfully detected automatically. However, in the event of a problem, the value\n       explicitly supplied here will be used to override. It should be provided in the form\n       expected by the underlying package builder (i.e. rpmbuild, appimagetool or InnoSetup etc.).\n\n       -o, --output \u003cfilename\u003e\n       Force package output filename. Normally this is derived from parameters in the configuration.\n       This value will be used to override. Example: -o AppName.AppImage\n\n       --verbose\n       Indicates verbose output when building. It is used also with --new option.\n\n       -u, --run\n       Performs a test run of the application after successful build (where supported).\n\n       -y, --skip-yes\n       Skips confirmation prompts (assumes yes).\n\n    Other Options:\n\n       -n, --new \u003cconf|desktop|meta|all\u003e [--verbose] [--skip-yes]\n       Creates a new empty conf file or associated file (i.e. desktop of metadata) for a new project.\n       A base file name may optionally be given. If --verbose is used, a configuration file with\n       documentation comments is generated. Use 'all' to generate a full set of configuration assets.\n       Example: pupnet HelloWorld -n all --verbose\n\n       --upgrade-conf [--verbose] [--skip-yes]\n       Upgrades supplied .pupnet.conf file to latest version parameters. For example, if the\n       conf file was created with program version 1.1 and new parameters where added in version\n       1.2, this command will upgrade the file by adding new parameters with default values.\n       If --verbose is used, a configuration file with documentation comments is generated.\n       Example: pupnet file.pupnet.conf --upgrade-conf --verbose\n\n       -h, --help \u003cargs|macro|conf\u003e\n       Show help information. Optional value specifies what kind of information to display.\n       Default is 'args'. Example: pupnet -h macro\n\n       --version\n       Show version and associated information.\n\n### Macro Reference \u003ca name=\"macro-reference\"/\u003e\n\nType `pupnet --help macro` to see supported macro reference information:\n\n    Macro variables may be used with the following configuration items:\n    DesktopFile, MetaFile, DotnetPublishArgs, DotnetPostPublish and DotnetPostPublishOnWindows.\n\n    IMPORTANT: Always use the ${MACRO_NAME} form, and not $MACRO_NAME.\n\n    ** ${APP_BASE_NAME} **\n    Gives the AppBaseName value from the pupnet.conf file\n    Example: ${APP_BASE_NAME} = HelloWorld\n\n    ** ${APP_FRIENDLY_NAME} **\n    Gives the AppFriendlyName value from the pupnet.conf file\n    Example: ${APP_FRIENDLY_NAME} = Hello World\n\n    ** ${APP_ID} **\n    Gives the AppId value from the pupnet.conf file\n    Example: ${APP_ID} = net.example.helloworld\n\n    ** ${APP_LICENSE_ID} **\n    Gives the AppLicenseId value from the pupnet.conf file\n    Example: ${APP_LICENSE_ID} = LicenseRef-Proprietary\n\n    ** ${APP_SHORT_SUMMARY} **\n    Gives the AppShortSummary value from the pupnet.conf file\n    Example: ${APP_SHORT_SUMMARY} = A HelloWorld application\n\n    ** ${APP_VERSION} **\n    Application version, excluding package-release extension\n    Example: ${APP_VERSION} = 1.0.0\n\n    ** ${APPSTREAM_CHANGELOG_XML} **\n    AppStream changelog XML content (use within the \u003creleases\u003e element only)\n\n    ** ${APPSTREAM_DESCRIPTION_XML} **\n    AppStream application description XML (use within the \u003cdescription\u003e element only)\n\n    ** ${BUILD_APP_BIN} **\n    Application build directory (i.e. the output of dotnet publish or C++ make)\n    Example: ${BUILD_APP_BIN} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/bin\n\n    ** ${BUILD_ARCH} **\n    Build architecture: x64, arm64, arm or x86 (may differ from package output notation)\n    Example: ${BUILD_ARCH} = x64\n\n    ** ${BUILD_DATE} **\n    Build date in 'yyyy-MM-dd' format\n    Example: ${BUILD_DATE} = 2023-05-05\n\n    ** ${BUILD_ROOT} **\n    Root of the temporary application build directory\n    Example: ${BUILD_ROOT} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir\n\n    ** ${BUILD_SHARE} **\n    Linux 'usr/share' build directory under BuildRoot (empty for some deployments)\n    Example: ${BUILD_SHARE} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/share\n\n    ** ${BUILD_TARGET} **\n    Release or Debug (Release unless explicitly specified)\n    Example: ${BUILD_TARGET} = Release\n\n    ** ${BUILD_YEAR} **\n    Build year as 'yyyy'\n    Example: ${BUILD_YEAR} = 2023\n\n    ** ${DEPLOY_KIND} **\n    Deployment output kind: appimage, flatpak, rpm, deb, setup, zip\n    Example: ${DEPLOY_KIND} = appimage\n\n    ** ${DESKTOP_INTEGRATE} **\n    Gives the logical not of ${DESKTOP_NODISPLAY}\n    Example: ${DESKTOP_INTEGRATE} = true\n\n    ** ${DESKTOP_NODISPLAY} **\n    Gives the DesktopNoDisplay value from the pupnet.conf file\n    Example: ${DESKTOP_NODISPLAY} = false\n\n    ** ${DESKTOP_TERMINAL} **\n    Gives the DesktopTerminal value from the pupnet.conf file\n    Example: ${DESKTOP_TERMINAL} = true\n\n    ** ${DOTNET_RUNTIME} **\n    Dotnet publish runtime identifier used (RID)\n    Example: ${DOTNET_RUNTIME} = linux-x64\n\n    ** ${INSTALL_BIN} **\n    Path to application directory on target system (not the build system)\n    Example: ${INSTALL_BIN} = usr/bin\n\n    ** ${INSTALL_EXEC} **\n    Path to application executable on target system (not the build system)\n    Example: ${INSTALL_EXEC} = usr/bin/HelloWorld\n\n    ** ${LOCAL_DIRECTORY} **\n    The pupnet.conf file directory\n\n    ** ${PACKAGE_RELEASE} **\n    Package release version\n    Example: ${PACKAGE_RELEASE} = 1\n\n    ** ${PRIME_CATEGORY} **\n    Gives the PrimeCategory value from the pupnet.conf file\n    Example: ${PRIME_CATEGORY} = Utility\n\n    ** ${PUBLISHER_COPYRIGHT} **\n    Gives the PublisherCopyright value from the pupnet.conf file\n    Example: ${PUBLISHER_COPYRIGHT} = Copyright (C) Acme Ltd 2023\n\n    ** ${PUBLISHER_EMAIL} **\n    Gives the PublisherEmail value from the pupnet.conf file\n    Example: ${PUBLISHER_EMAIL} = contact@example.net\n\n    ** ${PUBLISHER_LINK_NAME} **\n    Gives the PublisherLinkName value from the pupnet.conf file\n    Example: ${PUBLISHER_LINK_NAME} = Project Page\n\n    ** ${PUBLISHER_LINK_URL} **\n    Gives the PublisherLinkUrl value from the pupnet.conf file\n    Example: ${PUBLISHER_LINK_URL} = https://example.net\n\n    ** ${PUBLISHER_NAME} **\n    Gives the PublisherName value from the pupnet.conf file\n    Example: ${PUBLISHER_NAME} = The Hello World Team\n\n### Configuration Reference \u003ca name=\"configuration-reference\"/\u003e\n\nType `pupnet --help conf` to see supported configuration reference information:\n\n    ########################################\n    # APP PREAMBLE\n    ########################################\n\n    ** AppBaseName **\n    Mandatory application base name. This MUST BE the base name of the main executable file. It should NOT\n    include any directory part or extension, i.e. do not append '.exe' or '.dll'. It should not contain\n    spaces or invalid filename characters.\n    Example: AppBaseName = HelloWorld\n\n    ** AppFriendlyName **\n    Mandatory application friendly name.\n    Example: AppFriendlyName = Hello World\n\n    ** AppId **\n    Mandatory application ID in reverse DNS form. This should stay constant for lifetime of the software.\n    Example: AppId = net.example.helloworld\n\n    ** AppVersionRelease **\n    Mandatory application version and package release of form: 'VERSION[RELEASE]'. Use optional square\n    brackets to denote package release, i.e. '1.2.3[1]'. Release refers to a change to the deployment\n    package, rather the application. If release part is absent (i.e. '1.2.3'), the release value defaults\n    to '1'. Note that the version-release value given here may be overridden from the command line.\n    Example: AppVersionRelease = 1.0.0[1]\n\n    ** AppShortSummary **\n    Mandatory single line application summary text in default (English) language.\n    Example: AppShortSummary = A HelloWorld application\n\n    ** AppDescription **\n    Multi-line (surround with triple \"\"\" quotes) application description which provides longer explanation\n    than AppShortSummary in default language. Optional but it is recommended to specify this. Text\n    separated by an empty line will be treated as separate paragraphs. Avoid complex formatting, and do not\n    use HTML or markdown, other than list items begining with \"* \", \"+ \" or \"- \". This content is\n    used by package builders where supported, including RPM and DEB, and is used to populate the\n    ${APPSTREAM_DESCRIPTION_XML} element used within AppStream metadata.\n\n    ** AppLicenseId **\n    Mandatory application license ID. This should be one of the recognized SPDX license\n    identifiers, such as: 'MIT', 'GPL-3.0-or-later' or 'Apache-2.0'. For a proprietary or\n    custom license, use 'LicenseRef-Proprietary' or 'LicenseRef-LICENSE'.\n    Example: AppLicenseId = LicenseRef-Proprietary\n\n    ** AppLicenseFile **\n    Optional path to application copyright/license text file. If provided, it will be packaged with the\n    application and used with package builders where supported.\n    Example: AppLicenseFile = LICENSE.txt\n\n    ** AppChangeFile **\n    Optional path to application changelog file. IMPORTANT. If given, this file should contain version\n    information in a predefined format. Namely, it should contain one or more version headings of form:\n    '+ VERSION;DATE', under which are to be listed change items of form: '- Change description'. Formatted\n    information will be parsed and used to expand the ${APPSTREAM_CHANGELOG_XML} macro used\n    for AppStream metadata (superfluous text is ignored, so the file may also contain README information).\n    The given file will also be packaged with the application verbatim. See: https://github.com/kuiperzone/PupNet-Deploy.\n    Example: AppChangeFile = CHANGELOG.txt\n\n    ########################################\n    # PUBLISHER\n    ########################################\n\n    ** PublisherName **\n    Mandatory publisher, group or creator.\n    Example: PublisherName = The Hello World Team\n\n    ** PublisherCopyright **\n    Optional copyright statement.\n    Example: PublisherCopyright = Copyright (C) Acme Ltd 2024\n\n    ** PublisherLinkName **\n    Optional publisher or application web-link name. Note that Windows Setup packages\n    require both PublisherLinkName and PublisherLinkUrl in order to include the link as\n    an item in program menu entries. Do not modify name, as may leave old entries in updated installations.\n    Example: PublisherLinkName = Project Page\n\n    ** PublisherLinkUrl **\n    Publisher or application web-link URL. Although optional, it should be considered mandatory if using\n    MetaFile\n    Example: PublisherLinkUrl = https://example.net\n\n    ** PublisherEmail **\n    Publisher or maintainer email contact. Although optional, some package builders (i.e. DEB) require it\n    and may warn or fail unless provided.\n    Example: PublisherEmail = contact@example.net\n\n    ########################################\n    # DESKTOP INTEGRATION\n    ########################################\n\n    ** DesktopNoDisplay **\n    Boolean (true or false) which indicates whether the application is hidden on the desktop. It is used to\n    populate the 'NoDisplay' field of the .desktop file. The default is false. Setting to true will also\n    cause the main application start menu entry to be omitted for Windows Setup.\n    Example: DesktopNoDisplay = false\n\n    ** DesktopTerminal **\n    Boolean (true or false) which indicates whether the application runs in the terminal, rather than\n    providing a GUI. It is used to populate the 'Terminal' field of the .desktop file.\n    Example: DesktopTerminal = true\n\n    ** DesktopFile **\n    Optional path to a Linux desktop file. If empty (default), one will be generated automatically from\n    the information in this file. Supplying a custom file, however, allows for mime-types and\n    internationalisation. If supplied, the file MUST contain the line: 'Exec=${INSTALL_EXEC}'\n    in order to use the correct install location. Other macros may be used to help automate the content.\n    Note. PupNet Deploy can generate you a desktop file. Use --help and 'pupnet --help macro' for reference.\n    See: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html\n    Example: DesktopFile = Deploy/app.desktop\n\n    ** StartCommand **\n    Optional command name to start the application from the terminal. If, for example, AppBaseName is\n    'Zone.Kuiper.HelloWorld', the value here may be set to a simpler and/or lower-case variant such as\n    'helloworld'. It must not contain spaces or invalid filename characters. Do not add any extension such\n    as '.exe'. If empty, the application will not be in the path and cannot be started from the command line.\n    For Windows Setup packages, see also SetupCommandPrompt. StartCommand is not\n    supported for all packages kinds (i.e. Flatpak). Default is empty (none).\n    Example: StartCommand = helloworld\n\n    ** PrimeCategory **\n    Optional category for the application. The value should be one of the recognized Freedesktop top-level\n    categories, such as: Audio, Development, Game, Office, Utility etc. Only a single value should be\n    provided here which will be used, where supported, to populate metadata. The default is empty.\n    See: https://specifications.freedesktop.org/menu-spec/latest/apa.html\n    Example: PrimeCategory = Utility\n\n    ** MetaFile **\n    Path to AppStream metadata file. It is optional, but recommended as it is used by software centers.\n    Note. The contents of the files may use macro variables. Use 'pupnet --help macro' for reference.\n    See: https://docs.appimage.org/packaging-guide/optional/appstream.html\n    Example: MetaFile = Deploy/app.metainfo.xml\n\n    ** IconFiles **\n    Optional icon file paths. The value may include multiple filenames separated with semicolon or given\n    in multi-line form. Valid types are SVG, PNG and ICO (ICO ignored on Linux). Note that the inclusion\n    of a scalable SVG is preferable on Linux, whereas PNGs must be one of the standard sizes and MUST\n    include the size in the filename in the form: name.32x32.png' or 'name.32.png'.\n    Example: IconFiles = \"\"\"\n        app.ico\n        app.svg\n        app.16x16.png\n        app.32x32.png\n        app.64x64.png\n    \"\"\"\n\n    ########################################\n    # DOTNET PUBLISH\n    ########################################\n\n    ** DotnetProjectPath **\n    Optional path relative to this file in which to find the dotnet project (.csproj) file, or the\n    directory containing it. If empty (default), a single project file is expected under the same\n    directory as this file. IMPORTANT. If set to 'NONE', dotnet publish is disabled\n    (i.e. not called). Instead, only DotnetPostPublish is called.\n    Example: DotnetProjectPath = Source\n\n    ** DotnetPublishArgs **\n    Optional arguments supplied to 'dotnet publish'. Do NOT include '-r' (runtime), or '-c' (configuration)\n    here as they will be added according to command line arguments. Typically you want as a minimum:\n    '-p:Version=${APP_VERSION} --self-contained true'. Additional useful arguments include:\n    '-p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishReadyToRun=true\n    -p:PublishTrimmed=true -p:TrimMode=link'. Note. This value may use macro variables. Use 'pupnet --help macro'\n    for reference. See: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish\n    Example: DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false\n\n    ** DotnetPostPublish **\n    Post-publish (or standalone build) command on Linux (ignored on Windows). It is called after dotnet\n    publish, but before the final output is built. This could, for example, be a script which copies\n    additional files into the build directory given by ${BUILD_APP_BIN}. The working directory will be\n    the location of this file. This value is optional, but becomes mandatory if DotnetProjectPath equals\n    'NONE'. Note. This value may use macro variables. Additionally, scripts may use these as environment\n    variables. Use 'pupnet --help macro' for reference.\n    Example: DotnetPostPublish = post-publish.sh\n\n    ** DotnetPostPublishOnWindows **\n    Post-publish (or standalone build) command on Windows (ignored on Linux). This should perform\n    the equivalent operation, as required, as DotnetPostPublish, but using DOS commands and batch\n    scripts. Multiple commands may be specified, separated by semicolon or given in multi-line form.\n    Note. This value may use macro variables. Additionally, scripts may use these as environment\n    variables. Use 'pupnet --help macro' for reference.\n    Example: DotnetPostPublishOnWindows = post-publish.bat\n\n    ########################################\n    # PACKAGE OUTPUT\n    ########################################\n\n    ** PackageName **\n    Optional package name (excludes version etc.). If empty, defaults to AppBaseName. However, it is\n    used not only to specify the base output filename, but to identify the application in DEB and RPM\n    packages. You may wish, therefore, to ensure that the value represents a unique name. Naming\n    requirements are strict and must contain only alpha-numeric and '-', '+' and '.' characters.\n    Example: PackageName = HelloWorld\n\n    ** OutputDirectory **\n    Output directory, or subdirectory relative to this file. It will be created if it does not exist and\n    will contain the final deploy output files. If empty, it defaults to the location of this file.\n    Example: OutputDirectory = Deploy/OUT\n\n    ########################################\n    # APPIMAGE OPTIONS\n    ########################################\n\n    ** AppImageArgs **\n    Additional arguments for use with appimagetool. Useful for signing. Default is empty.\n    Example: AppImageArgs = --sign\n\n    ** AppImageVersionOutput **\n    Boolean (true or false) which sets whether to include the application version in the AppImage filename,\n    i.e. 'HelloWorld-1.2.3-x86_64.AppImage'. Default is false. It is ignored if the output filename is\n    specified at command line.\n    Example: AppImageVersionOutput = false\n\n    ########################################\n    # FLATPAK OPTIONS\n    ########################################\n\n    ** FlatpakPlatformRuntime **\n    The runtime platform. Invariably for .NET (inc. Avalonia), this should be 'org.freedesktop.Platform'.\n    Refer: https://docs.flatpak.org/en/latest/available-runtimes.html\n    Example: FlatpakPlatformRuntime = org.freedesktop.Platform\n\n    ** FlatpakPlatformSdk **\n    The platform SDK. Invariably for .NET (inc. Avalonia applications) this should be 'org.freedesktop.Sdk'.\n    The SDK must be installed on the build system.\n    Example: FlatpakPlatformSdk = org.freedesktop.Sdk\n\n    ** FlatpakPlatformVersion **\n    The platform runtime version. The latest available version may change periodically.\n    Refer to Flatpak documentation.\n    Example: FlatpakPlatformVersion = 23.08\n\n    ** FlatpakFinishArgs **\n    Flatpak manifest 'finish-args' sandbox permissions. Optional, but if empty, the application will have\n    extremely limited access to the host environment. This option may be used to grant required\n    application permissions. Values here should be prefixed with '--' and separated by semicolon or given\n    in multi-line form. Refer: https://docs.flatpak.org/en/latest/sandbox-permissions.html\n    Example: FlatpakFinishArgs = \"\"\"\n        --socket=wayland\n        --socket=x11\n        --filesystem=host\n        --share=network\n    \"\"\"\n\n    ** FlatpakBuilderArgs **\n    Additional arguments for use with flatpak-builder. Useful for signing. Default is empty.\n    See flatpak-builder --help.\n    Example: FlatpakBuilderArgs = --gpg-keys=FILE\n\n    ########################################\n    # RPM OPTIONS\n    ########################################\n\n    ** RpmAutoReq **\n    Boolean (true or false) which specifies whether to build the RPM package with 'AutoReq' equal to yes or no.\n    For dotnet application, the value should typically be false, but see RpmRequires below.\n    Refer: https://rpm-software-management.github.io/rpm/manual/spec.html\n    Example: RpmAutoReq = false\n\n    ** RpmAutoProv **\n    Boolean (true or false) which specifies whether to build the RPM package with 'AutoProv' equal to yes or no.\n    Refer: https://rpm-software-management.github.io/rpm/manual/spec.html\n    Example: RpmAutoProv = true\n\n    ** RpmRequires **\n    Optional list of RPM dependencies. The list may include multiple values separated with semicolon or given\n    in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)\n    Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.\n    Default values are recommended for use with dotnet and RPM packages at the time of writing.\n    For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-rhel#dependencies\n    Example: RpmRequires = \"\"\"\n        krb5-libs\n        libicu\n        openssl-libs\n        zlib\n    \"\"\"\n\n    ########################################\n    # DEBIAN OPTIONS\n    ########################################\n\n    ** DebianRecommends **\n    Optional list of Debian dependencies. The list may include multiple values separated with semicolon or given\n    in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)\n    Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.\n    Default values are recommended for use with dotnet and Debian packages at the time of writing.\n    For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#dependencies\n    Example: DebianRecommends = \"\"\"\n        libc6\n        libgcc1\n        libgcc-s1\n        libgssapi-krb5-2\n        libicu\n        libssl\n        libstdc++6\n        libunwind\n        zlib1g\n    \"\"\"\n\n    ########################################\n    # WINDOWS SETUP OPTIONS\n    ########################################\n\n    ** SetupGroupName **\n    Optional application group name used as the Start Menu folder and install directory under Program Files.\n    Specifically, it is used to define the InnoSetup DefaultGroupName and DefaultDirName parameters.\n    If empty (default), suitable values are used based on your application.\n    See: https://jrsoftware.org/ishelp/index.php?topic=setup_defaultgroupname\n    Example: SetupGroupName = HelloWorld Demo\n\n    ** SetupAdminInstall **\n    Boolean (true or false) which specifies whether the application is to be installed in administrative\n    mode, or per-user. Default is false. See: https://jrsoftware.org/ishelp/topic_admininstallmode.htm\n    Example: SetupAdminInstall = false\n\n    ** SetupCommandPrompt **\n    Optional command prompt title. The Windows installer will NOT add your application to the path. However,\n    if your package contains a command-line utility, setting this value will ensure that a 'Command Prompt'\n    program menu entry is added (with this title) which, when launched, will open a dedicated command\n    window with your application directory in its path. Default is empty. See also StartCommand.\n    Example: SetupCommandPrompt = Command Prompt\n\n    ** SetupMinWindowsVersion **\n    Mandatory value which specifies minimum version of Windows that your software runs on. Windows 8 = 6.2,\n    Windows 10/11 = 10. Default: 10. See: https://jrsoftware.org/ishelp/topic_setup_minversion.htm\n    Example: SetupMinWindowsVersion = 10\n\n    ** SetupSignTool **\n    Optional name and parameters of the Sign Tool to be used to digitally sign: the installer,\n    uninstaller, and contained exe and dll files. If empty, files will not be signed.\n    See: https://jrsoftware.org/ishelp/topic_setup_signtool.htm\n\n    ** SetupSuffixOutput **\n    Optional suffix for the installer output filename. The default is empty, but you may wish set it to:\n    'Setup' or similar. This, for example, will output a file of name: HelloWorldSetup-x86_64.exe\n    Ignored if the output filename is specified at command line.\n    Example: SetupSuffixOutput = Setup\n\n    ** SetupVersionOutput **\n    Boolean (true or false) which sets whether to include the application version in the setup filename,\n    i.e. 'HelloWorld-1.2.3-x86_64.exe'. Default is false. Ignored if the output filename is specified\n    at command line.\n    Example: SetupVersionOutput = true\n\n    ** SetupUninstallScript **\n    Optional name of a script to run before uninstall.\n    This is script file relative to the directory of the application and must have a default file association.\n    This binds to the `[UninstallRun]` section of InnoSetup.\n    From this script, you may want to run your application, which is very useful if\n    your application has non-static configurable storage locations for data.\n\n    Example: uninstall.bat\n\n## FAQs \u0026 GOTCHAS \u003ca name=\"faqs-gotchas\"/\u003e\n\n### NETSDK1194: The \"--output\" option isn't supported \u003ca name=\"NETSDK1194\"/\u003e\n\nFrom .NET7 ownward, the `dotnet publish` no longer accepts a `.sln` file or directory containing one as input. It's\ncurrent behaviour for .NET8.0 is to warn rather than fail but this may change in a future .NET release.\n\nFor your pupnet.conf files, the solution is to either place the conf file in the same directory as your `.csproj`\nfile, or specify the `.csproj` file location using the `DotnetProjectPath` parameter.\n\nSee also: [Solution-level --output option no longer valid for build-related commands](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/7.0/solution-level-output-no-longer-valid).\n\n### Virtual Box \u0026 Symlinks \u003ca name=\"virtual-box-symlinks\"/\u003e\n\nIf you are using VirtualBox with your project, note that symbolic links are disabled within shared folders by VirtualBox\nitself, and this may cause problems with generating AppImages. To overcome this, copy your entire project to your home\ndirectory in the virtual machine. Alternatively, it is possible to enable shared-folder symlinks in VirtualBox.\n\n### Package Naming is not Consistent \u003ca name=\"package-naming-is-not-consistent\"/\u003e\n\nYou may notice that PupNet outputs differences in package naming styles. For example:\n\n    PupNet-Deploy.x86_64.AppImage\n    pupnet-deploy_0.0.1-1_amd64.deb\n\nPupNet follows the naming conventions used with the respective packages. This includes, for example, different CPU\narchitecture naming conventions. With some package naming styles, it is normal to include the version in the filename,\nbut not in others.\n\n### Package Cannot be Removed using Gnome Software Center \u003ca name=\"package-cannot-be-removed-using-gnome-software-center\"/\u003e\n\nIf you install your Flatpak, RPM or DEB package directly from a local file (rather than a repository) they will,\ncourtesy of your AppStream metadata, show up in the Gnome Software Center, as expected. However, you may find that they\ncannot be launched or removed using the GUI.\n\nInstead, they must be removed from the command line, like so:\n\n    sudo flatpak uninstall zone.kuiper.helloworld\n\nor:\n\n    sudo dnf remove helloworld\n\nor:\n\n    sudo apt remove helloworld\n\nThis is not an issue with PupNet or AppStream metadata. Rather, having been installed from file, the Gnome Software Center\nlacks certain other metadata it expects had the package originated from a repository.\nSee [here for information](https://discourse.gnome.org/t/gnome-software-open-and-uninstall-button-not-working-for-app/14338/7).\n\n\n## ADDITIONAL INFORMATION \u003ca name=\"additional-information\"/\u003e\n\n### Brief Discussion on Past \u0026 Future \u003ca name=\"brief-discussion-on-past-future\"/\u003e\n\nPupNet Deploy began life as a bash script called \"*Publish-AppImage for .NET*\":\n\n\u003cp style=\"text-align:left;\"\u003e\n    \u003ca href=\"https://github.com/kuiperzone/Publish-AppImage\"\u003e\n        \u003cimg title=\"Publish-AppImage\" alt=\"Publish-AppImage\" src=\"Media/Publish-AppImage.png\" style=\"width:40%;max-width:250px;\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nAt the time, I was excited by Flatpak and it was my original intention to add Flatpak support to *Publish-AppImage*. However,\nit was difficult to handle the increased complexity in a bash script, so I re-wrote everything as a C# application and\n*PupNet Deploy* is the result.\n\nIn the process, however, I had cause to reflect on certain things, including the fact that the\n[security model of Flatpak is broken IMHO](https://ludocode.com/blog/flatpak-is-not-the-future). This came about\nbecause I intended to use Flatpak to deploy my other [application project](https://github.com/kuiperzone/AvantGarde),\nbut found that there are several important scenarios which Flatpak cannot support, including the deployment of development\ntools. Regardless, I thought it useful for developers to be able ship software in formats convenient for users,\nand recognise that Flatpak is a popular packaging technology. However, I felt that RPM and Debian formats should be added\nin order to provide alternatives where Flatpak is unsuitable.\n\n### Notes on Extending PupNet \u003ca name=\"notes-on-extending-pupnet\"/\u003e\n\nAnyone wishing to extend PupNet, should study how the existing `RpmBuilder`, `FlatpakBuilder` and Windows `SetupBuilder`\nclasses override and extend the behaviour of the `PackageBuilder` base class. The `PackageBuilder` base class is Linux\ncentric, with unused directories and properties being set to null and ignored for the Windows Setup and Zip builders.\n\nMoreover, a new enum value would need to be added to the `PackageKind` type. It would help to do a search on\nexisting `PackageKind` values, and add the new type behaviour to switch statements wherever encountered, including\nthe `BuilderFactory` class.\n\nPlease do feel free to post questions to the Github Discussion area. Where possible, I will be happy to respond.\n\n### An Application which uses PupNet Deploy \u003ca name=\"an-application-which-uses-pupnet-deploy\"/\u003e\n\n[AvantGarde](https://github.com/kuiperzone/AvantGarde) is a cross-platform XAML previewer for the C# Avalonia Framework,\nand the primary previewer solution when developing on Linux.\n\n\u003cp style=\"text-align:left;\"\u003e\n    \u003ca href=\"https://github.com/kuiperzone/AvantGarde\"\u003e\n        \u003cimg title=\"AvantGarde Screenshot\" alt=\"AvantGarde Screenshot\" src=\"Media/Screenie-AvantGarde.png\" style=\"width:50%;max-width:500px;\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\n### Copyright \u0026 License \u003ca name=\"copyright-license\"/\u003e\n\nCopyright (C) Andy Thomas, 2023. Website: https://kuiper.zone\n\nPupNet is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free Software\nFoundation, either version 3 of the License, or (at your option) any later version.\n\nPupNet is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License along\nwith PupNet. If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n\n#### Embedded Assets ####\nPupNet embeds \"appimagetool\", from the \"AppImageKit\".\nAppImageKit is Copyright (C) 2004-20 Simon Peter:\nhttps://github.com/AppImage/AppImageKit\n\n#### Non-code Assets ####\nImages and non-code assets are not subject to AGPL.\n\nProject Logo: Copyright (C) Andy Thomas, 2023.\n\nAll other copyright and trademarks are property of respective owners.\n\nIf you like this project, don't forget to like and share.\n","funding_links":[],"categories":["Tooling","AppImage developer tools"],"sub_categories":["Web Browsers","Deployment tools for .NET Core (Mono) applications"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuiperzone%2FPupNet-Deploy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkuiperzone%2FPupNet-Deploy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkuiperzone%2FPupNet-Deploy/lists"}