Makefile.am
looks like a normal Makefile
in terms of syntax. This language
is apparently M4, using the GNU M4 implementation, an implementation of a Unix
macro processor. Apparently GNU Autoconf and therefore the files Makefile.am
,
~Makefile.in~, Makefile
and configure.ac
all make use of this language:
Autoconf is an extensible package of M4 macros that produce shell scripts to automatically configure software source code packages. These scripts can adapt the packages to many kinds of UNIX-like systems without manual user intervention. Autoconf creates a configuration script for a package from a template file that lists the operating system features that the package can use, in the form of M4 macro calls.
-- https://www.gnu.org/software/autoconf/autoconf.html
guile-haunt
is a static site generator written in GNU Guile only. It is
available on GNU Guix, so it should make for a good example for how one can
build a GNU Guix package oneself. It also was a package recommended to look at
on the GNU Guile IRC channel.
The repository can be found here: https://github.com/guildhall/guile-haunt.
So lets go. Lets try to explain what the various parts, that we can find in the ~guile-haunt~ project, that are taking part in making a GNU Guix package, do.
Apparently one ships the source files with the package, so the source files need to be defined somewhere.
#+begin_src makefile SOURCES = \ haunt/config.scm \ haunt/utils.scm \ haunt/post.scm \ haunt/reader.scm \ haunt/page.scm \ haunt/asset.scm \ haunt/site.scm \ haunt/html.scm \ haunt/builder/assets.scm \ haunt/builder/atom.scm \ haunt/builder/blog.scm \ haunt/ui.scm \ haunt/ui/build.scm \ haunt/ui/serve.scm \ haunt/serve/mime-types.scm \ haunt/serve/web-server.scm #+end_src
This seems to simply be a list of all GNU Guile source files and is fittingly
named SOURCES
.
GNU Guile source files are compiled to Guile object files, which have the file
extension ~.go~. The following rules of the form $(var:a=b)
is a so called
"substitution reference" (See also
https://www.gnu.org/software/make/manual/make.html#Substitution-Refs):
GOBJECTS = $(SOURCES:%.scm=%.go)
This rule says: For each item in SOURCES
, which has the form %.scm
, put a
new item in GOBJECTS
, which has the form %.go
. %.scm
matches all filenames
with the extension ~.scm~.
So this is an easy way of saying GOBJECTS
are the Guile object files, which
correspond to the SOURCES
files.
Extra distributed files are files, which are not source code of the library or program itself, but files, which nevertheless should be put into the package. Such files are readme files initialization files and a ~package.scm~ file, which suspiciously looks like a file GNU Guix might be looking for already.
Additionally to the compiled sources, the sources and not compiled sources get distributed.
#+begin_src makefile EXTRA_DIST = $(SOURCES) $(NOCOMP_SOURCES)
EXTRA_DIST += \ pre-inst-env.in \ README.md \ package.scm #+end_src
For some reason (TODO) the sub directories of the project need to be specified.
SUBDIRS = \ example \ website
The situation with guile-haunt
is a little different from a simple library,
because it is a command line tool, which is supposed to be invoked by the user.
However, guile-haunt
is not intended to be called by calling guile
and then
specifying the directory, which guile-haunt
and the main source file are
installed in. This would be a bit cumbersome for users. Instead the idea is to
provide a script, which is on the PATH
and can be run. This script should
accept the same arguments that the actual guile-haunt
program accepts and hand
them over to guile-haunt
.
Such a script is located in the scripts
directory inside the project.
TODO: I am not sure, why it needs to be specified in the Makefile.am
file.
#+begin_src makefile bin_SCRIPTS = \ scripts/haunt #+end_src
The actual script has the following content:
#!@GUILE@ --no-auto-compile -*- scheme -*- !# ;;; Haunt --- Static site generator for GNU Guile ;;; Copyright © 2015 David Thompson ;;; ;;; This file is part of Haunt. ;;; ;;; Haunt is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or ;;; (at your option) any later version. ;;; ;;; Haunt 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 ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with Haunt. If not, see .
(use-modules (haunt ui)) (apply haunt-main (command-line))
It looks like the hash-bang line refers to Guile, not directly, but via a template variable or something. Perhaps the script is merely a template, which is filled in later?
TODO: explain
The Guile code itself is quite simple.
(use-modules (haunt ui)) (apply haunt-main (command-line))
It loads the module (haunt ui)
and then applies the project's main function to
the command line arguments.
GNU Guile source files are compiled to Guile object files, which have the file
extension ~.go~. The directory, in which those files can be found also is
specified in the Makefile.am
.
TODO: I am not sure, why this directory needs to be specified in the ~Makefile.am~ file.
godir=$(libdir)/guile/2.0/ccache
The modules directory is the directory, in which the GNU Guile source files will be put, when the package is installed. It is specified as well:
moddir=$(prefix)/share/guile/site/2.0
Since GNU Guile scheme files are compiled to ~.go~, one can force a recompile of the source by deleting the ~.go~ files, when they are needed next time.
CLEANFILES = $(GOBJECTS)
Some flags about warning output at compile time of sources are specified and given the name ~GUILE_WARNINGS~:
GUILE_WARNINGS = -Wunbound-variable -Warity-mismatch -Wformat
They are later used in the target ~.scm.go~.
A list of file endings is defined:
SUFFIXES = .scm .go
TODO: I do not know yet, why the SUFFIXES
are defined.
There are many definitions, but only a few actual targets in the ~Makefile.am~ of ~guile-haunt~:
$(guile_install_go_files)
That is it.
TODO: I do not know yet, why the files have a combined file ending of ~.scm~ and then ~.go~ instead of only ~.go~. Perhaps this is a common convention?
At some point there needs to be an instruction that tells GNU Guix how to actually compile the program. This instruction is a target defined as follows:
.scm.go: $(AM_V_GEN)$(top_builddir)/pre-inst-env $(GUILE_TOOLS) compile $(GUILE_WARNINGS) -o "$@" "$<"
AM_V_GEN
stands Apparently for "automake" (see: Automake hello) then perhaps
~V~ for "verbosity", then perhaps GEN
for "generate". So a string, which gets
inserted, which contains instructions for the verbosity of the command to only
show what it generated. Prepending it to a command will output only GEN
TARGET
, where TARGET
is the created file which is the target. In this case
the output should be GEN ....scm.go
for each ~.scm.go~ file. AM_V_GEN
is
probably predefined in automake.
Here is an explanation for AM_V_GEN
from the Automake manual:
You can use the predefined variable AM_V_GEN as a prefix to commands that should output a status line in silent mode, and AM_V_at as a prefix to commands that should not output anything in silent mode. When output is to be verbose, both of these variables will expand to the empty string.
-- https://www.gnu.org/software/automake/manual/automake.html#amhello_0027s-configure_002eac-Setup-Explained
top_builddir
appears in 2 places in the repository:
#+begin_src shell ... abs_top_builddir="`cd "@abs_top_builddir@" > /dev/null; pwd`" ... GUILE_LOAD_COMPILED_PATH="$abs_top_builddir${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH" ... PATH="$abs_top_builddir/scripts:$PATH" #+end_src
Makefile.am
TODO: What is the @VARNAME@
syntax in the shell script? Is this normal shell
script syntax?
TODO: Where does top_builddir
come from?
TODO: Where does GUILE_TOOLS
come from? It is only mentioned in its definition
in the Makefile.am
.
TODO: Explain "$@"
. TODO: Explain "$<"
.
There are still some parts missing from a full explanation:
nobase_mod_DATA = $(SOURCES) $(NOCOMP_SOURCES) nobase_go_DATA = $(GOBJECTS)
guile_install_go_files = install-nobase_goDATA $(guile_install_go_files): install-nobase_modDATA
nobase_mod_DATA
only appears once in the whole repository of guile-haunt
,
which is in its definition in the Makefile.am
. It therefore seems, that it is
something GNU Guix is looking for in a Makefile
, which is produced from the
~Makefile.am~. Looking at Creating amhello in the GNU automake manual, it seems,
that there is a convention, by which one appends _DATA
to some
variables. Perhaps those are always data for other tools to access later, when
they work with the resulting Makefile
.
Same goes for nobase_go_DATA
. It also only appears in its definition and seems
to be data for later usage.
nobase
relating to? What would be "the base", of which thereinstall-nobase_modDATA
come from? Is it relating toinstall-nobase_goDATA
come from? Is it relating toinstall-nobase_modDATA
depends on