This page informally completes the [[https://people.debian.org/~lbrenta/debian-ada-policy.html|Debian Policy for Ada]]. = Links for Debian maintainers of Ada packages = Debian patches GCC so that it handles SOURCE_DATE_EPOCH, so this reproducibility issue should not be a concern anymore. See the [[https://wiki.debian.org/ReproducibleBuilds/TimestampsInAdaLibraryInformationFiles|dedicated page]] for details. The [[https://manpages.debian.org/bullseye/dh-ada-library/dh_ada_library.1.en.html|dh-ada-library]] helper may be convenient, even if the package builds no library. Here is [[https://salsa.debian.org/debian/libtemplates-parser/-/blob/debian/master/debian|a full example]]. = Build flags in Debian = [[https://manpages.debian.org/bullseye/dpkg-dev/dpkg-buildflags.1.en.html|dpkg-buildflags]] computes `CFLAGS`, `CPPFLAGS` and `LDFLAGS` from the architecture, system-wide defaults, `DEB_BUILD_MAINT_OPTIONS` (set by the Debian maintainer in `debian/rules`), and `DEB_BUILD_OPTIONS` (set at build time). It is usually invoked implicitly by `dpkg-buildpackage` or `buildflags.mk`. For historical reasons, `dpkg-buildpackage` invokes `dpkg-buildflags`, then exports the computed values before running `debian/rules`. It is recommended that `debian/rules` also computes and exports them, as `dpkg-buildpackage` is not the only way to invoke `debian/rules`. The `buildflags.mk` Makefile snippet serves this purpose, and `ada/debian_packaging.mk` adds `ADAFLAGS` and `BUILDER_OPTIONS` (`GNATMAKEFLAGS` and `GPRBUILDFLAGS` after gnat-11). {{{#!highlight Make include /usr/share/dpkg/buildflags.mk include /usr/share/dpkg/buildopts.mk # Build-Depends: gnat (<= 10) include /usr/share/ada/debian_packaging-$(shell gnatgcc -dumpversion) # Build-Depends-Arch: gnat (<= 10) gcc_version != sed -n '/^ gnat-\(.*\),$$/{s//\1/;p;q}' debian/control include $(wildcard /usr/share/ada/debian_packaging-$(gcc_version)) # Build-Depends: gnat (>= 11) include /usr/share/ada/debian_packaging.mk # Build-Depends-Arch: gnat (>= 11) include $(wildcard /usr/share/ada/debian_packaging.mk) }}} = Suggestions for upstream maintainers = This section describes how to make an Ada build system easy to package for Debian. The build system should support the configuration of build flags via environment variables or command-line arguments. * `ADAFLAGS` should be added to the Ada compiler command line, after default arguments so that they take precedence. * `CFLAGS` and `CPPFLAGS` should similarly affect the C compiler and preprocessor. The preprocessor is usually implicitly run by the compiler, so these variables often ends up concatened. * A variable should similarly affect the `gnatmake` or `gprbuild` command lines. There is no convention, but `GNATMAKEFLAGS` and `GPRBUILDFLAGS` follow GNU standards. * `LDFLAGS` and `LDLIBS` should be added respectively before and after the linker default arguments, so that options like `-Wl,--as-needed` work as expected. * It should be possible to similarly change the build tool, for example when cross-building. The tradition is to name the variable after the capitalized tool. * It should be possible to install an unstripped executable. * For shared libraries, it should be possible to set the shared object version, that is the last part of the `-Wl,-soname=libNAME.so.VERSION` linker argument. There is no convention, but `NAME_soversion` comes to mind (or `NAME_soname` for the whole argument). The prefix matters because a typical link involves several libraries. When a source package builds several libraries, please allow a distinct override for each library, even if the default is common. Even for C, it is not easy to use the default GNU Make recipes, because for example {{{#!highlight Make CFLAGS := -g -O2 $(CFLAGS) main: helper.o }}} give different results for `make CFLAGS=-O0` and `CFLAGS=-O0 make`. The following Makefile is configurable enough as far as Debian is affected. {{{#!highlight Make # https://www.gnu.org/prep/standards/html_node/Command-Variables.html GNATMAKE ?= gnatmake GNATMAKEFLAGS ?= -v ADAFLAGS ?= -g -O2 # CC ?= cc CFLAGS ?= -g -O2 # CPPFLAGS ?= # LDFLAGS ?= # LDLIBS ?= INSTALL ?= install INSTALL_PROGRAM ?= $(INSTALL) INSTALL_DATA ?= $(INSTALL) -m 644 STRIP ?= strip # https://www.gnu.org/prep/standards/html_node/DESTDIR.html # DESTDIR = # https://www.gnu.org/prep/standards/html_node/Directory-Variables.html # These path may also affect references embedded in executables # (resources), documentation, pkg-config .pc files or GNAT .gpr # projects (sources and libraries)... prefix = /usr/local exec_prefix = $(prefix) bindir = $(exec_prefix)/bin datarootdir = $(prefix)/share mandir = $(datarootdir)/man # Override is probable. NUMJOBS != getconf _NPROCESSORS_ONLN # Override is unexpected, these settings are either required or inoffensive. executable = tool ada_main_unit = ada_main_unit gnatmakeflags = -eS -j$(NUMJOBS) adaflags = -gnatwa -gnatwe cflags = -Wall -Wextra cppflags = -Ifoo/ ldflags = -Wl,--as-needed ldlibs = ../bar/libbar.so libbaz.a -lfoo c_objects = obj/c1.o obj/c2.o all: $(c_objects) | obj $(GNATMAKE) $(ada_main_unit) -aIsrc -D obj -o obj/$(executable) \ $(gnatmakeflags) $(GNATMAKEFLAGS) \ -cargs $(adaflags) $(ADAFLAGS) \ -largs $(ldflags) $(LDFLAGS) $(c_objects) $(ldlibs) $(LDLIBS) $(c_objects): obj/%.o: src/%.c src/%.h | obj $(CC) $(cflags) $(CFLAGS) $(cppflags) $(CPPFLAGS) -c -o $@ $< obj/c1.o: src/c2.h obj: mkdir obj install: all $(INSTALL_PROGRAM) obj/$(executable) -Dt $(DESTDIR)$(bindir) $(INSTALL_DATA) $(executable).1 -Dt $(DESTDIR)$(mandir) install-strip: install $(STRIP) $(DESTDIR)$(bindir)/$(executable) clean: rm -fr obj .PHONY: all install clean }}} Here is an example of [[https://docs.adacore.com/gprbuild-docs/html/gprbuild_ug/gnat_project_manager.html|GNAT project]]. {{{#!highlight Ada package Compiler is Adaflags := ("-g", "-O2"); case Mode is when "production" => Adaflags := Adaflags & ("-gnatn"); when "debug" => Adaflags := Adaflags & ("-gnata"); end case; Adaflags := Adaflags & External_As_List ("ADAFLAGS", " "); for Switches ("Ada") use Adaflags; for Switches ("C") use ("-g", "-O2", "-Ifoo/") & External_As_List ("CFLAGS", " ") & External_As_List ("CPPFLAGS", " "); end Compiler; package Linker is for Leading_Switches ("Ada") use ("-Wl,--as-needed") & External_As_List ("LDFLAGS", " "); for Switches ("Ada") use ("../bar/libbar.so", "libbaz.a", "-lfoo") & External_As_List ("LDLIBS", " "); end Linker; }}} For a library project, there is no need to change the Compiler package. The object and library directoy paths should be reasonably unique for a given set of build flags. At least, PIC and non-PIC objects should be stored separately so that a static archive and a shared object may be built in a row. {{{#!highlight Ada Pic := ""; -- for now Ldlibs := ("../bar/libbar.so", "libbaz.a", "-lfoo") & External_As_List ("LDLIBS", " "); case project'Library_Kind is when "dynamic" | "relocatable" => for Library_Version use "libNAME.so." & External ("NAME_soversion", "3.4"); for Leading_Library_Options use ("-Wl,--as-needed") & External_As_List ("LDFLAGS", " "); for Library_Options use Ldlibs; Pic := "pic"; when "static" => Pic := "static"; when "static-pic" => Pic := "pic"; end case; for Object_Dir use "build/obj-" & Pic & "-" & Mode; for Library_Dir use "build/lib-" & Pic & "-" & Mode; package Linker is for Linker_Options use Ldlibs; end Linker; }}} Scenario variables from the environment or `-X` options should be prefered to constructs like `gprbuild -cargs $(ADAFLAGS)`. The interaction of `-cargs` with Compiler.Switches is under-documented and hardly predictable. For the same reason, the options for `gprbuild` itself should be set either on the command line or in a `Builder` package, but not both. At least for libraries, `gprinstall` or `install` targets are usually not flexible enough for Debian and completely ignored. The `clean` target should simply `rm -fr` the build directory. `gprclean` is complex, slow, and typically requires several runs with different scenario variables. In Makefiles, please try to catch only the expected error instead of prefixing a recipe with a dash. For example, if `rm -fr foo` ever fails, the error is probably important and unexpected enough to stop execution. In Makefiles, please avoid `.SILENT` and use the `@` prefix with parcimony. Verbose logs are quite useful when debugging.