guile-haunt.org 11 KB

Makefile.am

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

Why guile-haunt?

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.

Explanations

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.

GNU Guile source files

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 compiled files

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

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

Sub directories

For some reason (TODO) the sub directories of the project need to be specified.

SUBDIRS = \ example \ website

Scripts

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

haunt script

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.

Directory of compiled GNU Guile files

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

Modules directory

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

Cleaning up

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)

Compilation flags

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~.

File endings

A list of file endings is defined:

SUFFIXES = .scm .go

TODO: I do not know yet, why the SUFFIXES are defined.

Targets

There are many definitions, but only a few actual targets in the ~Makefile.am~ of ~guile-haunt~:

  1. $(guile_install_go_files)
  2. ~.scm.go~

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?

Compilation command

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:

  • thrice in the pre-installation environment:

#+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

  • in its usage in the 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 "$<".

Still unexplained

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.

  • TODO: What is nobase relating to? What would be "the base", of which there
  • is none here?
  • TODO: Where does install-nobase_modDATA come from? Is it relating to
  • ~nobase_go_DATA~ and the ~install-~ prefix is magically taken off? ~go~ probably stands for "GNU Guile object file".
  • TODO: Where does install-nobase_goDATA come from? Is it relating to
  • ~nobase_mod_DATA~ and the ~install-~ prefix magically taken off? ~mod~ might stand for "GNU Guile module".
  • TODO: But why? How does GNU Guix make use of these variables?
  • TODO: What does it mean, that install-nobase_modDATA depends on
  • ~guile_install_go_files~?

Makefile syntax