XML Parse error on Local Build

Colin Law clanlaw at gmail.com
Sat Dec 10 08:46:09 EST 2016

On 10 December 2016 at 13:33, Geert Janssens <geert.gnucash at kobaltwit.be> wrote:
> ...
> I agree the complete details of autogen/configure/make are fairly complex. I
> don't even understand all of it myself. The complexity stems from the design
> idea to create a build system that's generic enough to build all kinds of
> objects (applications, libraries, documentation, websites, whatever) on as
> many different platforms as possible. Luckily we don't need all of this
> complexity for our purposes.
> Let me try to explain this top to bottom. The command we're ultimately
> interested in is 'make'. This command follows recipes to convert some source
> files into some end object(s). For gnucash this is a bunch of c and guile
> sources which are transformed into the gnucash application (which itself is
> composed of an executable and lots of libraries). There are lots of details
> I'm glossing over here, focusing mostly on the principles.
> For our docs plain make (without explicit target that is) does nothing,
> because the xml files are both the source and the target which yelp needs to
> display the docs.
> However aside from the main target one can also define alternative targets. A
> few spring to mind for the docs: html, pdf, mobi, epub, install. So one could
> run
> make pdf
> and make will search a recipe to build one or more pdf files, depending on
> which directory you execute the command in.
> 'install' is a special recipe that is intended to put whatever make built as
> primary target (the xml files in case of the docs, which are the same as the
> source xml files) in a special location where a typical unix system expects
> these files. For example, executables typically should be installed in
> /usr/bin on linux. This location can be overridden. I'll get back to this
> later.
> Where does make find all these recipes ?
> make looks for a file called Makefile in the current directory. Makefile holds
> the recipes and other configuration items. Unfortunately this file is very
> complex in itself because - as I said earlier - the build system is designed
> to work in very different environments.
> For example the location of all the tools needed to create targets from the
> source files (like xsltproc) may be installed in different locations on
> different platforms, or even have a different name (like xsltproc.exe in a
> Windows environment). Or some commandline options for certain tools may not
> be available on all platforms or versions of the tool. Manually coping with
> all these variations will quickly result in a mess.
> So to cope with this a configuration step was added to the build process. This
> step runs a very complicated script called "configure" that will analyze your
> system and actually creates the Makefile files I described above. configure
> will lookup installation location for all tools used and can enable or disable
> certain recipes in the Makefiles based on its findings. "configure" can also
> take extra commandline options that can alter what it will include in the
> Makefiles. You can see these options by running configure --help. Most of them
> are not relevant for us, except for the few we invented ourselves like
> --with-mobi.
> "configure" doesn't take Makefile's as input. Instead it will read files
> called Makefile.in, which is a pseudo Makefile with lots or variables that
> still need final setting.
> Still, writing a configure script and Makefile.in files remains very
> cumbersome and lots of information in both files comes back all the time in
> different projects. So yet another step was added before in the build system.
> This step is meant to generate the configure script and the Makefile.in files
> based on another set of files: configure.ac and Makefile.am files.
> These files encode the essence of configure and the final Makefiles, but with
> everything removed that can be detected by a smart configuration script. Only
> the details that matter and are unique for each project are retained in these
> files.
> Generating configure and the various Makefile.in files involve a few steps,
> but they are always the same, regardless of the platform you run them on. For
> this reason they are combined together in a small script called autogen.sh.
> This script itself is the platform independent and is used to initiate the
> whole build system for a given project.
> And that's the general idea behind the autotools based build system. Again I
> glossed over a lot of details.
> As a rule of thumb, autogen.sh should be called the first time you want to
> initialize the build system and sometimes when changes are made in
> configure.ac or the Makefile.am files. Frequently those changes are
> autodetected though. Calling autogen.sh when it's not necessary doesn't doe
> harm either way. The only side effect is that the first next build may take
> longer.
> The same goes for "configure". It should generally be called right after
> autogen.sh for the same reasons. And same here, calling it while not really
> required has no negative side-effect other than that the first next build may
> take longer because more objects will be rebuilt.
> Lastly, make is the command you'll want to call after each change in the
> sources you want reflected in the targets.
> Now on to directories. In a build system there are three important
> directories:
> - the source directory
> - the build directory
> - the installation directory (which can also be more than one directory all
> under a special directory called the prefix-directory)
> The source directory should be clear - it's where your source files are.
> gnucash-docs (the clone of our github repository) with all its subdirectories
> on your system for documentation. If you want to make changes to the
> documentaiton, you do this in the source directory.
> The build directory is a directory used by the build system to store all
> files/objects that are generated by the build system.*make is always executed
> in the build directory*. Each make recipe results in at least one such file or
> object.
> Without any extra steps, the build directory will be the same as the source
> directory. So if you build the html files for the English guide for example,
> these files will be put next to the xml files for that guide in the source
> directory (although the recipe will put them in a subdirectory as a
> convenience).
> If you don't want this (and it's generally recommended *not* to build in the
> source directory directly for various reasons), you can also choose to work
> with a separate build directory. The way to do this is a bit unusual but very
> simple once you understand it: configure will use the directory from which
> it's called as the build directory. An example will help here:
> Assume you have cloned the gnucash-docs repository here:
> /home/user/gnucash/gnucash-docs
> and want to use
> /home/user/gnucash/gnucash-docs/build
> as build directory
> Then first run autogen.sh in /home/user/gnucash/gnucash-docs as follows
> cd /home/user/gnucash/gnucash-docs
> ./autogen.sh
> This ensures the configure script is generated. Now create the directory you
> want to use as build directory
> mkdir /home/user/gnucash/gnucash-docs/build
> Note that "build" is purely arbitrary. It can be whatever suits you, and even
> wherever it suits you. Some people create it as a subdirectory to the source
> directory. I tend to have it in a completely different location to have all
> builds together under one directory. That is a matter of preference.
> Now to "call configure from the build directory", you first have to be *in*
> the build directory:
> cd /home/user/gnucash/gnucash-docs/build
> And then invoke configure. Configure is still in the source directory, so in
> order to call it you need to use the full (absolute or relative) path to it:
> /home/user/gnucash/gnucash-docs/configure
> or
> ../configure
> Both are equivalent. The former uses the absolute path, the latter uses a
> relative path.
> With this, configure will use /home/user/gnucash/gnucash-docs/build as the
> build directory. The Makefile files and target objects will all be stored in
> there (and its subdirectories).
> And finally there is the installation location, which is the location where
> the generated objects should finally end up to be used sensibly in the system.
> Without any special configuration this will be /usr/local/... on linux based
> systems. This is however not a good location to keep as default during
> development (or documentation changing), because this would interfere with
> your stable, running system and that's generally not what you want on a modern
> system where installed software is usually done via a package manager.
> So for development purposes we need to tell the build system to use another
> final location. This is done during the run to configure, by setting the
> --prefix option. You can find a reference to this in the wiki page as well in
> the section about testing on linux. Again whatever you choose as base
> directory for the --prefix option is really a matter of preference. The only
> conditions are:
> - it should be a writable location for the user that runs make install
> - it should not be in the default paths /usr or /usr/local
> For the example started above, one could use say
> /home/user/gnucash/gnucash-docs/install
> Or the full configure command (using relative paths here):
> ../configure --prefix=/home/user/gnucash/gnucash-docs/install
> And this is as far as I can tell all there is to know. You may need to install
> a few packages at the beginning. xsltproc is one, the build system also
> requires autoconf, automake and libtoolize. I believe most distributions
> provide generic packages to install all that is needed to have a suitable
> development environment. These should take care of most of the dependencies.
> I'm a bit vague here as it's been quite a while since I had to start from
> scratch like this. Sorry about that.

That's a great description of how build systems work. You should put
it on a blog somewhere.


More information about the gnucash-devel mailing list