Debian upstream

From Lazarus wiki
Revision as of 19:33, 28 October 2020 by Circular (talk | contribs) (started page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

On Debian distribution, the upstream source is the code of the program that can be compiled for any target platform. It needs to be compilable using packages already available in the latest Debian distribution.

Dependence on Lazarus custom packages

Generally Debian packages will use dynamically linked libraries, that will be provided as another Debian package. However in Lazarus, it is common to use statically linked libraries that are provided as Lazarus custom packages (the main file have .lpk extension).

If you are using custom Lazarus packages, you will need to include them in the upstream source. You can do that by copying the custom packages source code into your projects repository or create an upstream repository that will contain your own project as well as all custom packages source code.

Publishing a new version of your project on Debian will thus require you to copy the package source with the adequate version number. It is recommended to specify the required package version by enforcing it in the project inspector, so that you won't use an outdated custom package for compilation and also that you will be able to know which version is supposed to be used.

Upstream source, package maintainer and sponsor

There are different levels when it comes to uploading packages into Debian:

  • upstream source provided by the software developer
  • Debian package provided by the package maintainer
  • upload done by the package sponsor

Note that it may be difficult to find a package maintainer so that the developer can as a matter of fact be the maintainer as well. This article talks only about the upstream source.

Upstream source content

The upstream source consists of:

  • you project source code
  • custom Lazarus packages source code
  • a configure script
  • a Makefile

In all cases, the debian name must no be used as a root folder name because it is reserved for the Debian package.

Project and custom packages

It is recommended to use a specific folder for each custom package, though there is no restriction here. You just need to remember the path to those when writing the Makefile.

configure script

The script called configure is a script that is called initially before compilation. It can be used to detect the compilation environment and take appropriate actions. In the case of Lazarus, the bare minimum is to handle the prefix parameter. Here is for example a simple script that will store the prefix parameter in a file called prefix.

#!/bin/bash
args=("$@")
defaultprefix=/usr/local
wantedprefix=$defaultprefix
for param in "${args[@]}"
do
	if [ "$param" == "-h" ] || [ "$param" == "--help" ]; then
		echo "Usage: ./configure [OPTIONS]"
		echo ""
		echo "    --prefix=PREFIX"
		echo "        Specifies the install prefix."
		echo "        By default prefix is \"$defaultprefix\"" 
		echo "        For packages use \"/usr\""
		exit 0
	elif [ "${param:0:9}" == "--prefix=" ]; then
		wantedprefix=${param:9}
	else
		echo "Warning: unknown option $param"
	fi
done
echo "Prefix set to: $wantedprefix"
echo $wantedprefix >prefix  # store the prefix into the file called "prefix"

Here are examples of calls:

./configure                 # when testing the program locally
./configure --prefix=/usr   # when building the package

Makefile

Initialization

The Makefile is a sort of script. It does not have a shebang (line starting with "#!") and uses by default the minimalist shell /bin/sh. You can override it though and use bash with something like:

SHELL := /bin/bash

Note that in the Makefile, unlike a regular script, to access a variable one write $(VARIABLE) with brackets instead of ${VARIABLE} with braces. To run a shell command and retrieve the result, the brackets will also be used, which can be a little bit confusing.

Variables are set using := operator. For example, to compute the actual target path, one can write the following:

prefix := $(shell cat prefix)   # retrieve the content of the file called "prefix"
TARGET_DIR = $(DESTDIR)$(prefix)

When building locally, DESTDIR will be empty so that the target path will be the same as prefix. When building the package though, DESTDIR will indicate a temporary folder to use.

To make things easier to update, let's define the name of your project (without the .lpi extension):

PROJECT_NAME := myproject
Compiling

After the initialization of variables, the Makefile consists of entries called rules. The syntax of a rule is the following:

rule1: require1 require2
#... how to make it

Here the name of the rule is rule1 and it requires the rules require1 and require2 to be already made. This means that first require1 and require2 will be made and only afterwards rule1 will be made. The following lines contain the instructions to execute to make rule1.

If a rule does not need any other, there won't be anything after the colon. In the case of a Lazarus project, one can simply write:

all:
	lazbuild --build-mode=Release $(PROJECT_NAME).lpi

The rule all is the one invoked to compile the program. Note that before the instructions, a tab character is needed (not spaces). It is recommended to specify the build-mode, because there may be various build modes like Debug or for different widgetsets (gtk2, gtk3, qt4, qt5). So whatever build mode is active in the project, you will be assured of the build mode used to generate the Debian package.

To clean the compiled files, there is a need for another rule:

clean:
	rm -f $(PROJECT_NAME)  # remove generated executable file
	rm -rf lib             # remove object files

Note that the object files may be in another folder. Check the project options.

For completeness, let's provide a rule to clean the whole building process:

distclean: clean clean_configure
clean_configure:
	rm -f prefix     # remove the "prefix" file generated by "configure" script
Installation and package building

The Makefile needs to be able to install files on the system or to put them in the package. Both will be done with the same code and when building a package, the target directory will instead be a temporary one.

We will need additional folders for that. They are similar to the content of a .deb file.

BIN_DIR = $(TARGET_DIR)/bin                  # executable file
SHARE_DIR = $(TARGET_DIR)/share              # other files
RESOURCE_DIR = $(SHARE_DIR)/$(PROJECT_NAME)  # custom resources
DOC_DIR = $(SHARE_DIR)/doc/$(PROJECT_NAME)   # documentation
ICON_DIR = $(SHARE_DIR)/icons/hicolor        # icons (multiple resolutions)
PIXMAP_DIR = $(SHARE_DIR)/pixmaps            # pixmap (fallback icon)

The installation will require the prefix file to exist. This can be specified like any other rule:

install: prefix