Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kuiperzone/PupNet-Deploy

PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.
https://github.com/kuiperzone/PupNet-Deploy

appimage csharp debian deploy dotnet flatpak installation-automation linux package rpm setup windows

Last synced: about 1 month ago
JSON representation

PupNet Deploy is a cross-platform deployment utility which packages your .NET project as a ready-to-ship installation file in a single step.

Awesome Lists containing this project

README

        



# PupNet Deploy - Publish & Package for .NET #

**PupNet Deploy** is a cross-platform deployment utility which packages your .NET project as a ready-to-ship
installation file in a single step.

## Announcement 2024 ##
I'd like to take a moment to thank recent contributors, but also say that I'm not in position to maintain this
project on a timely basis. That doesn't mean that it's abandoned and I do, in fact, plan on making updates in the
future, especially around AppImage. I've just got other commitments at the moment which take up a lot of my time.
Thank you. Kuiper

## CONTENTS ##

* [INTRODUCTION](#introduction)
* [General Principles](#general-principles)

* [INSTALL & PREREQUISITES](#install-prerequisites)
* [AppImage Out of the Box](#appimage-out-of-the-box)
* [Flatpaks on Linux](#flatpak-on-linux)
* [Debian Packages on Linux](#debian-packages-on-linux)
* [RPM Packages on Linux](#rpm-packages-on-linux)
* [Setup Files on Windows](#setup-files-on-windows)

* [PUPNET CONFIGURATION](#pupnet-configuration)
* [Desktop File](#desktop-file)
* [AppStream Metadata](#appstream-metadata)
* [Icons](#icons)
* [Dotnet Project Path](#dotnet-project-path)
* [Dotnet Publish Arguments](#dotnet-publish-arguments)
* [Application Versioning & Changelog](#application-versioning-changelog)
* [Application Version (AppVersionRelease)](#application-version)
* [Changelog (AppChangeFile)](#changelog)
* [Terminal vs GUI Applications](#terminal-vs-gui-applications)
* [GUI Application](#gui-application)
* [Terminal Application](#terminal-application")
* [Custom Post-Publish Operations](#custom-post-publish-operations)
* [Non-Dotnet Projects](#non-dotnet-projects)
* [Debian & RPM Considerations](#debian-rpm-considerations)
* [Install Location](#debian-rpm-install-location)
* [Dependencies](#debian-rpm-dependencies)

* [BUILDING THE HELLO WORLD DEMO](#building-the-hello-world-demo)
* [On Linux](#on-linux)
* [On Windows](#on-windows)

* [CREATING NEW PUPNET PROJECT FILES](#creating-new-pupnet-project-files)

* [BACKWARD COMPATIBILITY & UPGRADING YOUR CONFIGURATION](#backward-compatibility-upgrading-your-configuration)
* [Version 1.4 Changes](#version-1.4-changes)

* [HELP SYSTEM REFERENCE](#help-system-reference)
* [Command Arguments](#command-arguments)
* [Macro Reference](#macro-reference)
* [Configuration Reference](#configuration-reference)

* [FAQs & GOTCHAS](#faqs-gotchas)
* [NETSDK1194: The "--output" option isn't supported](#NETSDK1194)
* [Virtual Box & Symlinks](#virtual-box-symlinks)
* [Package Naming is not Consistent](#package-naming-is-not-consistent)
* [Package Cannot be Removed using Gnome Software Center](#package-cannot-be-removed-using-gnome-software-center)

* [ADDITIONAL INFORMATION](#additional-information)
* [Brief Discussion on Past & Future](#brief-discussion-on-past-future)
* [Notes on Extending PupNet](#notes-on-extending-pupnet)
* [An Application which uses PupNet Deploy](#an-application-which-uses-pupnet-deploy)
* [Copyright & License](#copyright-license)

## INTRODUCTION

It has been possible to cross-compile console C# applications for sometime now. More recently, the cross-platform
[Avalonia](https://github.com/AvaloniaUI/Avalonia) replacement for WPF allows fully-featured GUI applications to target
a range of platforms, including: Linux, Windows, MacOS and Android.

Now, **PupNet Deploy** allows you to ship your dotnet application as:

* AppImage for Linux
* Setup File for Windows
* Flatpak for Linux
* Debian Binary Package
* RPM Binary Package
* Plain old Zip

To create an installation file, you fill out the parameters in a simple `pupnet.conf` file and, from within your project,
run a command like so:

pupnet --runtime linux-x64 --kind appimage

In this case, PupNet calls `dotnet publish` on your project and generates a distributable [AppImage](https://github.com/AppImage/AppImageKit)
file fo use on Linux systems. Additionally, you may optionally provide `.desktop` and AppStream metadata files.
There is no need to write complex build-specific manifests, RPM spec or Debian control files. You need only supply your
deployment configuration once as a single `pupnet.conf` file, and PupNet takes care of the underlying build-specific tasks.

Likewise, to package the same project for Windows:

pupnet -r win-x64 -k setup

PupNet has good support for internationalization, desktop icons, publisher metadata and custom build operations.
Although developed for .NET, it is also possible to use it to deploy C++ and other kinds of applications.

The output of PupNet is a distributable file, such as an AppImage, flatpak or Windows Setup.exe file -- it does
not auto-submit your project to repositories. Note also that, in order to build a Linux deployment, the build system
must be a Linux box and, likewise to build a Windows Setup file, a Windows system (virtual machines are handy).

However, it is possible to build a Debian package on an RPM machine, and viceversa.

### General Principles

#### Single App per Install Package ####
It is assumed that you are building a deployment package containing a single application. AppImages also work this way
and, from .NET7 onward, it is no longer possible to `publish` a dotnet solution containing multiple projects.

This may be something investigated in the future but, for the moment, PupNet is not suitable for deploying a suit of
applications as a single package.

#### Read-only Access to Installation ####
As a general principle when deploying your software, it should be assumed that your application has read-only access to
its installation folder. Your application should use the `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData`
location or other suitable special folder to write data.

## INSTALL & PREREQUISITES

To install as a dotnet tool:

dotnet tool install -g KuiperZone.PupNet

Currently, the "PupNet tool" targets .NET8 LTS (this does not restrict the dotnet version of your own projects).
The last version of PupNet built against .NET6 was 1.7.1.

Alternatively, for self-contained installers:

**[DOWNLOAD & INSTALL](https://github.com/kuiperzone/PupNet/releases/latest)**

If you are using the AppImage deployment of PupNet, add it to your path and consider renaming the AppImage file to `pupnet`
so that the instructions below will match your system.

### AppImage Out of the Box
Out of the box, PupNet can create AppImages on Linux and Zip files on all platforms. **There is no need to install any
AppImage tools therefore.** In order to build other deployments, however, you must first install the appropriate
third-party builder tool against which PupNet will call.

### Flatpaks on Linux

PupNet requires `flatpak` and `flatpak-builder`. It will also be necessary to install a flatpak platform SDK and runtime.
As appropriate, use:

sudo dnf install flatpak flatpak-builder

or:

sudo apt install flatpak flatpak-builder

And then use flatpak to install:

sudo flatpak install flathub org.freedesktop.Platform//23.08 org.freedesktop.Sdk//23.08

Here, the version number (23.08) was the latest at the time of writing, but will be subject to update.
See [Flatpak Available Runtimes](https://docs.flatpak.org/en/latest/available-runtimes.html).

### Debian Packages on Linux

PupNet requires `dpkg-deb`. So, as appropriate:

sudo apt install dpkg

or:

sudo dnf install dpkg

It is possible to build Debian packages using `dpkg-deb` on an RPM based system. However, it is not recommended to
test install a Debian package on an RPM machine (use a virtual machines to test it).

### RPM Packages on Linux

PupNet requires `rpmbuild`. As appropriate:

sudo dnf install rpmdevtools

or:

sudo apt install rpm

It is possible to build RPM packages using `rpmbuild` on a Debian system. However, as above, it is not recommended to
test install an RPM package on a Debian machine (use a virtual machines to test it).

### Setup Files on Windows

PupNet leverages [InnoSetup](https://jrsoftware.org/isinfo.php) on Windows. Download and install it.

It will also be necessary to manually add the InnoSetup location to the user's PATH variable
so that PupNet can call the `iscc` compiler. See screenshot below below:



## PUPNET CONFIGURATION

**Hello World for PupNet** is a demonstration project for PupNet Deploy. It will be instructive to discuss
the major configuration elements with reference to this simple project, as it demonstrates all the major
features of building distributable packages.

The Hello World project lives in [a separate git repo](https://github.com/kuiperzone/PupNet-HelloWorld) of its own:





Head over to this project in a different browser tab, or download it to your local drive.

Now, take a look at the `HelloWorld.pupnet.conf` in the root of the project.



This is a simple ini file in which the deployment project is configured. Where local paths are given, they are local
to the `.conf` file, rather than your current working directory. Always use the forward-slash '/' as a path separator
for cross-platform compatibility.

You will see that each parameter is documented. However, we will discuss key properties and issues below.

### Desktop File

Note the `DesktopFile` parameter which provides a path to a Linux `.desktop` file. *If you leave it blank, one will
be generated automatically.* In the Hello World demo, we have specified a file in order to show the default contents...

Open the file `Deploy/app.desktop`, and you will see:

[Desktop Entry]
Type=Application
Name=${APP_FRIENDLY_NAME}
Icon=${APP_ID}
Comment=${APP_SHORT_SUMMARY}
Exec=${INSTALL_EXEC}
TryExec=${INSTALL_EXEC}
NoDisplay=${DESKTOP_NODISPLAY}
X-AppImage-Integrate=${DESKTOP_INTEGRATE}
Terminal=${DESKTOP_TERMINAL}
Categories=${PRIME_CATEGORY}
MimeType=
Keywords=

Note that the contents above are entirely populated using macro variables (more below on these). However, you can
easily extend this file to specify a `MimeType` and `Keywords`, as well as adding international translations and
additional entries.

IMPORTANT: While you can edit this file as you wish, the file must contain the line below with its macro:

Exec=${INSTALL_EXEC}

Or, if you prefer:

Exec=${INSTALL_BIN}/app-name

The reason for this is that the actual path on installation will depend on the package type. You cannot hard code this
here as different packages will install to different paths. It is important also that you use macros as shown with
their braces, i.e. `${INSTALL_EXEC}` and not `$INSTALL_EXEC`, as a simple search-and-replace operation is
used to populate them.

In the event that you wish there be no desktop entry (i.e. a command-line application), you should declare:
`DesktopNoDisplay = true`. The file itself is ignored for Windows `Setup`, although if you set `DesktopNoDisplay`, then
no entry for your application's main executable will be added under the Windows Start Menu (i.e. synonymous
behavior on Windows with that on Linux).

**Hint:** You can use PupNet itself to generate a Linux desktop file for a new project:

pupnet [name] --new desktop

This will create a new file for you under: `name.desktop`

### AppStream Metadata

The `MetaFile` parameter specifies the path to a local AppStream metadata XML file. This applies to Linux only and
is optional. This metadata is used by software centers to display information about installed applications. For
detail information, see [AppStream Metadata Quick Start](https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html).

If you omit the `MetaFile` property, no `.metainfo.xml` file is shipped with your application. But let's assume you
wish to provide metadata, so take a look at the file provided under: `Deploy/app.metainfo.xml` in the Hello World demo.

Again, you will notice that macro variables are used. These are entirely optional here and simply mean that, as far
as possible, deployment configuration data is specified in one place only (i.e. your `pupnet.conf` file). However,
you may still wish to edit and extend this file to provide a screenshot, international language translations and
additional information such as keywords.

**IMPORTANT:** Since PupNet version 1.4.0, the macros `${APPSTREAM_DESCRIPTION_XML}` and `${APPSTREAM_CHANGELOG_XML}`
may be used to auto-populate the default application description, and change (release) information. The latter is
described in more detail below under [Application Versioning](#application-versioning-changelog).

**Hint:** You can use PupNet itself to generate a metadata template file for a new project:

pupnet [name] --new meta

This will create a new file for you under: `name.metainfo.xml`

### Icons

Multiple desktop icons are provided with the `IconPaths` parameter. You can use semi-colon as a separator, such as:
`IconPaths = icon1.ico;icon2.64x64.png;icon3.svg`, or present them in multi-line form as shown in the Hello World demo:

IconFiles = """
Deploy/HelloWorld.16x16.png
Deploy/HelloWorld.24x24.png
Deploy/HelloWorld.32x32.png
Deploy/HelloWorld.48x48.png
Deploy/HelloWorld.64x64.png
Deploy/HelloWorld.svg
Deploy/HelloWorld.ico
"""

Note the use of *triple quotes* here for multi-line values.

Use only the `svg`, `png` and `ico` file types. On Linux, `svg` and `png` files will be installed appropriately and the
Windows `ico` file ignored. For Windows `Setup` packages, on the other hand, only the `ico` file is used, and PNG and SVG
files are ignored.

**IMPORTANT:** It is necessary to specify the size of PNG files by embedding their size in the filename, as shown above,
or simply as: `name.64.png`.

### Dotnet Project Path

When building the deployment, PupNet first calls `dotnet publish` on your project. To do this, it needs to know where
your project lives. In `HelloWorld.pupnet.conf`, you may note that file is at the solution level, but `DotnetProjectPath`
value provides the project directory.

If your `pupnet.conf` files shares the same directory as your `.csproj` file, you may leave `DotnetProjectPath`
empty. Otherwise use this field to specify the path to your project file or directory relative to the location
of the configuration file.

### Dotnet Publish Arguments

The `DotnetPublishArgs` parameter is used to specify values to supply to the `dotnet publish` call:

DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

Do NOT include '-r' (runtime), or '-c' (configuration) here as they will be added automatically according to
configuration and command line arguments.

As an absolute minimum, we always want to include `--self-contained true`, as this will cause dotnet not only to
compile the application, but to publish all dependencies into a single directory. (From .NET8 onward you may wish to
consider using Native AOT).

### Application Versioning & Changelog

#### Application Version (AppVersionRelease)
The application version (plus release number) is specified in the `pupnet.conf` file, for example:

AppVersionRelease = 3.2.1[5]

Here we are using the semantic version `3.2.1` plus a "package release number" in square brackets. The release number
applies specifically to the deployment package itself and is used by `rpm` and `deb` package kinds. If you omit the
release number, and just give `3.2.1` for example, it defaults to 1.

If you prefer, you can override the version in the configuration file from the command line using:

pupnet --runtime linux-arm64 --kind deb --app-version 4.0.0[1]

Crucially, look again at the `DotnetPublishArgs` configuration value we gave above above and note `${APP_VERSION}`:

DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

Here, we can see that the version from our configuration is supplied to the build process as a variable (only the
application part is supplied, i.e. `3.2.1`). This is optional and you may remove it if you wish, although you will
then need to specify the version both in application code and the `pupnet.conf` file in this case.

#### Changelog (AppChangeFile)
PupNet version 1.4 introduced the `AppChangeFile` configuration property. This gives the path to a changelog file
which must use a predefined but simple format, or a README file which contains such formatted changelog information.

PupNet will parse the file and extract relevant change information. This is used to expand the `${APPSTREAM_CHANGELOG_XML}`
macro variable which may optionally be used within the `` element of your AppStream metadata file. This means
that lengthy version change information need only be specified once (in a changelog or README file).

Version change information is to be provided as one or more version release sections prefixed with '+' and a leading
version number, and suffixed with trailing date. Subsequent change items are prefixed with '-', as shown below.
Note that ';' is used as a separator.

+ VERSION;[Other fields ignored;]yyyy-MM-dd
- Change feature 3
- Change feature 4

+ VERSION;[Other fields ignored;]yyyy-MM-dd
- Change feature 1
- Change feature 2

Additional fields, between the VERSION number and trailing date, may used as you wish, i.e. to give a version title
and/or maintainer contact information, as below.

+ VERSION 1.3.1; Patch Release; [email protected]; 2023-05-01
- Bugfix: Fix package creation when file path of contents contain spaces (enclose file path with quotes when executing chmod)

Here, the version title and contact information will be ignored and are not used in AppStream data.

It is possible for change items to span multiple lines, as follows, but a change item should not be broken with an
empty line (otherwise the parser will think it is reading plain superfluous text).

The following two examples are "legal":

+ 1.3.1;2023-05-01
- Long change line
describing feature 3
- Change feature 4

+ 1.3.1;2023-05-01

- Long change line
describing feature 1

- Change feature 2

The following example is "illegal" and will result in version information loss:

+ 1.3.1;2023-05-01
- Long change line

describing feature 1
- Change feature 2

The changelog parser should do a robust job at parsing version information while ignoring superfluous README text,
but care should be taken to ensure that version information is correctly formatted. You may review the final AppStream
metadata (after macro expansion) by using `--verbose` command line option when building your deployment.

Finally, it should be stressed that this feature is entirely optional. If it does not suit your project, leave
`AppChangeFile` blank and specify version release information in your AppStream metadata file yourself (or just omit it).

### Terminal vs GUI Applications

While the Hello World demo is a terminal application, it was envisaged that a typical use case for PupNet
would be to deploy GUI applications built with Avalonia that are integrated with the desktop.

#### GUI Application
For a GUI application, you will want to ensure the following:

DesktopNoDisplay = false
DesktopTerminal = false

You may typically leave `StartCommand` empty, but may set it if you wish.

#### Terminal Application
IMPORTANT: Your terminal application will not be in the user's path by default, so note `StartCommand` and
`SetupCommandPrompt` below. Note, also, that Flatpak is not suitable for command-line centric applications.

DesktopNoDisplay = true
DesktopTerminal = true
StartCommand = command-name
SetupCommandPrompt = Command Prompt

For command line only apps, you would typically set `DesktopNoDisplay` true, but you may give your application a desktop
entry by setting it to false if you wish.

With `StartCommand`, you should set a simple command name for application which will be located in the user's path after
installation. This will actually be realized via a tiny bash script on Linux, or bat file on Windows, which will launch
your main application (the rest of your application will not be in the path). If, for example, your runnable file is
something like 'Zone.Kuiper.HelloWorld', you may set `StartCommand` simply to 'helloworld'.

On Windows, a different approach is taken. The `SetupCommandPrompt` is a Windows only option which ensures that a
Console entry is written to the Program Files menu (using the title you supply) which, when launched, will open a
dedicated command window with your application directory in the path for the session.

### Custom Post-Publish Operations

In `HelloWorld.pupnet.conf`, we see the lines:

DotnetPostPublish = Deploy/PostPublish.sh
DotnetPostPublishOnWindows = Deploy/PostPublish.bat

This is an advanced feature which allows you to call a command or script in order to perform additional operations after
`dotnet publish` has been called, but prior to building the package output. The above commands are called only on their
respective build systems, and should perform equivalent operation.

Such scripts may employ macro variables which are exported to the environment. The Hello World bash and batch scripts above,
for example, create a subdirectory and dummy file within the application build directory, the path of which is supplied
as the `${BUILD_APP_BIN}` environment variable (see below for a complete reference).

Here are the contents of our example bash script:

#!/bin/bash
# This is a dummy bash script used for demonstration and test. It outputs a few variables
# and creates a dummy file in the application directory which will be detected by the program.

echo
echo "==========================="
echo "POST_PUBLISH BASH SCRIPT"
echo "==========================="
echo

# Some useful macros / environment variables
echo "BUILD_ARCH: ${BUILD_ARCH}"
echo "BUILD_TARGET: ${BUILD_TARGET}"
echo "BUILD_SHARE: ${BUILD_SHARE}"
echo "BUILD_APP_BIN: ${BUILD_APP_BIN}"
echo

# Directory and file will be detected by HelloWorld Program
echo "Do work..."
set -x #echo on
mkdir -p "${BUILD_APP_BIN}/subdir"
touch "${BUILD_APP_BIN}/subdir/file.test"
set +x #echo off

echo
echo "==========================="
echo "POST_PUBLISH END"
echo "==========================="
echo

Likewise, in the Hello World demo bat file which does the equivalent job on Windows.

#### Non-Dotnet Projects
Additionally, you may leverage the post-publish operations (above) to perform the actual build operation itself
and populate the `${BUILD_APP_BIN}` directory with the output of your build process -- whatever that may be. In
principle, therefore, you could use this to package a C++ or Python application, provided that it is satisfactory
that the application and all its associated libraries are contained in a single target directory.

IMPORTANT: If you do this, you will need to disable PupNet from calling `dotnet publish`, which can be done by setting
`DotnetProjectPath = NONE`.

### Debian & RPM Considerations

#### Install Location
With Debian and RPM deployments, your application will be installed to the `/opt` directory, rather than `/usr/bin`.
If you set `StartCommand`, a tiny bash script will also be installed to `/usr/bin` in order to launch your application.

#### Dependencies
Although publishing a "self-contained" dotnet app should ideally produce a truly *self-contained* package, in reality
it may have additional dependencies which create complexity when building RPM and Debian deployments.

Microsoft list additional dependencies for these, although note that they may also be distro specific also:
https://learn.microsoft.com/en-us/dotnet/core/install/linux-scripted-manual#rpm-dependencies

From PupNet version 1.3.0 onward, the pupnet.conf file supports the ability to define such additional dependencies
using the `RpmRequires` and `DebRecommends` properties. By default, they are populated with typically expected values
(below), although these may be subject to change and you should review them for your application.

RpmRequires = """
krb5-libs
libicu
openssl-libs
zlib
"""

DebianRecommends = """
libc6
libgcc1
libgcc-s1
libgssapi-krb5-2
libicu
libssl
libstdc++6
libunwind
zlib1g
"""

*You should test RPM and Debian packages against your target distributions.*

## BUILDING THE HELLO WORLD DEMO

**Hello World for PupNet** can be built for all package kinds, including `appimage`, `flatpak`, `deb`, `rpm`, `zip`
and `setup` for Windows.

If you wish to build and try the demo, clone or download the [PupNet Hello World Project](https://github.com/kuiperzone/PupNet-HelloWorld)
to your local drive. Ensure that you have installed the prerequisites above, or at least those you wish to use.

In the terminal, CD into the root of the project directory.

### On Linux

Assuming you're on Linux, type:

pupnet --kind appimage

This will show the following information and ask for confirmation before building the deployment file.

============================================================
APPLICATION: HelloWorld 1.0.3 [1]
============================================================

AppBaseName: HelloWorld
AppId: zone.kuiper.helloworld
AppVersion: 1.0.3
PackageRelease: 1
StartCommand: helloworld [Not Supported]

============================================================
OUTPUT: APPIMAGE
============================================================

PackageKind: AppImage
Runtime: linux-x64
Arch: Auto (x86_64)
Build: Release
OutputName: HelloWorld.x86_64.AppImage
OutputDirectory: /mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/bin

============================================================
DESKTOP: app.desktop
============================================================

[Desktop Entry]
Type=Application
Name=Hello World
Icon=zone.kuiper.helloworld
Comment=A Hello World application
Exec=usr/bin/HelloWorld
TryExec=usr/bin/HelloWorld
NoDisplay=false
X-AppImage-Integrate=true
Terminal=true
Categories=Utility
MimeType=
Keywords=

============================================================
CHANGELOG: CHANGES
============================================================

+ Version 1.0.3;2023-05-04
- The pupnet.conf file upgraded to version 1.4.0
- Added ${APPSTREAM_CHANGELOG_XML} to app.metainfo.xml
- Added ${APPSTREAM_DESCRIPTION_XML} to app.metainfo.xml
- Other minor corrections and changes
- This line is deliberate test of escaping XML <>/" characters

+ Version 1.0.2;2023-04-18
- The pupnet.conf file upgraded to version 1.3.0
- Now builds using .NET6, rather than .NET7 (you can change this in csproj file if needed)
- Reinstated key-press to exit on all deployments

+ Version 1.0.1;2023-03-26
- Programs now asks for key-press only on Windows
- Reports version correctly as 1.0.1

+ Version 1.0.0;2023-03-22
- Initial release
- Reports version as "3.2.1". This was intentional at the time by way of demonstration.

============================================================
BUILD PROJECT: PupNet-HelloWorld
============================================================

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"

/mnt/DEVEL-1T/DOTNET/GITHUB/PupNet-HelloWorld/Deploy/PostPublish.sh

============================================================
BUILD PACKAGE: HelloWorld.x86_64.AppImage
============================================================

/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"

============================================================
ISSUES
============================================================

NONE

Continue? [N/y]:

This tells us that it will create a file called `HelloWorld.x86_64.AppImage`, under the `Deploy/bin` directory.
Moreover, it shows the expanded contents of the desktop file, and gives the `dotnet publish` call it will make so
that we may ensure that everything looks correct before hitting "y".

We can view more information, including the AppStream metadata contents, by using:

pupnet --kind appimage --verbose

The `--verbose` option is useful in other areas too, as we will see below.

### On Windows

On a Windows machine with InnoSetup installed, type:

pupnet --kind setup

This will generate the file: `HelloWorld.x64.exe`, which may be launched to install the program.



On installation, we find we have a new Program Menu entry, as shown below. We can see that it has also
included a link to our home page, which is optional.



Moreover, there is a "Command Prompt" option to launch a dedicated command window, as described above.

## CREATING NEW PUPNET PROJECT FILES

If you're starting a new project, you will wish to generate a new `pupnet.conf` file and possibly the associated
desktop and AppStream metadata files as well.

To generate a new `pupnet.conf` file in the current working directory:

pupnet --new conf

This will create a new file, `app.pupnet.conf`, which will be a "light weight" configuration file lacking the
documentation comments.

To generate a "verbose" file with documentation under a custom name:

pupnet ProjectName --new conf --verbose

In fact, we can generate a complete set of files, as follows:

pupnet ProjectName --new all --verbose

This creates not only the `pupnet.conf` file, but the `.desktop` and a `.metainfo.xml` template as well.

## BACKWARD COMPATIBILITY & UPGRADING YOUR CONFIGURATION
Where possible, new versions of PupNet will be backward compatible with existing pupnet.conf files. If ever this
is not the case, it will be explicitly stated.

New configuration properties may be added and old ones removed or deprecated, however. Where a new PupNet version results
in changes to configuration properties, you can upgrade an existing pupnet.conf file to the latest format using:

pupnet [file.pupnet.conf] --upgrade-conf

or

pupnet [file.pupnet.conf] --upgrade-conf --verbose

Your existing file will "backed-up" by appending an ".old" extension, and a new file written containing new properties
with their default values.

Using the `--verbose` option (above), causes the new file to contain extensive document comments. Without it, the new file
will be stripped of comments.

See also version specific changes below.

### Version 1.4 Changes

PupNet version 1.4.0 introduced new `AppDescription` and `AppChangeFile` configuration properties. If you wish to
make use of them, populate `AppDescription` with a longer application description (example below), and point `AppChangeFile`
to a changelog or README file containing formatted version information.

AppDescription = """
Hello World demonstrates all the major features of building distributable packages with PupNet.
It can be built for all package kinds, including AppImage, Flatpak, DEB and RPM formats on Linux,
and as a Setup file on Windows. It provides an example of using desktop and AppStream metadata files,
as well as icons and post-publish scripts.

On execution, the Hello World program displays command arguments and assembly information. The assembly
version confirms that version information, provided in the deployment configuration, was successfully passed
through the build system, to the application.
"""

AppChangeFile = CHANGES.txt

See above for the required format of `AppChangeFile` content.

Additionally, you will need to add a couple of macros to your AppStream metadata file, as follows, in order to fully
make use of these new features:


${APPSTREAM_DESCRIPTION_XML}

Here, you may replace your default description text, but keep any other language text. And:


${APPSTREAM_CHANGELOG_XML}

With this one, you should remove existing version release information if `${APPSTREAM_CHANGELOG_XML}` is going to be
populated from `AppChangeFile`.

In addition to AppStream metadata, the `AppDescription` content is now also used in the construction of RPM and DEB
packages.

## HELP SYSTEM REFERENCE

### Command Arguments

Type `pupnet --help` to display command arguments as expected.

PupNet Deploy 1.8.0
See also: https://github.com/kuiperzone/PupNet-Deploy

USAGE:
pupnet [] [--option-n value-n]

Example:
pupnet app.pupnet.conf -y -r linux-arm64

Always give .pupnet.conf file first. If .pupnet.conf file is omitted, the default is the one in the
working directory.

Build Options:
-k, --kind
Package output kind. If omitted, one is chosen according to the runtime (AppImage on linux).
Example: pupnet HelloWorld -k Flatpak

-r, --runtime
Dotnet publish runtime identifier. Default: linux-x64.
Valid examples include: 'linux-x64', 'linux-arm64' and 'win-x64' etc.
See: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog

-c, --build
Optional build target (or 'Configuration' in dotnet terminology).
Value should be 'Release' or 'Debug' only. Default: Release.

-j, --project
Optional path to the .csproj file or directory containing it. Overrides DotnetProjectPath
in the conf file.

-e, --clean
Call 'dotnet clean' prior to 'dotnet publish'. Default: false.

-v, --app-version
Specifies application version-release in form 'version[release]', where value in square
brackets is package release. Overrides AppVersionRelease in conf file.
Example: 1.2.3[1].

-p, --property
Specifies a property to be supplied to dotnet publish command. Do not use for app versioning.
Separate multiple values with comma. Example: -p DefineConstants=TRACE,DEBUG

--arch
Force target architecture, i.e. as 'x86_64', 'amd64' or 'aarch64' etc. Note that this is
not normally necessary as, in most cases, the architecture is defined by the dotnet runtime-id
and will be successfully detected automatically. However, in the event of a problem, the value
explicitly supplied here will be used to override. It should be provided in the form
expected by the underlying package builder (i.e. rpmbuild, appimagetool or InnoSetup etc.).

-o, --output
Force package output filename. Normally this is derived from parameters in the configuration.
This value will be used to override. Example: -o AppName.AppImage

--verbose
Indicates verbose output when building. It is used also with --new option.

-u, --run
Performs a test run of the application after successful build (where supported).

-y, --skip-yes
Skips confirmation prompts (assumes yes).

Other Options:

-n, --new [--verbose] [--skip-yes]
Creates a new empty conf file or associated file (i.e. desktop of metadata) for a new project.
A base file name may optionally be given. If --verbose is used, a configuration file with
documentation comments is generated. Use 'all' to generate a full set of configuration assets.
Example: pupnet HelloWorld -n all --verbose

--upgrade-conf [--verbose] [--skip-yes]
Upgrades supplied .pupnet.conf file to latest version parameters. For example, if the
conf file was created with program version 1.1 and new parameters where added in version
1.2, this command will upgrade the file by adding new parameters with default values.
If --verbose is used, a configuration file with documentation comments is generated.
Example: pupnet file.pupnet.conf --upgrade-conf --verbose

-h, --help
Show help information. Optional value specifies what kind of information to display.
Default is 'args'. Example: pupnet -h macro

--version
Show version and associated information.

### Macro Reference

Type `pupnet --help macro` to see supported macro reference information:

Macro variables may be used with the following configuration items:
DesktopFile, MetaFile, DotnetPublishArgs, DotnetPostPublish and DotnetPostPublishOnWindows.

IMPORTANT: Always use the ${MACRO_NAME} form, and not $MACRO_NAME.

** ${APP_BASE_NAME} **
Gives the AppBaseName value from the pupnet.conf file
Example: ${APP_BASE_NAME} = HelloWorld

** ${APP_FRIENDLY_NAME} **
Gives the AppFriendlyName value from the pupnet.conf file
Example: ${APP_FRIENDLY_NAME} = Hello World

** ${APP_ID} **
Gives the AppId value from the pupnet.conf file
Example: ${APP_ID} = net.example.helloworld

** ${APP_LICENSE_ID} **
Gives the AppLicenseId value from the pupnet.conf file
Example: ${APP_LICENSE_ID} = LicenseRef-Proprietary

** ${APP_SHORT_SUMMARY} **
Gives the AppShortSummary value from the pupnet.conf file
Example: ${APP_SHORT_SUMMARY} = A HelloWorld application

** ${APP_VERSION} **
Application version, excluding package-release extension
Example: ${APP_VERSION} = 1.0.0

** ${APPSTREAM_CHANGELOG_XML} **
AppStream changelog XML content (use within the element only)

** ${APPSTREAM_DESCRIPTION_XML} **
AppStream application description XML (use within the element only)

** ${BUILD_APP_BIN} **
Application build directory (i.e. the output of dotnet publish or C++ make)
Example: ${BUILD_APP_BIN} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/bin

** ${BUILD_ARCH} **
Build architecture: x64, arm64, arm or x86 (may differ from package output notation)
Example: ${BUILD_ARCH} = x64

** ${BUILD_DATE} **
Build date in 'yyyy-MM-dd' format
Example: ${BUILD_DATE} = 2023-05-05

** ${BUILD_ROOT} **
Root of the temporary application build directory
Example: ${BUILD_ROOT} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir

** ${BUILD_SHARE} **
Linux 'usr/share' build directory under BuildRoot (empty for some deployments)
Example: ${BUILD_SHARE} = /tmp/KuiperZone.PupNet/net.example.helloworld-linux-x64-Release-AppImage/AppDir/usr/share

** ${BUILD_TARGET} **
Release or Debug (Release unless explicitly specified)
Example: ${BUILD_TARGET} = Release

** ${BUILD_YEAR} **
Build year as 'yyyy'
Example: ${BUILD_YEAR} = 2023

** ${DEPLOY_KIND} **
Deployment output kind: appimage, flatpak, rpm, deb, setup, zip
Example: ${DEPLOY_KIND} = appimage

** ${DESKTOP_INTEGRATE} **
Gives the logical not of ${DESKTOP_NODISPLAY}
Example: ${DESKTOP_INTEGRATE} = true

** ${DESKTOP_NODISPLAY} **
Gives the DesktopNoDisplay value from the pupnet.conf file
Example: ${DESKTOP_NODISPLAY} = false

** ${DESKTOP_TERMINAL} **
Gives the DesktopTerminal value from the pupnet.conf file
Example: ${DESKTOP_TERMINAL} = true

** ${DOTNET_RUNTIME} **
Dotnet publish runtime identifier used (RID)
Example: ${DOTNET_RUNTIME} = linux-x64

** ${INSTALL_BIN} **
Path to application directory on target system (not the build system)
Example: ${INSTALL_BIN} = usr/bin

** ${INSTALL_EXEC} **
Path to application executable on target system (not the build system)
Example: ${INSTALL_EXEC} = usr/bin/HelloWorld

** ${LOCAL_DIRECTORY} **
The pupnet.conf file directory

** ${PACKAGE_RELEASE} **
Package release version
Example: ${PACKAGE_RELEASE} = 1

** ${PRIME_CATEGORY} **
Gives the PrimeCategory value from the pupnet.conf file
Example: ${PRIME_CATEGORY} = Utility

** ${PUBLISHER_COPYRIGHT} **
Gives the PublisherCopyright value from the pupnet.conf file
Example: ${PUBLISHER_COPYRIGHT} = Copyright (C) Acme Ltd 2023

** ${PUBLISHER_EMAIL} **
Gives the PublisherEmail value from the pupnet.conf file
Example: ${PUBLISHER_EMAIL} = [email protected]

** ${PUBLISHER_LINK_NAME} **
Gives the PublisherLinkName value from the pupnet.conf file
Example: ${PUBLISHER_LINK_NAME} = Project Page

** ${PUBLISHER_LINK_URL} **
Gives the PublisherLinkUrl value from the pupnet.conf file
Example: ${PUBLISHER_LINK_URL} = https://example.net

** ${PUBLISHER_NAME} **
Gives the PublisherName value from the pupnet.conf file
Example: ${PUBLISHER_NAME} = The Hello World Team

### Configuration Reference

Type `pupnet --help conf` to see supported configuration reference information:

########################################
# APP PREAMBLE
########################################

** AppBaseName **
Mandatory application base name. This MUST BE the base name of the main executable file. It should NOT
include any directory part or extension, i.e. do not append '.exe' or '.dll'. It should not contain
spaces or invalid filename characters.
Example: AppBaseName = HelloWorld

** AppFriendlyName **
Mandatory application friendly name.
Example: AppFriendlyName = Hello World

** AppId **
Mandatory application ID in reverse DNS form. This should stay constant for lifetime of the software.
Example: AppId = net.example.helloworld

** AppVersionRelease **
Mandatory application version and package release of form: 'VERSION[RELEASE]'. Use optional square
brackets to denote package release, i.e. '1.2.3[1]'. Release refers to a change to the deployment
package, rather the application. If release part is absent (i.e. '1.2.3'), the release value defaults
to '1'. Note that the version-release value given here may be overridden from the command line.
Example: AppVersionRelease = 1.0.0[1]

** AppShortSummary **
Mandatory single line application summary text in default (English) language.
Example: AppShortSummary = A HelloWorld application

** AppDescription **
Multi-line (surround with triple """ quotes) application description which provides longer explanation
than AppShortSummary in default language. Optional but it is recommended to specify this. Text
separated by an empty line will be treated as separate paragraphs. Avoid complex formatting, and do not
use HTML or markdown, other than list items begining with "* ", "+ " or "- ". This content is
used by package builders where supported, including RPM and DEB, and is used to populate the
${APPSTREAM_DESCRIPTION_XML} element used within AppStream metadata.

** AppLicenseId **
Mandatory application license ID. This should be one of the recognized SPDX license
identifiers, such as: 'MIT', 'GPL-3.0-or-later' or 'Apache-2.0'. For a proprietary or
custom license, use 'LicenseRef-Proprietary' or 'LicenseRef-LICENSE'.
Example: AppLicenseId = LicenseRef-Proprietary

** AppLicenseFile **
Optional path to application copyright/license text file. If provided, it will be packaged with the
application and used with package builders where supported.
Example: AppLicenseFile = LICENSE.txt

** AppChangeFile **
Optional path to application changelog file. IMPORTANT. If given, this file should contain version
information in a predefined format. Namely, it should contain one or more version headings of form:
'+ VERSION;DATE', under which are to be listed change items of form: '- Change description'. Formatted
information will be parsed and used to expand the ${APPSTREAM_CHANGELOG_XML} macro used
for AppStream metadata (superfluous text is ignored, so the file may also contain README information).
The given file will also be packaged with the application verbatim. See: https://github.com/kuiperzone/PupNet-Deploy.
Example: AppChangeFile = CHANGELOG.txt

########################################
# PUBLISHER
########################################

** PublisherName **
Mandatory publisher, group or creator.
Example: PublisherName = The Hello World Team

** PublisherCopyright **
Optional copyright statement.
Example: PublisherCopyright = Copyright (C) Acme Ltd 2024

** PublisherLinkName **
Optional publisher or application web-link name. Note that Windows Setup packages
require both PublisherLinkName and PublisherLinkUrl in order to include the link as
an item in program menu entries. Do not modify name, as may leave old entries in updated installations.
Example: PublisherLinkName = Project Page

** PublisherLinkUrl **
Publisher or application web-link URL. Although optional, it should be considered mandatory if using
MetaFile
Example: PublisherLinkUrl = https://example.net

** PublisherEmail **
Publisher or maintainer email contact. Although optional, some package builders (i.e. DEB) require it
and may warn or fail unless provided.
Example: PublisherEmail = [email protected]

########################################
# DESKTOP INTEGRATION
########################################

** DesktopNoDisplay **
Boolean (true or false) which indicates whether the application is hidden on the desktop. It is used to
populate the 'NoDisplay' field of the .desktop file. The default is false. Setting to true will also
cause the main application start menu entry to be omitted for Windows Setup.
Example: DesktopNoDisplay = false

** DesktopTerminal **
Boolean (true or false) which indicates whether the application runs in the terminal, rather than
providing a GUI. It is used to populate the 'Terminal' field of the .desktop file.
Example: DesktopTerminal = true

** DesktopFile **
Optional path to a Linux desktop file. If empty (default), one will be generated automatically from
the information in this file. Supplying a custom file, however, allows for mime-types and
internationalisation. If supplied, the file MUST contain the line: 'Exec=${INSTALL_EXEC}'
in order to use the correct install location. Other macros may be used to help automate the content.
Note. PupNet Deploy can generate you a desktop file. Use --help and 'pupnet --help macro' for reference.
See: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
Example: DesktopFile = Deploy/app.desktop

** StartCommand **
Optional command name to start the application from the terminal. If, for example, AppBaseName is
'Zone.Kuiper.HelloWorld', the value here may be set to a simpler and/or lower-case variant such as
'helloworld'. It must not contain spaces or invalid filename characters. Do not add any extension such
as '.exe'. If empty, the application will not be in the path and cannot be started from the command line.
For Windows Setup packages, see also SetupCommandPrompt. StartCommand is not
supported for all packages kinds (i.e. Flatpak). Default is empty (none).
Example: StartCommand = helloworld

** PrimeCategory **
Optional category for the application. The value should be one of the recognized Freedesktop top-level
categories, such as: Audio, Development, Game, Office, Utility etc. Only a single value should be
provided here which will be used, where supported, to populate metadata. The default is empty.
See: https://specifications.freedesktop.org/menu-spec/latest/apa.html
Example: PrimeCategory = Utility

** MetaFile **
Path to AppStream metadata file. It is optional, but recommended as it is used by software centers.
Note. The contents of the files may use macro variables. Use 'pupnet --help macro' for reference.
See: https://docs.appimage.org/packaging-guide/optional/appstream.html
Example: MetaFile = Deploy/app.metainfo.xml

** IconFiles **
Optional icon file paths. The value may include multiple filenames separated with semicolon or given
in multi-line form. Valid types are SVG, PNG and ICO (ICO ignored on Linux). Note that the inclusion
of a scalable SVG is preferable on Linux, whereas PNGs must be one of the standard sizes and MUST
include the size in the filename in the form: name.32x32.png' or 'name.32.png'.
Example: IconFiles = """
app.ico
app.svg
app.16x16.png
app.32x32.png
app.64x64.png
"""

########################################
# DOTNET PUBLISH
########################################

** DotnetProjectPath **
Optional path relative to this file in which to find the dotnet project (.csproj) file, or the
directory containing it. If empty (default), a single project file is expected under the same
directory as this file. IMPORTANT. If set to 'NONE', dotnet publish is disabled
(i.e. not called). Instead, only DotnetPostPublish is called.
Example: DotnetProjectPath = Source

** DotnetPublishArgs **
Optional arguments supplied to 'dotnet publish'. Do NOT include '-r' (runtime), or '-c' (configuration)
here as they will be added according to command line arguments. Typically you want as a minimum:
'-p:Version=${APP_VERSION} --self-contained true'. Additional useful arguments include:
'-p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishReadyToRun=true
-p:PublishTrimmed=true -p:TrimMode=link'. Note. This value may use macro variables. Use 'pupnet --help macro'
for reference. See: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish
Example: DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false

** DotnetPostPublish **
Post-publish (or standalone build) command on Linux (ignored on Windows). It is called after dotnet
publish, but before the final output is built. This could, for example, be a script which copies
additional files into the build directory given by ${BUILD_APP_BIN}. The working directory will be
the location of this file. This value is optional, but becomes mandatory if DotnetProjectPath equals
'NONE'. Note. This value may use macro variables. Additionally, scripts may use these as environment
variables. Use 'pupnet --help macro' for reference.
Example: DotnetPostPublish = post-publish.sh

** DotnetPostPublishOnWindows **
Post-publish (or standalone build) command on Windows (ignored on Linux). This should perform
the equivalent operation, as required, as DotnetPostPublish, but using DOS commands and batch
scripts. Multiple commands may be specified, separated by semicolon or given in multi-line form.
Note. This value may use macro variables. Additionally, scripts may use these as environment
variables. Use 'pupnet --help macro' for reference.
Example: DotnetPostPublishOnWindows = post-publish.bat

########################################
# PACKAGE OUTPUT
########################################

** PackageName **
Optional package name (excludes version etc.). If empty, defaults to AppBaseName. However, it is
used not only to specify the base output filename, but to identify the application in DEB and RPM
packages. You may wish, therefore, to ensure that the value represents a unique name. Naming
requirements are strict and must contain only alpha-numeric and '-', '+' and '.' characters.
Example: PackageName = HelloWorld

** OutputDirectory **
Output directory, or subdirectory relative to this file. It will be created if it does not exist and
will contain the final deploy output files. If empty, it defaults to the location of this file.
Example: OutputDirectory = Deploy/OUT

########################################
# APPIMAGE OPTIONS
########################################

** AppImageArgs **
Additional arguments for use with appimagetool. Useful for signing. Default is empty.
Example: AppImageArgs = --sign

** AppImageVersionOutput **
Boolean (true or false) which sets whether to include the application version in the AppImage filename,
i.e. 'HelloWorld-1.2.3-x86_64.AppImage'. Default is false. It is ignored if the output filename is
specified at command line.
Example: AppImageVersionOutput = false

########################################
# FLATPAK OPTIONS
########################################

** FlatpakPlatformRuntime **
The runtime platform. Invariably for .NET (inc. Avalonia), this should be 'org.freedesktop.Platform'.
Refer: https://docs.flatpak.org/en/latest/available-runtimes.html
Example: FlatpakPlatformRuntime = org.freedesktop.Platform

** FlatpakPlatformSdk **
The platform SDK. Invariably for .NET (inc. Avalonia applications) this should be 'org.freedesktop.Sdk'.
The SDK must be installed on the build system.
Example: FlatpakPlatformSdk = org.freedesktop.Sdk

** FlatpakPlatformVersion **
The platform runtime version. The latest available version may change periodically.
Refer to Flatpak documentation.
Example: FlatpakPlatformVersion = 23.08

** FlatpakFinishArgs **
Flatpak manifest 'finish-args' sandbox permissions. Optional, but if empty, the application will have
extremely limited access to the host environment. This option may be used to grant required
application permissions. Values here should be prefixed with '--' and separated by semicolon or given
in multi-line form. Refer: https://docs.flatpak.org/en/latest/sandbox-permissions.html
Example: FlatpakFinishArgs = """
--socket=wayland
--socket=x11
--filesystem=host
--share=network
"""

** FlatpakBuilderArgs **
Additional arguments for use with flatpak-builder. Useful for signing. Default is empty.
See flatpak-builder --help.
Example: FlatpakBuilderArgs = --gpg-keys=FILE

########################################
# RPM OPTIONS
########################################

** RpmAutoReq **
Boolean (true or false) which specifies whether to build the RPM package with 'AutoReq' equal to yes or no.
For dotnet application, the value should typically be false, but see RpmRequires below.
Refer: https://rpm-software-management.github.io/rpm/manual/spec.html
Example: RpmAutoReq = false

** RpmAutoProv **
Boolean (true or false) which specifies whether to build the RPM package with 'AutoProv' equal to yes or no.
Refer: https://rpm-software-management.github.io/rpm/manual/spec.html
Example: RpmAutoProv = true

** RpmRequires **
Optional list of RPM dependencies. The list may include multiple values separated with semicolon or given
in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)
Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.
Default values are recommended for use with dotnet and RPM packages at the time of writing.
For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-rhel#dependencies
Example: RpmRequires = """
krb5-libs
libicu
openssl-libs
zlib
"""

########################################
# DEBIAN OPTIONS
########################################

** DebianRecommends **
Optional list of Debian dependencies. The list may include multiple values separated with semicolon or given
in multi-line form. If empty, a self-contained dotnet package will successfully run on many (but not all)
Linux distros. In some cases, it will be necessary to explicitly specify additional dependencies.
Default values are recommended for use with dotnet and Debian packages at the time of writing.
For updated information, see: https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#dependencies
Example: DebianRecommends = """
libc6
libgcc1
libgcc-s1
libgssapi-krb5-2
libicu
libssl
libstdc++6
libunwind
zlib1g
"""

########################################
# WINDOWS SETUP OPTIONS
########################################

** SetupGroupName **
Optional application group name used as the Start Menu folder and install directory under Program Files.
Specifically, it is used to define the InnoSetup DefaultGroupName and DefaultDirName parameters.
If empty (default), suitable values are used based on your application.
See: https://jrsoftware.org/ishelp/index.php?topic=setup_defaultgroupname
Example: SetupGroupName = HelloWorld Demo

** SetupAdminInstall **
Boolean (true or false) which specifies whether the application is to be installed in administrative
mode, or per-user. Default is false. See: https://jrsoftware.org/ishelp/topic_admininstallmode.htm
Example: SetupAdminInstall = false

** SetupCommandPrompt **
Optional command prompt title. The Windows installer will NOT add your application to the path. However,
if your package contains a command-line utility, setting this value will ensure that a 'Command Prompt'
program menu entry is added (with this title) which, when launched, will open a dedicated command
window with your application directory in its path. Default is empty. See also StartCommand.
Example: SetupCommandPrompt = Command Prompt

** SetupMinWindowsVersion **
Mandatory value which specifies minimum version of Windows that your software runs on. Windows 8 = 6.2,
Windows 10/11 = 10. Default: 10. See: https://jrsoftware.org/ishelp/topic_setup_minversion.htm
Example: SetupMinWindowsVersion = 10

** SetupSignTool **
Optional name and parameters of the Sign Tool to be used to digitally sign: the installer,
uninstaller, and contained exe and dll files. If empty, files will not be signed.
See: https://jrsoftware.org/ishelp/topic_setup_signtool.htm

** SetupSuffixOutput **
Optional suffix for the installer output filename. The default is empty, but you may wish set it to:
'Setup' or similar. This, for example, will output a file of name: HelloWorldSetup-x86_64.exe
Ignored if the output filename is specified at command line.
Example: SetupSuffixOutput = Setup

** SetupVersionOutput **
Boolean (true or false) which sets whether to include the application version in the setup filename,
i.e. 'HelloWorld-1.2.3-x86_64.exe'. Default is false. Ignored if the output filename is specified
at command line.
Example: SetupVersionOutput = true

** SetupUninstallScript **
Optional name of a script to run before uninstall.
This is script file relative to the directory of the application and must have a default file association.
This binds to the `[UninstallRun]` section of InnoSetup.
From this script, you may want to run your application, which is very useful if
your application has non-static configurable storage locations for data.

Example: uninstall.bat

## FAQs & GOTCHAS

### NETSDK1194: The "--output" option isn't supported

From .NET7 ownward, the `dotnet publish` no longer accepts a `.sln` file or directory containing one as input. It's
current behaviour for .NET8.0 is to warn rather than fail but this may change in a future .NET release.

For your pupnet.conf files, the solution is to either place the conf file in the same directory as your `.csproj`
file, or specify the `.csproj` file location using the `DotnetProjectPath` parameter.

See 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).

### Virtual Box & Symlinks

If you are using VirtualBox with your project, note that symbolic links are disabled within shared folders by VirtualBox
itself, and this may cause problems with generating AppImages. To overcome this, copy your entire project to your home
directory in the virtual machine. Alternatively, it is possible to enable shared-folder symlinks in VirtualBox.

### Package Naming is not Consistent

You may notice that PupNet outputs differences in package naming styles. For example:

PupNet-Deploy.x86_64.AppImage
pupnet-deploy_0.0.1-1_amd64.deb

PupNet follows the naming conventions used with the respective packages. This includes, for example, different CPU
architecture naming conventions. With some package naming styles, it is normal to include the version in the filename,
but not in others.

### Package Cannot be Removed using Gnome Software Center

If you install your Flatpak, RPM or DEB package directly from a local file (rather than a repository) they will,
courtesy of your AppStream metadata, show up in the Gnome Software Center, as expected. However, you may find that they
cannot be launched or removed using the GUI.

Instead, they must be removed from the command line, like so:

sudo flatpak uninstall zone.kuiper.helloworld

or:

sudo dnf remove helloworld

or:

sudo apt remove helloworld

This is not an issue with PupNet or AppStream metadata. Rather, having been installed from file, the Gnome Software Center
lacks certain other metadata it expects had the package originated from a repository.
See [here for information](https://discourse.gnome.org/t/gnome-software-open-and-uninstall-button-not-working-for-app/14338/7).

## ADDITIONAL INFORMATION

### Brief Discussion on Past & Future

PupNet Deploy began life as a bash script called "*Publish-AppImage for .NET*":



Publish-AppImage

At the time, I was excited by Flatpak and it was my original intention to add Flatpak support to *Publish-AppImage*. However,
it was difficult to handle the increased complexity in a bash script, so I re-wrote everything as a C# application and
*PupNet Deploy* is the result.

In the process, however, I had cause to reflect on certain things, including the fact that the
[security model of Flatpak is broken IMHO](https://ludocode.com/blog/flatpak-is-not-the-future). This came about
because I intended to use Flatpak to deploy my other [application project](https://github.com/kuiperzone/AvantGarde),
but found that there are several important scenarios which Flatpak cannot support, including the deployment of development
tools. Regardless, I thought it useful for developers to be able ship software in formats convenient for users,
and recognise that Flatpak is a popular packaging technology. However, I felt that RPM and Debian formats should be added
in order to provide alternatives where Flatpak is unsuitable.

### Notes on Extending PupNet

Anyone wishing to extend PupNet, should study how the existing `RpmBuilder`, `FlatpakBuilder` and Windows `SetupBuilder`
classes override and extend the behaviour of the `PackageBuilder` base class. The `PackageBuilder` base class is Linux
centric, with unused directories and properties being set to null and ignored for the Windows Setup and Zip builders.

Moreover, a new enum value would need to be added to the `PackageKind` type. It would help to do a search on
existing `PackageKind` values, and add the new type behaviour to switch statements wherever encountered, including
the `BuilderFactory` class.

Please do feel free to post questions to the Github Discussion area. Where possible, I will be happy to respond.

### An Application which uses PupNet Deploy

[AvantGarde](https://github.com/kuiperzone/AvantGarde) is a cross-platform XAML previewer for the C# Avalonia Framework,
and the primary previewer solution when developing on Linux.



AvantGarde Screenshot

### Copyright & License

Copyright (C) Andy Thomas, 2023. Website: https://kuiper.zone

PupNet is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.

PupNet is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with PupNet. If not, see .

#### Embedded Assets ####
PupNet embeds "appimagetool", from the "AppImageKit".
AppImageKit is Copyright (C) 2004-20 Simon Peter:
https://github.com/AppImage/AppImageKit

#### Non-code Assets ####
Images and non-code assets are not subject to AGPL.

Project Logo: Copyright (C) Andy Thomas, 2023.

All other copyright and trademarks are property of respective owners.

If you like this project, don't forget to like and share.