Edition 1
1998-09-02
Eleftherios Gkioulekas
@shorttitlepage Learning the GNU development tools Copyright (C) 1998 Eleftherios Gkioulekas. All rights reserved.
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the sections entitled "Copying" and "Philosophical issues" are included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice and the sections entitled "Copying" and "Philosophical issues" may be stated in a translation approved by the Free Software Foundation instead of the original English.
The purpose of this document is to introduce you to the GNU build system, and show you how to use it to write good code. It is also meant to serve as a manual for Autotools, an additional package that provides a variety of additional features. Finally it discusses peripheral topics such as how to use GNU Emacs as a source code navigator and how to make heads and tails out of Texinfo. The intended reader should be a software developer who understands his programming languages, and wants to learn how to put together his programs the way a typical FSF program is put together.
When we speak of the GNU build system we refer primarily to the following three programs:
- Autoconf produces a configuration shell script, named `configure', which probes the installer platform for portability related information which is required to customize makefiles, configuration header files, and other application specific files. Then it proceeds to generate customized versions of these files from generic templates. This way, the user will not need to customize these files manually.
- Automake produces makefile templates, `Makefile.in' to be used by Autoconf, from a very high level specification stored in a file called `Makefile.am'. Automake produces makefiles that conform to the GNU makefile standards, taking away the extraordinary effort required to produce them by hand. Automake requires Autoconf in order to be used properly.
- Libtool makes it possible to compile position indepedent code and build shared libraries in a portable manner. It does not require either Autoconf, or Automake and can be used indepedently. Automake however supports libtool and interoperates with it in a seamless manner.
The GNU build system has two goals. The first is to simplify the development of portable programs. The second is to simplify the building of programs that are distributed as source code. The first goal is achieved by the automatic generation of a `configure' shell script. The second goal is achieved by the automatic generation of Makefiles and other shell scripts that are typically used in the building process. This way the developer can concentrate on debugging his source code, instead of his overly complex Makefiles. And the installer can compile and install the program directly from the source code distribution by a simple and automatic procedure.
The GNU build system needs to be installed only when you are developing programs that are meant to be distributed. To build a program from distributed source code, you only need a working make, a compiler, a shell, and sometimes standard Unix utilities like sed, awk, yacc, lex. The objective is to make software installation as simple and as automatic as possible for the installer. Also, by setting up the GNU build system such that it creates programs that don't require the build system to be present during their installation, it becomes possible to use the build system to bootstrap itself.
Some tasks that are simplified by the GNU build system include:
- Building multidirectory software packages. It is much more difficult to use raw
make recursively. Having simplified this step, the developer is encouraged to organize his source code in a deep directory tree rather than lump everything under the same directory. Developers that use raw make often can't justify the inconvenience of recursive make and prefer to disorganize their source code. With the GNU tools this is no longer necessary.
- Automatic configuration. You will never have to tell your users that they need to edit your Makefile. You yourself will not have to edit your Makefiles as you move new versions of your code back and forth between different machines.
- Automatic makefile generation. Writing makefiles involves a lot of repetition, and in large projects it will get on your nerves. The GNU build system instead requires you to write `Makefile.am' files that are much more terse and easy to maintain.
- Support for test suites. You can very easily write test suite code, and by adding one extra line in your `Makefile.am' make a
check target available such that you can compile and run the entire test suite by running make check.
- Automatic distribution building. The GNU build tools are meant to be used in the development of free software, therefore if you have a working build system in place for your programs, you can create a source code distribution out of it by running
make distcheck.
- Shared libraries. Building shared libraries becomes as easy as building static libraries.
The Autotools package complements the GNU build system by providing the following additional features:
- Automatic generation of legal notices that are needed in order to apply the GNU GPL license.
- Automatic generation of directory trees for new software packages, such that they conform to the GNITS standard (more or less).
- Some rudimentary portability framework for C++ programs. There is a lot of room for improvement here, in the future. Also a framework for embedding text into your executable and handling include files accross multiple directories.
- Support for writing portable software that uses both Fortran and C++.
- Additional support for writing software documentation in Texinfo, but also in LaTeX.
Autotools is still under development and there may still be bugs. At the moment Autotools doesn't do shared libraries, but that will change in the future.
This effort began by my attempt to write a tutorial for Autoconf. It involved into "Learning Autoconf and Automake". Along the way I developed Autotools to deal with things that annoyed me or to cover needs from my own work. Ultimately I want this document to be both a unified introduction of the GNU build system as well as documentation for the Autotools package.
I believe that knowing these tools and having this know-how is very important, and should not be missed from engineering or science students who will one day go out and do software development for academic or industrial research. Many students are incredibly undertrained in software engineering and write a lot of bad code. This is very very sad because of all people, it is them that have the greatest need to write portable, robust and reliable code. I found from my own experience that moving away from Fortran and C, and towards C++ is the first step in writing better code. The second step is to use the sophisticated GNU build system and use it properly, as described in this document. Ultimately, I am hoping that this document will help people get over the learning curve of the second step, so they can be productive and ready to study the reference manuals that are distributed with all these tools.
This manual of course is still under construction. When I am done constructing it some paragraph somewhere will be inserted with the traditional run-down of summaries about each chapter. I write this manual in a highly non-linear way, so while it is under construction you will find that some parts are better-developed than others. If you wish to contribute sections of the manual that I haven't written or haven't yet developed fully, please contact me.
Chapters 1,2,3,4 are okey. Chapter 5 is okey to, but needs a little more work. I removed the other chapters to minimize confusion, but the sources for them are still being distributed as part of the Autotools package for those that found them useful. The other chapters need a lot of rewriting and they would do more harm than good at this point to the unsuspecting reader. Please contact me if you have any suggestions for improving this manual.
This document and the Autotools package have originally been written by Eleftherios Gkioulekas. Many people have further contributed to this effort, directly or indirectly, in various way. Here is a list of these people. Please help me keep it complete and exempt of errors.
- The appendix Philosophical issues has been written by Richard Stallman. (see section Philosophical issues)
- The chapter on Fortran, and the Autotools support for developing software that is partly written in Fortran is derived from the work of John Eaton on GNU Octave, which I mainly generalized for use in other programs. (see section Fortran with Autoconf).
- Mark Galassi was the first person, to the best of my knowledge, who tried to write an Autoconf tutorial. It is thanks to his work that I was inspired to begin this work.
FIXME: I need to start keeping track of acknowledgements here
The following notice refers to the Autotools package with which this document is being distributed. The following notice refers to the Autotools package, which includes this documentation, as well as the source code for utilities like `acmkdir' and for additional Autoconf macros. The complete GNU build system involves other packages also, such as Autoconf, Automake, Libtool and a few other accessories. These packages are also free software, and you can obtain them from the Free Software Foundation. For details on doing so, please visit their web site http://www.fsf.org/. Although Autotools has been designed to work with the GNU build system, it is not yet an official part of the GNU project.
The Autotools package is "free"; this means that everyone is free to use it and free to redistribute it on a free basis. The Autotools package is not in the public domain; it is copyrighted and there are restrictions on its distribution, but these restrictions are designed to permit everything that a good cooperating citizen would want to do. What is not allowed is to try to prevent others from further sharing any version of this package that they might get from you.
Specifically, we want to make sure that you have the right to give away copies of the programs that relate to Autotools, that you receive source code or else can get it if you want it, that you can change these programs or use pieces of them in new free programs, and that you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of the Autotools-related code, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights.
Also, for our own protection, we must make certain that everyone finds out that there is no warranty for the programs that relate to Autotools. If these programs are modified by someone else and passed on, we want their recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation.
The precise conditions of the licenses for the programs currently being distributed that relate to Autotools are found in the General Public Licenses that accompany it.
When you download an autoconfiguring package , it usually has a filename like: `foo-1.0.tar.gz' where the number is a version number. To install it, first you have to unpack the package to a directory someplace:
% gunzip foo-1.0.tar.gz
% tar xf foo-1.0.tar
Then you enter the directory and look for files like `README' or `INSTALL' that explain what you need to do. Almost always this amounts to typing the following commands:
% cd foo-1.0
% configure
% make
% make check
% su
# make install
The `configure' command invokes a shell script that is distributed with the package that configures the package for you automatically. First it probes your system through a set of tests that allow it to determine things it needs to know, and then it uses this knowledge to generate automatically a `Makefile' from a template stored in a file called `Makefile.in'. When you invoke `make' with no argument, it executes the default target of the generated `Makefile'. That target will compile your source code, but will not install it. If your software comes with self-tests then you can compile and run them by typing `make check'. To install your software, you need to explicitly invoke `make' again with the target `install'. In order for `make' to work, you must make the directory where the `Makefile' is located the current directory.
During installation, the following files go to the following places:
Executables -> /usr/local/bin
Libraries -> /usr/local/lib
Header files -> /usr/local/include
Man pages -> /usr/local/man/man?
Info files -> /usr/local/info
where `foo' is the name of the package. The `/usr/local' directory is called the prefix. The default prefix is always `/usr/local' but you can set it to anything you like when you call `configure'. For example, if you want to install the package to your home directory instead, you will have to do this instead:
% configure --prefix=/home/skeletor
% make
% make check
% make install
The `--prefix' argument tells `configure' where you want to install your package, and `configure' will take that into account and build the proper makefile automatically.
The `configure' script is compiled by `autoconf' from the contents of a file called `configure.in'. These files are very easy to maintain, and in this tutorial we will teach you how they work. The `Makefile.in' file is also compiled by `automake' from a very high-level specification stored in a file called `Makefile.am'. The developer then only needs to maintain `configure.in' and `Makefile.am'. As it turns out, these are so much easier to work with than Makefiles and so much more powerful, that you will find that you will not want to go back to Makefiles ever again once you get the hang of it.
In some packages, the `configure' script supports many more options than just `--prefix'. To find out about these options you should consult the file `INSTALL' and `README' that are traditionally distributed with the package, and also look at `configure''s self documenting facility:
% configure --help
Configure scripts can also report the version of Autoconf that generated them:
% configure --version
The makefiles generated by `automake' support a few more targets for undoing the installation process to various levels. More specifically:
- If
configure or make did it, make distclean undoes it.
- If
make did it, make clean undoes it.
- If
make install did it, make uninstall undoes it.
Also, in the spirit of free redistributable code, there are targets for cutting a source code distribution. If you type
% make dist
it will rebuild the `foo-1.0.tar.gz' file that you started with. If you modified the source, the modifications will be included in the distribution (and you should probably change the version number). Before putting a distribution up on FTP, you can test its integrity with:
% make distcheck
This makes the distribution, then unpacks it in a temporary subdirectory and tries to configure it, build it, run the test-suite, and check if the installation script works. If everything is okey then you're told that your distribution is ready.
Once you go through this tutorial, you'll have the know-how you need to develop autoconfiguring programs with such powerful Makefiles.
It is not unusual to be stuck on a system that does not have the GNU build tools installed. If you do have them installed, check to see whether you have the most recent versions. To do that type:
% autoconf --version
% automake --version
% libtool --version
If you don't have any of the above packages, you need to get a copy and install them on your computer. The distribution filenames for the GNU build tools are:
autoconf-2.12.tar.gz
automake-1.3.tar.gz
libtool-1.3.tar.gz
Before installing these packages however, you will need to install the following needed packages from the FSF:
make-3.76.1.tar.gz
m4-1.4.tar.gz
texinfo-3.12.tar.gz
tar-1.12.shar.gz
You will need the GNU versions of make, m4 and tar even if your system already has native versions of these utilities. To check whether you do have the GNU versions see whether they accept the --version flag. If you have proprietory versions of make or m4, rename them and then install the GNU ones. You will also need to install Perl, the GNU C compiler, and the TeX typesetter.
It is important to note that the end user will only need a decent shell and a working make to build a source code distribution. The developer however needs to gather all of these tools in order to create the distribution.
Finally, to install Autotools begin by installing the following additional utilities from FSF:
bash-2.01.tar.gz
sharutils-4.2.tar.gz
and then install
autotools-X.X.tar.gz
You should be able to obtain a copy of Autotools from the same site from which you received this document.
The installation process, for most of these tools is rather straightforward:
% ./configure
% make
% make check
% make install
Most of these tools include documentation which you can build with
% make dvi
Exceptions to the rule are Perl, the GNU C compiler and TeX which have a more complicated installation procedure. However, you are very likely to have these installed already.
The versions numbers indicated above were the current ones at the time of this writing. If more recent versions are available, you may want to use them instead.
To get your feet wet we will show you how to do the Hello world program using `autoconf' and `automake'. In the fine tradition of K&R, the C version of the hello world program is:
#include <stdio.h>
main()
{
printf("Howdy world!\n");
}
Let's say we've put this in a file called `hello.c'. Please place this file under an empty directory since we will be producing a lot of clutter soon enough! It can be compiled and ran directly with the following commands:
% gcc hello.c -o hello
% hello
If you are on a non-GNU variant of Unix, your compiler might be called `cc' but the usage will be pretty much the same.
Now to do the same thing the `autoconf' and `automake' way create first the following files:
- `Makefile.am'
-
bin_PROGRAMS = hello
hello_SOURCES = hello.c
- `configure.in'
-
AC_INIT(hello.c)
AM_INIT_AUTOMAKE(hello,1.0)
AC_PROG_CC
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
Now run `autoconf':
% aclocal
% autoconf
This will create the shell script `configure'. Next, run `automake':
% automake -a
required file "./install-sh" not found; installing
required file "./mkinstalldirs" not found; installing
required file "./missing" not found; installing
required file "./INSTALL" not found; installing
required file "./NEWS" not found
required file "./README" not found
required file "./COPYING" not found; installing
required file "./AUTHORS" not found
required file "./ChangeLog" not found
The first time you do this, you get a spew of messages. It says that `automake' installed a whole bunch of cryptic stuff: `install-sh', `mkinstalldirs' and `missing'. These are shell scripts that are needed by the makefiles that `automake' generates. You don't have to worry about what they do. It also complains that the following files are not around:
INSTALL, COPYING, NEWS, README, AUTHORS, ChangeLog
These files are required to be present by the GNU coding standards, and we will discuss them in detail later. Nevertheless, it is important that these files are at least touched, because when we try to make a test distribution by calling `make distcheck' later on, it will cause a fatal error if any of these files are missing. Eventually, we will suggest that you use the `acmkdir' utility to automatically generate templates for these files which you can edit at will. To make these files exist, now please type:
% touch NEWS README AUTHORS ChangeLog
and to make Automake aware of the existence of these files, please rerun it:
% automake -a
Only when Automake completes without error messages, you can assume that the generated `Makefile.in' might be correct.
Now you are "all set" in the sense that your package is in the state that will allow you, as well as the end-user to type:
% configure
% make
% hello
to compile and run the hello world program. The idea of course is that the end-user will get the package "all-set" and will not have to have a copy of `automake' and `autoconf' to get it compiled. This is the developer's responsibility. If you really want to install it, go ahead and do it:
# make install
Oops, you changed your mind! Then uninstall it:
# make uninstall
If you didn't use the `--prefix' argument to point to your home directory you may need to be superuser to invoke the install commands.
Please note that in order for the above to work you need to use the GNU `gcc' compiler. Automake dependends on `gcc''s ability to compute the dependencies, so without `gcc' this example will not work. If you do have `gcc' installed, then the `configure' script will select it for you.
If you feel like cutting a distribution, you can do it with:
% make distcheck
This will create a file called `hello-1.0.tar.gz' in the current working directory so that when unpacked it is "all-set" for the user to fire away `configure' and start building. While building that file, Automake includes the precomputed dependencies and disables the dependencies from the end-user makefiles. This way the end-user will not have to have `gcc' to compile the package.
Now pretend that you are the end-user, unpack this file, enter it and compile it all over again:
% gunzip hello-1.0.tar.gz
% tar xf hello-1.0.tar
% cd hello-1.0
% configure
% make
% hello
And this is the full circle.
It is very important that when you run Automake the `configure' file already exists, otherwise Automake will not include it in the distribution when you do `make dist' and the target `distcheck' will fail to build. This means that you should run Autoconf before running Automake. To see this effect go back up to the toplevel directory and do the following:
% rm -f configure
% automake
% make distcheck
You will notice that the `distcheck' target fails.
Before you ever cut a distribution and put it up on FTP, you should put content to the files
INSTALL, COPYING, NEWS, README, AUTHORS, ChangeLog
The file `COPYING' has to do with copyright issues (see section Copyright and Free Software). The other files are part of the software documentation. The GNU coding standards require that these files be present when you distribute your source code.
In this section we give a summary overview of how you should maintain these files. For more details, please see the GNU coding standards, as published by the FSF.
- The README file: Every distribution must contain this file. This is the file that the installer must read fully after unpacking the distribution and before configuring it. You should briefly explain the purpose of the distribution, and reference all other documentation available. Instructions for installing the package normally belong in the `INSTALL' file. However if you have something that you feel the installer should know then mention it in this file.
- The INSTALL file: Because the GNU installation procedure is streamlined, a standard `INSTALL' file will be created for you automatically by
Automake. If you have something very important to say, it may be best to say it in the `README' file instead. the `INSTALL' file is mostly for the benefit of people who've never installed a GNU package before. However, if your package is very unusual, you may decide that it is best to modify the standard INSTALL file or write your own.
- The AUTHORS file: The purpose of this file is to record for copyright purposes who wrote what. The file must state the name of the owner, and it must also list the names of contributors and for each contributor the set of files they modified and the set of new files that they created. For example, typical contents of the `AUTHORS' file might look like:
Authors of FOO
See also the files THANKS and ChangeLog
Bart Simpson designed and implemented FOO
Principal Skinner:
entire files bob1.cc, bob2.cc, bob3.cc
extensive changes in foo1.cc, foo2.cc, foo3.cc
- The THANKS file: Here you list the names and email addresses of the people who contributed to the development of your package either through actual contributed work or through comments and suggestions. There is no legal need to maintain but it is good manners to credit and thank all who have helped you, besides those listed in `AUTHORS'. The wording of the `THANKS' file may look like this:
FOO THANKS file
FOO has originally been written by Your Name. Many people have further
contributed to FOO by reporting problems, suggesting various improvements,
or submitting actual code. Here is a list of these people. Help me keep
it complete and exempt of errors
Name1 <email address1>
Name2 <email address2>
....
A good habit is to use the `THANKS' file to record people's email addresses instead of having them in many places (like `AUTHORS', `ChangeLog'). This will make it easier to keep them updated.
- The NEWS file: This is where you tell the users about the major features of this distribution. You needn't go into details, but you do need to list all the major features. The GNU coding standards explain in more detail how to structure this file.
- The ChangeLog file: This file you are meant to maintain as you develop your code. It is meant to be like a diary where you write down in detail what changes you made to your code as you develop it. The GNU coding standards explain in a lot of detail how you should structure a `ChangeLog', so you should read about it there. The basic idea is to record modifications you make to code that already works. It is not necessary to detail how you developed a new piece of code, until you get it to work. It is important however to note down version releases. This way by viewing the `ChangeLog' file you can tell rather quickly the changes between versions. This file also records the names of the people making the modifications. This way if development is done by a team, and you want to address a bug in a certain part of the code, you can see who has been playing with it recently, get them on a mailing list and talk. The Gnu coding standards go into the details about how to do this. You can automate `ChangeLog' maintance with Emacs using the
M-x add-change-log-entry-other-window. It may be easier to bind a key (for example f8) to this command by adding:
(global-set-key [f8] 'add-change-log-entry-other-window)
to your `.emacs' file. Then, after having made a modification and while the cursor is still at the place where you made the modification, press f8 and record your entry. Recently Emacs has decided to use the ISO 8601 standard for dates which is: YYYY-MM-DD (year-month-date). A typical `ChangeLog' entry looks like this:
1998-05-17 Eleftherios Gkioulekas <lf@amath.washington.edu>
* src/acmkdir.sh: Now acmkdir will put better default content
to the files README, NEWS, AUTHORS, THANKS
Every entry contains all the changes you made within the period of a day. The most recent changes are listed at the top, the older changes slowly scroll to the bottom. If you are a vi user, please see section Editing with Vi and GNU Emacs. Emacs is actually a very powerful programming language for developing editors, and there exists a Vi clone called viper that you can use in the Emacs environment (see section Configuring GNU Emacs).
- COPYING Here you list the copyright terms of your distribution, in particular the GPL. This file will be generated for you automatically. You can also generate it with the
gpl utility:
% gpl -l COPYING
Copyright is a very important concern in the free software community. For the legal aspects of copyright see section Copyright and Free Software. For the philosophical aspects of copyright see section Philosophical issues.
Most of these files are easy to maintain. Later we will show you how to use `acmkdir' to create a new directory for a new distribution. The `acmkdir' utility will provide you with templates for all of these files from which you can begin editing.
If you are just writing programs for your own internal use and you don't plan to redistribute them, you don't really need to worry too much about copyright. However, if you want to give your programs to other people then copyright issues become relavant. The main reason why `autoconf' and `automake' were developed was to facilitate the distribution of source code by making packages autoconfiguring. So, if you want to use these tools, you probably also want to know something about copyright issues. The following sections will focus primarily on the legal issues surrounding software. For a discussion of the philosophical issues please see section Philosophical issues. At this point, I should point out that I am not a lawyer, this is not legal advice, and I do not represent the opinions of the Free Software Foundation.
When you create a work, like a computer program, or a novel, and so on, you automatically have a set of legal rights called copyright. This means that you have the right to forbid others to use, modify and redistribute your work. By default no-one, except you the owner, is allowed to do any of these things. To relax these restrictions, you need to enter into an agreement with other people individually when they receive a copy from you. Such an agreement is called a License Agreement, which potentially entails rights and obligations to both you and them. It is very important that the License is written by a lawyer, and invoked from every file that is part of the work, in order for that file to fall under the terms the License. This can be done either by including the full text of the license or by including a legalese reference to the full text of the License. In the free software community, we standardize on using primarily the GNU General Public License, which we will discuss in the next section.
Copyright is transferable. This means that you have the right to transfer most your rights, that we call copyright, to another person or organization, with the exception of the moral right. The moral right is your right to say that you were the first owner of the work. This transfer is called copyright assignment. The moral right will force others to credit you, even if you must assign your copyright to them. When a work is being developed by a team, it makes legal sense to transfer the copyright to a single organization that can then coordinate enforcement of the copyright. In the free software community, some people assign their software to the Free Software Foundation. The arrangement is that copyright is transfered to the FSF. The FSF then grants you all the rights back in the form of a License Agreement, and commits itself legally to distribute the work only as free software. If you want to do this, you should contact the FSF for more information. It is not a good idea to assign your copyright to anyone else, unless you know very well that this is what you want to do.
The legal meaning of the word "use", as it refers to software, is peculiar, because software itself is very peculiar compared to all other forms of copyrighted work. For an executable program, "use" means to run it. But, for a library "use" refers to the act of linking it to your program. Copyright also covers derived work. If someone takes your code and modifies it, he is legally bound by the conditions under which you permitted him to do that. Similarly, if he links against a library that you wrote, then although he has a copyright to his code, he is bound by the license agreement that allowed him to do the linking, and he can only license his work in way that is also consistent with that agreement.
The concept of derived work is actually very slippery ground. Supposedly, what is copyrighted is not the algorithm but the implementation. What this means is that if you take someone's code, fire up an editor and modify it, then the resulting code is derived work. If you take someone's code understand the idea behind the implementation and reimplement the idea, then it is not derived work, even if the two end-results are remarkably similar, which they will be if the idea is very simple. So the property of a work being derived is not an inherent property of the work itself, but of the process with which you created the work. In practical terms, it's derived work if a judge says so in court.
Because copyright law is by default restrictive, you must explicitly grant permissions to your users to enable them to use your work. You do this, when you grant them a License Agreement. Even though the user never signs the agreement, nothing else grants the user any rights, so merely by using the program, the user is bound by the agreement. With some proprietary software, you are bound by the agreement the minute you break the seal in the packaging to unpack the box that contains the media with your software.
In addition to copyright law, there is another legal beast: the patent law. Unlike copyright, which you own automatically by the act of creating the work, you don't get a patent unless you file an application for it. If approved, the work is published but others must pay you royalties in order to use it in any way.
The problem with patents is that they cover algorithms, and if an algorithm is patented you can't write an implementation for it without a license. What makes it worse is that it is very difficult and expensive to find out whether the algorithms that you use are patented or will be patented in the future. What makes it insane is that the patent office, in its infinite stupidity, has patented algorithms that are very trivial with nothing innovative about them. For example, the use of backing store in a multiprocesing window system, like X11, is covered by patent 4,555,775. In the spring of 1991, the owner of the patent, AT&T, threatened to sue every member of the X Consortium including MIT. Backing store is the idea that the windowing system save the contents of all windows at all times. This way, when a window is covered by another window and then exposed again, it is redrawn by the windowing system, and not the code responsible for the application. Other insane patents include the IBM patent 4,674,040 which covers "cut and paste between files" in a text editor. Recently, a Microsoft backed company called "Wang" took Netscape to court over a patent that covered "bookmarks"! Wang lost.
Although most of these patents don't stand a chance in court, the cost of litigation is sufficient to terrorize small bussinesses, non-profit organizations like the Free Software Foundation, as well as individual software developers. For this reason, companies are all too eager to patent whatever they can get away with patenting to protect themselves from being sued by others, further complicating this problem. In practice, you will not be sued unless your code threatens the interests of a big corporation, or if a big corporation's lawyers get too much time on their hands.
An additional legal burden to both copyrights and patents is governmental paranoia over encryption algorithms. According to the US government, a computer program implementing an encryption algorithm is considered ammunition, therefore export-control laws on ammunition apply. What is not allowed under these laws is to export the software outside the borders of the US. The government is pushing the issue by claiming that making encryption software available on the internet is the same thing as exporting it. Zimmermann, the author of a popular encryption program, was sued by the government based on this interpretation of the law. However the government's position was not tested at court because the government decided to drop the charges, after dragging the case for a few years, long enough to send a message of terror to the internet community. The current wisdom seems to be that it is okey to make encryption software available on the net provided that you take strong measures that will prevent foreigners to download your work. It should be noted however that doing so still is taking a legal risk that could land you to Federal Prison. The munitions law thinks of your program as an atomic bomb. A mathematical description of an encryption algorithm is similar to writing a book about nuclear reactions and is allowed by the Constitution as your inalienable right to freedom of speach. Even so, it is not unusual for the NSA to suppress the publication of new algorithms that they have indepedently discovered invoking "matters of national security".
Other countries also have restrictive laws against encryption. In certain places you may not be even allowed to run such programs. The reason why governments are so paranoid of encryption is because it is the key to a wide array of technologies that empower the individual citizens to circumvent governmental snooping on our privacies. The US export laws however hurt US bussiness interests, and they are pointless since good encryption software is available on the internet in other countries.
Both copyright and patent laws are being used mainly to destroy our freedom. By freedom we refer to three things: the freedom to use software, the freedom to modify it and improve it, and the freedom to redistribute it with the modifications and improvements so that the whole community benefits. These freedoms are very important to the free software community. This is why it is important to know the laws, so that we can defend our freedoms from those who would like to take them from us. For a detailed discussion of these issues please see section Philosophical issues.
The prefered way to free your software is to distribute it under the terms of the GNU General Public License, also known as the "GPL". To best understand the GPL, you simply have to sit down and read the original document very carefully. In broad strokes, the license does the following:
- Grants you unrestricted permission to run the software and maintain as many copies as you like. You can also make personal custom modifications and use them freely. The GNU GPL does not restrict what you do in the privacy of your own computer in any way. On the contrary it waives all the restrictions that the copyright law applies to private use. It only kicks in when you distribute the software you have received to other people.
- Grants permission to redistribute the software or modified versions (derived work) provided that you do so only under the terms of the GNU public license. This means that if you make any changes, they must also be free. This protects the freedom of the package by forbidding someone to make a free version proprietary. This measure is called copyleft because it subverts the copyright law to do the opposite of what copyright is normally used for (i.e. to prevent a user to make a proprietary package free). The GNU GPL does not oblidge you to distribute your modifications. It only requires that you distribute them freely, if you choose to distribute them at all. The decision of whether or not to distribute your derived work is entirely up to you.
- Disclaims all warranty to protect the authors from lawsuits, including various implied warranties such as the warranty for merchantability and fitness for a particular purpose.
- Protects the software's freedom from patents as much as this is possible. The scenario that we want to avoid is someone receiving the source code, and then filing a patent application for the algorithms it uses, effectively making the software proprietary. If you do that, the GPL will forbid you from redistributing the software as well as derived work. So you will not want to do it. The patent law itself will prevent someone else, who distributes a competing product, to patent the algorithm if your implementation predates his.
The purpose of the GPL is to use the copyright law to encourage a world in which software is not copyrighted. If copyright didn't cover software, then we would all be free to use, modify and redistribute software, and we would not be able to restrict others from enjoying these freedoms because there would be no law giving anyone such power. One way to grant the freedoms to the users of your software is to revoke your copyright on the software completely. This is called putting your work in the public domain. The problem with this is that it only grants the freedoms. It does not create the reality in which no-one can take these freedoms away from derived works. In fact the copyright law covers by default derived works regardless of whether the original was public domain or copyrighted. By distributing your work under the GPL, you grant the same freedoms, and at the same time you protect these freedoms from hoarders.
The GNU GPL is a legal instrument that has been designed to create a safe haven in which software can be written free from copyright law encumberence. It allows developers to freely share their work with a friendly community that is also willing to share theirs, and at the same time protect them from being exploited by publishers of proprietary software.
To apply the GPL to your programs you need to do the following things:
- Attach a copy of the GNU public license to the toplevel directory of your source code in a file called `COPYING'.
- Include a legal notice to every file that you want covered by the GPL, saying that it is covered by the GPL. It is important that all files that constitute source code must include this notice, including `Makefile.am', `configure.in' files and shell scripts. The legal notice should look like this:
// Copyright (C) (year) (Your Name) <your@email.address>
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
If you have assigned your copyright to an organization, like the Free Software Foundation, then you should probably fashion your copyright notice like this:
// Copyright (C) (year) Free Software Foundation
// (your name) <your@email.address> (initial year)
// etc...
This legal notice works like a subroutine. By invoking it, you invoke the full text of the GNU General Public License which is too lengthy to include in every source file. Where you see `(year)' you need to list all the years in which you finished preparing a version that was actually released, and which was an ancestor to the current version. This list is not the list of years in which versions were released. It is a list of years in which versions, later released, were completed. If you finish a version on Dec 31, 1997 and release it on Jan 1, 1998, you need to include 1997, but you do not need to include 1998. This rule is complicated, but it is dictated by international copyright law.
- If your file is part of a library, and it invokes the GPL, then this causes the entire library to be under the GPL. When you link a GPLed library to produce an executable, then the executable is also under the GPL. This prevents people from distributing proprietary software that uses your library. In general, this is a good thing because it promotes the development of more free software. In some cases however, if your library aspires to implement a standard which you want to advocate, you may want to allow proprietary developers to use your library, while at the same time protecting the freedom of the library. The main reason for wanting to do this is not to give proprietary developers a freebie, but to benefit free software by allowing proprietary developers to make their software interopable with free software. One way to do this is to invoke the GNU GPL and then add the following additional legal wording:
// As a special exception, permission is granted for additional uses of
// the text contained in its release of LIB.
//
// The exception is that, if you link the LIB library with other files
// to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the LIB library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name LIB. If you copy code from other releases into a copy of
// LIB, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for LIB, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
Make sure to substitute "LIB" with the name of your library. This wording is used by the GNU project in the GUILE library. Similar terms are also used for the GNU C++ Standard Library to allow proprietary developers to use the GNU compiler. It is important to understand that you can not take a GPLed file, and slap this additional wording to it, without the original authors permission. You can however, at your option, use this wording in files that are your own original work. Also, if a file already invokes such wording, you can at your option retain or discard the wording in derived versions. Finally, if the library is linking any files that do not invoke this wording, then the permissions do not apply to the library as a whole, and if you link it to an executable, then you can not distribute that executable under a proprietary license. The individual files however, that do contain this notice, can be used to form a library that you can link into a proprietary executable, if that is technically possible.
- For files hat are not really source code, like Makefiles and Autoconf macros, you should use this alternative wording instead:
// This file is free software; as a special exception the author gives
// unlimited permission to copy and/or distribute it, with or without
// modifications, as long as this notice is preserved.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Note that this notice is very liberal. Please use it mainly for cases where you'd find it absurd to claim copyright. Such cases are mainly cases where it is rather hard to distinguish derived work from original work because it's all so similar.
- Use the `AUTHORS' file to keep records of who wrote what. These records will be important if you decide at some point to register your copyright. They are also important if you plan to assign your work to the FSF, because they will want to register the copyright. We discuss this in more detail later.
- If you modify someone else's GPL covered file make sure to comply with section 2 of the GPL. To do that place notices stating that you changed the file and the date of the change. Also your program should advertise the fact that it is free software, that there is no warranty and that it can be redistributed under the condition of the GPL. A standard way of doing this is to make your program output this notice when it is passed the
--version command-line flag. For details please read the GPL. Also see the GNITS conding standards for suggestions on the output of --version and --help, keeping in mind that these are simply suggestions.
You may feel that all this legal crap is stupid, and you just want to write code and get your work done. Every true hacker feels the same way and resents the fact that to code nowadays we have to have this sort of legal education. However unless you apply some license to your program, you are not granting anyone any permissions whatsoever. The `gpl' utility has been written to help you bother maintain the legalese. Many people write free software with ambiguous copyright terms, making it unusable to people who want to be precise about using the GNU GPL.
Maintaining these legalese notices can be quite painful after some time. To ease the burden, Autotools distributes a utility called `gpl'. This utility will conveniently generate for you all the legal wording you will ever want to use. It is important to know that this application is not approved in any way by the Free Software Foundation. By this I mean that I haven't asked their opinion of it yet.
To create the file `COPYING' type:
% gpl -l COPYING
If you want to include a copy of the GPL in your documentation, you can generate a copy in texinfo format like this:
% gpl -lt gpl.texi
Also, every time you want to create a new file, use the `gpl' to generate the copyright notice. If you want it covered by the GPL use the standard notice. If you want to invoke the Guile-like permissions, then also use the library notice. If you want to grant unlimited permissions, meaning no copyleft, use the special notice. The `gpl' utility takes many different flags to take into account the different commenting conventions.
- For a C file, create the standard notice with
% gpl -c file.c
the library notice with
% gpl -cL file.c
and the special notice with
% gpl -cS file.c
- For a C++ file, create the standard notice with
% gpl -cc file.cc
the library notice with
% gpl -ccL file.cc
and the special notice with
% gpl -ccS file.cc
- For a shells script (bash, perl) that uses hash marks for commenting, create the standard notice with
% gpl -sh foo.pl
the library notice with
% gpl -shL foo.tcl
and the special notice with
% gpl -shS foo.pl
It does not make sense to use the library notice, if no executable is being formed from this file. If however, you parse that file into C code that is then compiled into object code, then you may consider using the library notice on it instead of the special notice. One of the features provided by Autotools allows you to embed text, such as Tcl scripts, into the executable. In that case, you can use the library notice to license the original text.
- For files that define autoconf macros:
% gpl -m4 file.m4
In general, we exempt autoconf macro files from the GNU GPL because the terms of autoconf also exclude its output, the `configure' script, from the GPL.
- For `Makefile.am', or files that describe targets:
% gpl -am Makefile.am
For these we also exempt them from the GPL because they are so trivial that it makes no sense to add copyleft protection.
If you are using GNU Emacs, then you can insert these copyright notices on-demand while you're editing your source code. Autotools bundles two Emacs packages: gpl and gpl-copying which provide you with equivalents of the `gpl' command that can be run under Emacs. These packages will be byte-compiled and installed automatically for you while installing Autotools.
To use these packages, in your `.emacs' you must declare your identity by adding the following commands:
(setq user-mail-address "me@here.com")
(setq user-full-name "My Name")
Then you must require the packages to be loaded:
(require 'gpl)
(require 'gpl-copying)
These packages introduce a set of Emacs commands all of which are prefixed as gpl-. To invoke any of these commands press M-x, type the name of the command and press enter.
The following commands will generate notices for your source code:
- `gpl-c'
- Insert the standard GPL copyright notice using C commenting.
- `gpl-cL'
- lnsert the standard GPL copyright notice using C commenting, followed by a Guile-like library exception. This notice is used by the Guile library. You may want to use it for libraries that you write that implement some type of a standard that you wish to encourage. You will be prompted for the name of your package.
- `gpl-cc'
- Insert the standard GPL copyright notice using C++ commenting.
- `gpl-ccL'
- Insert the standard GPL copyright notice using C++ commenting, followed by a Guile-like library exception. You will be prompted for the name of your package
- `gpl-sh'
- Insert the standard GPL copyright notice using shell commenting (i.e. has marks).
- `gpl-shL'
- Insert the standard GPL copyright notice using shell commenting, followed by a Guile-like library exception. This can be useful for source files, like Tcl files, which are executable code that gets linked in to form an executable, and which use hash marks for commenting.
- `gpl-shS'
- Insert the standard GPL notice using shell commenting, followed by the special Autoconf exception. This is useful for small shell scripts that are distributed as part of a build system.
- `gpl-m4'
- Insert the standard GPL copyright notice using m4 commenting (i.e. dnl) and the special Autoconf exception. This is the prefered notice for new Autoconf macros.
- `gpl-el'
- Insert the standard GPL copyright notice using Elisp commenting. This is useful for writing Emacs extension files in Elisp.
The following commands will generate notices for your source code:
- `gpl-insert-copying-texinfo'
- Insert a set of paragraphs very similar to the ones appearing at the Copying section of this manual. It is a good idea to include this notice in an
unnumbered chapter titled "Copying" in the Texinfo documentation of your source code. You will be prompted for the title of your package. That title will substitute the word Autotools as it appears in the corresponding section in this manual. - `gpl-insert-license-texinfo'
- Insert the full text of the GNU General Public License in Texinfo format. If your documentation is very extensive, it may be a good idea to include this notice either at the very beginning of your manual, or at the end. You should include the full license, if you plan to distribute the manual separately from the package as a printed book.
We begin at the beginning. If you recall, we showed to you that the hello world program can be compiled very simply with the following command:
% gcc hello.c -o hello
See section Hello world example. Even in this simple case you have quite a few options:
- The `-g' flag causes the compiler to output debugging information to the executable. This way, you can step your program through a debugger if it crashes.
- The `-O', `-O2', `-O3' flags activate optimization. Some compilers can go as far as `-O6'. These numbers are called optimization levels. When you compile your program with optimization enabled, the compiler applies certain algorithms to the machine code output to make it go faster. The cost is that your program compiles much more slowly and that although you can step it through a debugger if you used the `-g' flag, things will be a little strange. During development the programmer usually uses no optimization, and only activates it when he is about to run the program for a production run. A good advice: always test your code with optimization activated as well. If optimization breaks your code, then this is telling you that you have a memory bug. Good luck finding it.
- The `-Wall' flag tells the compiler to issue warnings when it sees bad programming style. Some of these warning catch actual bugs, but occasionally some of the warnings complain about something correct that you did on purpose. For this reason you control whether you want to see these warnings or not with this flag.
Here are some variations of the above example:
% gcc -g -O3 hello.c hello
% gcc -g -Wall hello.c -o hello
% gcc -g -Wall -O3 hello.c -o hello
Compilers have many more flags like that, and some of these flags are compiler dependent.
Now let's consider the case where you have a much larger program. made of source files `foo1.c', `foo2.c', `foo3.c' and header files `header1.h' and `header2.h'. One way to compile the program is like this:
% gcc foo1.c foo2.c foo3.c -o foo
This is fine when you have only a few files to deal with. Eventually when you have more than a hundred files, this is very slow and inefficient, because everytime you change one of the `foo' files, all of them have to be recompiled. In large projects this can very well take a quite a few minutes, and in very large projects hours. The solution is to compile each part seperately and put them all together at the end, like this:
% gcc -c foo1.c
% gcc -c foo2.c
% gcc -c foo3.c
% gcc foo1.o foo2.o foo3.o -o foo
The first three lines compile the three parts seperately and generate output in the files `foo1.o', `foo2.o', `foo3.o'. The fourth line puts it all back together. This way if you make a change only in `foo1.o' you just do:
% gcc -c foo1.c
% gcc foo1.o foo2.o foo3.o -o foo
This feature of the compiler offers a way out, but it's hardly a solution.
- Writing out these commands everytime becomes annoying very soon.
- When it is a header file that you modified, you need to figure out which source files included it and rebuild all of them for your change to take effect. If you forget to rebuild just one of the source files, this bug fix you just made may not work, and you will be all confused.
- Once you are done compiling you have all these `.o' files sitting around and you may want to have a safe way of getting rid of them. Typing
rm -f *.o
is dangerous because you may misspell `o' for `c' or you may do this:
rm -f * .o
and become depressed.
The `make' utility was written to address these problems.
The `make' utility takes its instructions from a file called `Makefile' in the directory in which it was invoked. The `Makefile' involves four concepts: the target, the dependencies, the rules, and the source. Before we illustrate these concepts with examples we will explain them in abstract terms for those who are mathematically minded:
- Source are the files that you wrote and which are present when the distribution is unpacked. A source file has no dependencies, but itself it may be a dependency to a target.
- Target is a file that you wish to generate from the source, or an action that you wish to cause (called phony target since no file by the name of the target is generated). For example when you type `make install' you do not generate a file called `install'. What you generate is the action of moving certain files in certain places. Generating the file or taking the action is called building the target. A target may have dependencies and it may itself be a dependency to another target.
- A Dependency can be either a source file or a target. Either way, a dependency is something that only targets have. Source files do not have dependencies. If the dependency is a source file, then we say that, as a dependency to a certain target, it is up-to-date if and only if the target's latest update happened after the dependency's latest update. We say that the dependency changed if and only if the target's latest update happened before the dependency's latest update. If the dependency itself is a target, then we define recursively that as a dependency to a certain target, it has changed if and only if at least one of its own dependencies has changed. A phony target is never up-to-date. If a phony target is a dependency to another target, then it will always cause that other target to be rebuilt. Okey, take a big breath and think about this a bit.
- Rules is a set of instructions that detail how to build a target if the dependencies of that target have changed. These instructions need to be issued if and only if at least one of the dependencies has changed, and they must be issued only after the corresponding rules for the dependencies that have changed are recursively invoked. You may want to take a big breath here as well. Note that this recursion will be terminated only when it hits source files because they don't have any dependencies. Then it will wrap itself back up and work from bottom to top all the way to building the target at the top of the recursion.
The `Makefile' is essentially a collection of logical statements about these four concepts. The content of each statement in English is:
To build this target, first make sure that these dependencies are up to date. If not build them first in the order in which they are listed. Then execute these rules to build this target.
Given a complete collection of such statements it is possible to infer what action needs to be taken to build a specific target, from the source files and the current state of the distribution. By action we mean passing commands to the shell. One reason why this is useful is because if part of the building process does not need to be repeated, it will not be repeated. The `make' program will detect that certain dependencies have not changed and skip the action required for rebuilding their targets. Another reason why this approach is useful is because it is intuitive in human terms. At least, it will be intuitive when we illustrate it to you.
In make-speak each statement has the following form:
target: dependency1 dependency2 ....
shell-command-1
shell-command-2
shell-command-3
where target is the name of the target and dependency* the name of the dependencies, which can be either source files or other targets. The shell commands that follow are the commands that need to be passed to the shell to build the target after the dependencies have been built. To be compatible with most versions of make, you must seperate these statements with a blank line. Also, the shell-command* must be indented with the tab key. Don't forget your tab keys otherwise make will not work.
When you run make you can pass the target that you want to build as an argument. If you omit arguments and call make by itself then the first target mentioned in the Makefile is the one that gets built. The makefiles that Automake generates have the phony target all be the default target. That target will compile your code but not install it. They also provide a few more phony targets such as install, check, dist, distcheck, clean, distclean as we have discussed earlier. So Automake is saving you quite a lot of work because without it you would have to write a lot of repetitive code to provide all these phony targets.
To illustrate these concepts with an example suppose that you have this situation:
- Four source files: `foo1.c', `foo2.c', `foo3.c',`foo4.c'
- Three include files: `gleep1.h',`gleep2.h',`gleep3.h'
- `foo1.c' includes `gleep2.h' and `gleep3.h'
- `foo2.c' includes `gleep1.h'
- `foo3.c' includes `gleep1.h' and `gleep2.h'
- `foo4.c' includes `gleep3.h'
To build an executable `foo' you need to build object files and then link them together. We say that the executable depends on the object files and that each object file depends on a corresponding `*.c' file and the `*.h' files that it includes. Then to get to an executable `foo' you need to go through the following dependencies:
foo: foo1.o foo2.o foo3.o foo4.o
foo1.o: foo1.c gleep2.h gleep3.h
foo2.o: foo2.c gleep1.h
foo3.o: foo3.c gleep1.h gleep2.h
foo4.o: foo4.c gleep3.h
The thing on the left-hand-side is the target, the thing on the right-hand-side is the dependencies. The logic is that to build the thing on the left, you need to build the things on the right first. So, if `foo1.c' changes, `foo1.o' must be rebuilt. If `gleep3.h' changes then `foo1.o' and `foo4.o' must be rebuilt. That's the game.
The way the `Makefile' actually looks like is like this:
foo: foo1.o foo2.o foo3.o foo4.o
gcc foo1.o foo2.o foo3.o foo4.o -o foo
foo1.o: foo1.c gleep2.h gleep3.h
gcc -c foo1.c
foo2.o: foo2.c gleep1.h
gcc -c foo2.c
foo3.o: foo3.c gleep1.h gleep2.h
gcc -c foo3.c
foo4.o: foo4.c gleep3.h
gcc -c foo4.c
It's the same thing as before except that we have supplemented the rules by which the target is built from the dependencies. Things to note about syntax:
- The rules must be indented with a tab. To get a tab you must press the TAB key on your keyboard.
- Each statement must be separated from the next statement with a blank line.
- The first target is what gets built when you type simply
% make
Therefore, the target for the executable must go at the beginning.
If you omit the tabs or the blank line, then the Makefile will not work. Some versions of `make' have relaxed the blank line rule, since it's redundant, but to be portable, just put the damn blank line in.
You may ask, "how does `make' know what I changed?". It knows because UNIX keeps track of the exact date and time in which every file and directory was modified. This is called the Unix time-stamp. What happens then is that `make' checks whether any of the dependencies is newer than the main target. If so, then the target must be rebuilt. Cool. Now do the target's dependencies have to be rebuilt? Let's look at their dependencies and find out! In this recursive fashion, the logic is untangled and `make' does the Right Thing.
The `touch' command allows you to fake time-stamps and make a file look as if it has been just modified. This way you can force make to rebuild everything by saying something like:
% touch *.c *.h
If you are building more than one executable, then you may want to make a phony target all be the first target:
all: foo1 foo2 foo3
Then calling make will attempt to build all and that will cause make to loop over `foo1', `foo2', `foo3' and get them built. Of course you can also tell make to build these individually by typing:
% make foo1
% make foo2
% make foo3
Anything that is a target can be an argument. You might even say
% make bar.o
if all you want is to build a certain object file and then stop.
The main problem with maintaining Makefiles, in fact what we mean when we complain about maintaining Makefiles, is keeping track of the dependencies. The `make' utility will do its job if you tell it what the dependencies are, but it won't figure them out for you. There's a good reason for this of course, and herein lies the wisdom of Unix. To figure out the dependencies, you need to know something about the syntax of the files that you are working with!. And syntax is the turf of the compiler, and not `make'. The GNU compiler honors this responsibility and if you type:
% gcc -MM foo1.c
% gcc -MM foo2.c
% gcc -MM foo3.c
% gcc -MM foo4.c
it will compute the dependencies and put them out in standard output. Even so, it is clear that something else is needed to take advantage of this feature, if available, to generate a correct `Makefile' automatically. This is the main problem for which the only work-around is to use another tool that generates Makefiles.
The other big problem comes about with situations in which a software project spans many subdirectories. Each subdirectory needs to have a Makefile, and every Makefile must have a way to make sure that `make' gets called recursively to handle the subdirectories. This can be done, but it is quite cumbersome and annoying. Some programmers may choose to do without the advantages of a well-organized directory tree for this reason.
There are a few other little problems, but they have for most part solutions within the realm of the `make' utility. One such problem is that if you move to a system where the compiler is called `cc' instead of `gcc' you need to edit the Makefile everywhere. Here's a solution:
CC = gcc
#CFLAGS = -Wall -g -O3
CFLAGS = -Wall -g
foo: foo1.o foo2.o foo3.o foo4.o
$(CC) $(CFLAGS) foo1.o foo2.o foo3.o foo4.o -o foo
foo1.o: foo1.c gleep2.h gleep3.h
$(CC) $(CFLAGS) -c foo1.c
foo2.o: foo2.c gleep1.h
$(CC) $(CFLAGS) -c foo2.c
foo3.o: foo3.c gleep1.h gleep2.h
$(CC) $(CFLAGS) -c foo3.c
foo4.o: foo4.c gleep3.h
$(CC) $(CFLAGS) -c foo4.c
Now the user just has to modify the first line where he defines the macro-variable `CC', and whatever he puts there gets substituted in the rules bellow. The other macro variable, `CFLAGS' can be used to turn optimization on and off. Putting a `#' mark in the beginning of a line, makes the line a comment, and the line is ignored.
Another problem is that there is a lot of redundancy in this makefile. Every object file is built from the source file the same way. Clearly there should be a way to take advantage of that right? Here it is:
CC = gcc
CFLAGS = -Wall -g
.SUFFIXES: .c .o
.c.o:
$(CC) $(CFLAGS) -c ___FCKpd___72lt;
.o:
$(CC) $(CFLAGS) ___FCKpd___72lt; -o $@
foo: foo1.o foo2.o foo3.o foo4.o
foo1.o: foo1.c gleep2.h gleep3.h
foo2.o: foo2.c gleep1.h
foo3.o: foo3.c gleep1.h gleep2.h
foo4.o: foo4.c gleep3.h
Now this is more abstract, and has some cool punctuation. The `SUFFIXES' thing tells `make' that files that are possible targets, fall under three categories: files that end in `.c', files that end in `.o' and files that end in nothing. Now let's look at the next line:
.c.o:
$(CC) $(CFLAGS) -c ___FCKpd___73lt;
This line is an abstract rule that tells `make' how to make `.o' files from `.c' files. The punctuation marks have the following meanings:
- `$<'
- are the dependencies that changed causing the target to need to be rebuilt
- `$@'
- is the target
- `$^'
- are all the dependencies for the current rule
In the same spirit, the next rule tells how to make the executable file from the `.o' files.
.o:
$(CC) $(CFLAGS) ___FCKpd___74lt; -o $@
All that has to follow the abstract rules is the dependencies, without the specific rules! If you are using `gcc' these dependencies can be generated automatically and then you can include them from your Makefile. Unfortunately this approach doesn't work with all of the other compilers. And there is no standard way to include another file into Makefile source. (1) Of course, what we will point out eventually is that `automake' can take care of the dependencies for you.
The Makefile in our example can be enhanced in the following way:
CC = gcc
CFLAGS = -Wall -g
OBJECTS = foo1.o foo2.o foo3.o foo4.o
PREFIX = /usr/local
.SUFFIXES: .c .o
.c.o:
$(CC) $(CFLAGS) -c ___FCKpd___75lt;
.o:
$(CC) $(CFLAGS) ___FCKpd___75lt; -o $@
foo: $(OBJECTS)
foo1.o: foo1.c gleep2.h gleep3.h
foo2.o: foo2.c gleep1.h
foo3.o: foo3.c gleep1.h gleep2.h
foo4.o: foo4.c gleep3.h
clean:
rm -f $(OBJECTS)
distclean:
rm -f $(OBJECTS) foo
install:
rm -f $(PREFIX)/bin/foo
cp foo $(PREFIX)/bin/foo
We've added three fake targets called `clean' and `distclean', `install' and introduced a few more macro-variables to control redundancy. I am sure some bells are ringing now. When you type:
% make
the first target (which is `foo') gets build, and your program compiles. When you type
% make install
since there is no file called `install' anywhere, the rule there is executed which has the effect of copying the executable over at `/usr/local/bin'. To get rid of the object files,
% make clean
and to get rid of the executable as well
% make distclean
Such fake targets are called phony targets in makefile parlance. As you can see, the `make' utility is quite powerful and there's a lot it can do. If you want to become a `make' wizard, all you need to do is read the GNU Make Manual and waste a lot of time spiffying up your makefiles, instead of getting your programs debugged, The GNU Make manual is extremely well written, and will make for enjoyable reading. It is also free, unlike "published" books.
The reason we went to the trouble to explain `make' is because it is important to understand what happens behind the hood, and because in many cases, `make' is a fine thing to use. It works for simple programs. And it works for many other things such as formatting TeX documents and so on.
As we evolve to more and more complicated projects, there's two things that we need. A more high-level way of specifying what you want to build, and a way of automatically determining the values that you want to put to things like CFLAGS, PREFIX and so on. The first thing is what `automake' does, the second thing is what `autoconf' does.
There's one last thing that we need to mention before moving on, and that's libraries. As you recall, to put together an executable, we make a whole bunch of `.o' files and then put them all together. It just so happens in many cases that a set of `.o' files together forms a cohesive unit that can be reused in many applications, and you'd like to use them in other programs. To make things simpler, what you do is put the `.o' files together and make a library.
A library is usually composed of many `.c' files and hopefully only one or at most two `.h' files. It's a good practice to minimize the use of header files and put all your gunk in one header file, because this way the user of your library won't have to be typing an endless stream of `#include' directives for every `.c' file he writes that depends on the library. Be considerate. The user might be you! Header files fall under two categories: public and private. The public header files must be installed at `/prefix/include' whereas the private ones are only meant to be used internally. The public header files export documented library features to the user. The private header files export undocumented library features that are to be used only by the developer of the library and only for the purpose of developing the library.
Suppose that we have a library called `barf' that's made of the following files:
`barf.h', `barf1.c', `barf2.c', `barf3.c'
In real life, the names should be more meaningful than that, but we're being general here. To build it, you first make the `.o' files:
% gcc -c barf1.c
% gcc -c barf2.c
% gcc -c barf3.c
and then you do this magic:
% rm -f libbarf.a
% ar cru libbarf.a barf1.o barf2.o barf3.o
This will create a file libbarf.a from the object files `barf1.o', `barf2.o', `barf3.p'. On most Unix systems, the library won't work unless it's "blessed" by a program called `ranlib':
% ranlib libbarf.a
On other Unix systems, you might find that `ranlib' doesn't even exist because it's not needed.
The reason for this is historical. Originally ar was meant to be used merely for packaging files together. The more well known program tar is a descendent of ar that was designed to handle making such archives on a tape device. Now that tape devices are more or less obsolete, tar is playing the role that was originally meant for ar. As for ar, way back, some people thought to use it to package *.o files. However the linker wanted a symbol table to be passed along with the archive for the convenience of the people writing the code for the linker. Perhaps also for efficiency. So the ranlib program was written to generate that table and add it to the *.a file. Then some Unix vendors thought that if they incorporated ranlib to ar then users wouldn't have to worry about forgetting to call ranlib. So they provided ranlib but it did nothing. Some of the more evil ones dropped it all-together breaking many people's makefiles that tried to run ranlib. In the next chapter we will show you that Autoconf and Automake will automatically determine for you how to deal with ranlib in a portable manner.
Anyway, once you have a library, you put the header file `barf.h' under `/usr/local/include' and the `libbarf.a' file under `/usr/local/lib'. If you are in development phase, you put them somewhere else, under a prefix different other than `/usr/local'.
Now, how do we use libraries? Well, suppose that a program uses the barf function defined in the barf library. Then a typical program might look like:
// -* main.c *-
#include <stdio.h>
#include <barf.h>
main()
{
printf("This is barf!\n");
barf();
printf("Barf me!\n");
}
If the library was installed in `/usr/local' then you can compile like this:
% gcc -c main.c
% gcc main.o -o main -lbarf
Of course, if you did not install in `/prefix' instead of `/usr/local' or `/usr' then you are in trouble. Now you have to do it this way:
% gcc -I/prefix/include -c main.c
% gcc main.o -o main -L/prefix/lib -lbarf
The `-I' flag tells the compiler where to find any extra header files (like `barf.h') and the `-L' flag tells the compiler where to find any extra libraries (like `libbarf.a'). The `-lbarf' flag tells the compiler to bring in the entire `libbarf.a' library with all its enclosed `.o' files and link it in with whathaveyou to produce the executable.
If the library hasn't been installed yet, and is present in the same directory as the object file `main.o' then you can link them by passing its filename instead:
% gcc main.o libbarf.a -o main
Please link libraries with their full names if they haven't yet been installed under the prefix directory and reserve using the -l flag only for libraries that have already been installed. This is very important. When you use Automake it helps it keep the dependencies straight. And when you use shared libraries, it is absolutely essential.
Also, please pay attention to the order with which you link your libraries. When the linker links a library, it does not embed into the executable code the entire library, but only the symbols that are needed from the library. In order for the linker to know what symbols are really needed from any given library, it must have already parsed all the other libraries and object files that depend on that library! This implies that you first link your object files, then you link the higher-level libraries, then the lower-level libraries. If you are the author of the libraries, you must write your libraries in such a manner, that the dependency graph of your libraries is a tree. If two libraries depend on each other bidirectionally, then you may have trouble linking them in. This suggests that they should be one library instead!
While we are at the topic, when you compile ordinary programs like the hello world program what really goes on behind the scenes is this:
% gcc -c hello.c
% gcc -o hello hello.o -lc
This links in the C system library `libc.a'. The standard include files that you use, such as `stdio.h', `stdlib.h' and whathaveyou are all refering to various parts of these libraries. These libraries get linked in by default when the `-o' flag is present. Note that other C compilers may be calling their system libraries something else. For this reason the corresponding flags are assumed and you don't have to supply them.
The catch is that there are many functions that you think of as standard that are not included in the `libc.a' library. For example all the math functions that are declared in `math.h' are defined in a library called `libm.a' which is not linked by default. So if the hello world program needed the math library you should be doing this instead:
% gcc -c hello.c
% gcc -o hello hello.o -lm
On some old Linux systems it used to be required that you also link a `libieee.a' library:
% gcc -o hello hello.o -lieee -lm
More problems of this sort occur when you use more esoteric system calls like sockets. Some systems require you to link in additional system libraries such as `libbsd.a', `libsocket.a', `libnsl.a'. Also if you are linking Fortran and C code together you must also link the Fortran run-time libraries. These libraries have non-standard names and depend on the Fortran compiler you use. Finally, a very common problem is encountered when you are writing X applications. The X libraries and header files like to be placed in non-standard locations so you must provide system-dependent -I and -L flags so that the compiler can find them. Also the most recent version of X requires you to link in some additional libraries on top of libX11.a and some rare systems require you to link some additional system libraries to access networking features (recall that X is built on top of the sockets interface and it is essentially a communications protocol between the computer running the program and computer that controls the screen in which the X program is displayed.) Fortunately, Autoconf can help you deal with all of this. We will cover these issues in more detail in subsequent chapters.
Because it is necessary to link system libraries to form an executable, under copyright law, the executable is derived work from the system libraries. This means that you must pay attention to the license terms of these libraries. The GNU `libc' library is under the LGPL license which allows you to link and distribute both free and proprietary executables. The `stdc++' library is also under terms that permit the distribution of proprietary executables. The `libg++' library however only permits you to build free executables. If you are on a GNU system, including Linux-based GNU systems, the legalese is pretty straightforward. If you are on a proprietary Unix system, you need to be more careful. The GNU GPL does not allow GPLed code to be linked against proprietary library. Because on Unix systems, the system libraries are proprietary, their terms may not allow you to distribute executables derived from them. In practice, they do however, since proprietary Unix systems do want to attract proprietary applications. In the same spirit, the GNU GPL also makes an exception and explicitly permits the linking of GPL code with proprietary system libraries, provided that said libraries are system libraries. This includes proprietary `libc.a' libraries, the `libdxml.a' library in Digital Unix, proprietary Fortran system libraries like `libUfor.a', and the X11 libraries.
To begin, let's review the simplest example, the hello world program:
- `hello.c'
-
#include <stdio.h>
main()
{
printf("Howdy, world!\n");
}
- `Makefile.am'
-
bin_PROGRAMS = hello
hello_SOURCES = hello.c
- `configure.in'
-
AC_INIT(hello.cc)
AM_INIT_AUTOMAKE(hello,1.0)
AC_PROG_CC
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
The language of `Makefile.am' is a logic language. There is no explicit statement of execution. Only a statement of relations from which execution is inferred. On the other hand, the language of `configure.in' is procedural. Each line of `configure.in' is a command that is executed.
Seen in this light, here's what the `configure.in' commands shown do:
- The
AC_INIT command initializes the configure script. It must be passed as argument the name of one of the source files. Any source file will do.
- The
AM_INIT_AUTOMAKE performs some further initializations that are related to the fact that we are using `automake'. If you are writing your `Makefile.in' by hand, then you don't need to call this command. The two comma-separated arguments are the name of the package and the version number.
- The
AC_PROG_CC checks to see which C compiler you have.
- The
AC_PROG_INSTALL checks to see whether your system has a BSD compatible install utility. If not then it uses `install-sh' which `automake' will install at the root of your package directory if it's not there yet.
- The
AC_OUTPUT tells the configure script to generate `Makefile' from `Makefile.in'
The `Makefile.am' is more obvious. The first line specifies the name of the program we are building. The second line specifies the source files that compose the program.
For now, as far as `configure.in' is concerned you need to know the following additional facts:
As we explained before to build this package you need to execute the following commands:
% aclocal
% autoconf
% touch README AUTHORS NEWS ChangeLog
% automake -a
% configure
% make
The first three commands, are for the maintainer only. When the user unpacks a distribution, he should be able to start from `configure' and move on.
- The `aclocal' command installs a file called `aclocal.m4'. Normally, in that file you are supposed to place the definitions of any `autoconf' macros that you've written that happen to be in use in `configure.in'. We will teach you how to write `autoconf' macros later. The `automake' utility uses the
AM_INIT_AUTOMAKE macro which is not part of the standard `autoconf' macros. For this reason, it's definition needs to be placed in `aclocal.m4'. If you call `aclocal' with no arguments then it will generate the appropriate `aclocal.m4' file. Later we will show you how to use `aclocal' to also install your own `autoconf' macros.
- The `autoconf' command combines the `aclocal.m4' and `configure.in' files and produces the `configure' script. And now we are in bussiness.
- The `touch' command makes the files `README' and friends exist. It is important that these files exist before calling Automake, because Automake decides whether to include them in a distribution by checking if they exist at the time that you invoke `automake'. Automake must decide to include these files, because when you type `make distcheck' the presense of these files will be required.
- The `automake' command compiles a `Makefile.in' file from `Makefile.am' and if absent it installs various files that are required either by the GNU coding standards or by the makefile that will be generated.
If you are curious you can take a look at the generated `Makefile'. It looks like gorilla spit but it will give you an idea of how one gets there from the `Makefile.am'.
The `configure' script is an information gatherer. It finds out things about your system. That information is given to you in two ways. One way is through defining C preprocessor macros that you can test for directly in your source code with preprocessor directives. This is done by passing -D flags to the compiler. The other way is by making certain variables defined at the `Makefile.am' level. This way you can, for example, have the configure script find out how a certain library is linked, export is as a `Makefile.am' variable and use that variable in your `Makefile.am'. Also, through certain special variables, `configure' can control how the compiler is invoked by the `Makefile'.
As you may have noticed, the `configure' script in the previous example defines two preprocessor macros that you can use in your code: PACKAGE and VERSION. As you become a power-user of `autoconf' you will get define even more such macros. If you inspect the output of `make' during compilation, you will see that these macros get defined by passing `-D' flags to the compiler, one for each macro. When there is too many of these flags getting passed around, this can cause two problems: it can make the `make' output hard to read, and more importantly it can hit the buffer limits of various braindead implementations of `make'. To work around this problem, an alternative approach is to define all these macros in a special header file and include it in all the sources.
A hello world program using this technique looks like this
- `configure.in'
-
AC_INIT
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(hello,0.1)
AC_PROG_CXX
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
- `Makefile.am'
-
bin_PROGRAMS = hello
hello_SOURCES = hello.c
- `hello.c'
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
main()
{
printf("Howdy, pardner!\n");
}
Note that we call a new macro in `configure.in': AM_CONFIG_HEADER. Also we include the configuration file conditionally with the following three lines:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
It is important to make sure that the `config.h' file is the first thing that gets included. Now do the usual routine:
% aclocal
% autoconf
% touch NEWS README AUTHORS ChangeLog
% automake -a
Automake will give you an error message saying that it needs a file called `config.h.in'. You can generate such a file with the `autoheader' program. So run:
% autoheader
Symbol `PACKAGE' is not covered by acconfig.h
Symbol `VERSION' is not covered by acconfig.h
Again, you get error messages. The problem is that autoheader is bundled with the autoconf distribution, not the automake distribution, and consequently doesn't know how to deal with the PACKAGE and VERSION macros. Of course, if `configure' defines a macro, there's nothing to know. On the other hand, when a macro is not defined then there are at least two possible defaults:
#undef PACKAGE
#define PACKAGE 0
The autoheader program here complains that it doesn't know the defaults for the PACKAGE and VERSION macros. To provide the defaults, create a new file `acconfig.h':
- `acconfig.h'
-
#undef PACKAGE
#undef VERSION
and run `autoheader' again:
% autoheader
At this point you must run autoconf again, so that it takes into account the presense of acconfig.h:
% aclocal
% autoconf
Now you can go ahead and build the program:
% configure
% make
Computing dependencies for hello.cc...
echo > .deps/.P
gcc -DHAVE_CONFIG_H -I. -I. -I. -g -O2 -c hello.cc
gcc -g -O2 -o hello hello.o
Note that now instead of multiple -D flags, there is only one such flag passed: -DHAVE_CONFIG_H. Also, appropriate -I flags are passed to make sure that `hello.cc' can find and include `config.h'. To test the distribution, type:
% make distcheck
......
========================
hello-0.1.tar.gz is ready for distribution
========================
and it should all work out.
The `config.h' files go a long way back in history. In the past, there used to be packages where you would have to manually edit `config.h' files and adjust the macros you wanted defined by hand. This made these packages very difficult to install because they required intimate knowledge of your operating system. For example, it was not unusual to see a comment saying "if your system has a broken vfork, then define this macro". How the hell are you supposed to know if your systems vfork is broken?? With auto-configuring packages all of these details are taken care of automatically, shifting the burden from the user to the developer where it belongs.
Normally in the `acconfig.h' file you put statements like
#undef MACRO
#define MACRO default
These values are copied over to `config.h.in' and are supplemented with additional defaults for C preprocessor macros that get defined by native autoconf macros like AC_CHECK_HEADERS, AC_CHECK_FUNCS, AC_CHECK_SIZEOF, AC_CHECK_LIB.
If the file `acconfig.h' contains the string @TOP@ then all the lines before the string will be included verbatim to `config.h' before the custom definitions. Also, if the file `acconfig.h' contains the string @BOTTOM@ then all the lines after the string will be included verbatim to `config.h' after the custom definitions. This allows you to include further preprocessor directives that are related to configuration. Some of these directives may be using the custom definitions to conditionally issue further preprocessor directives. Due to a bug in some versions of autoheader if the strings @TOP@ and @BOTTOM@ do appear in your acconfig.h file, then you must make sure that there is at least one line appearing before @TOP@ and one line after @BOTTOM@, even if it has to be a comment. Otherwise, autoheader may not work correctly.
With `autotools' we distribute a utility called `acconfig' which will build `acconfig.h' automatically. By default it will always make sure that
#undef PACKAGE
#undef VERSION
are there. Additionally, if you install macros that are `acconfig' friendly then `acconfig' will also install entries for these macros. The acconfig program may be revised in the future and perhaps it might be eliminated. There is an unofficial patch to Autoconf that will automate the maintance of `acconfig.h', eliminating the need for a seperate program. I am not yet certain if that patch will be part of the official next version of Autoconf, but I very much expect it to. Until then, if you are interested, see: http://www.clark.net/pub/dickey/autoconf/autoconf.html This situation creates a bit of a dilemma about whether I should document and encourage acconfig in this tutorial or not. I believe that the Autoconf patch is a superior solution. However since I am not the one maintaining Autoconf, my hands are tied. For now let's say that if you confine yourself to using only the macros provided by autoconf, automake, and autotools then `acconfig.h' will be completely taken care for you by `acconfig'. In the future, I hope that acconfig.h will be generated by configure and be the sole responsibility of Autoconf.
You may be wondering whether it is worth using `config.h' files in the programs you develop if there aren't all that many macros being defined. My personal recommendation is yes. Use `config.h' files because perhaps in the future your `configure' might need to define even more macros. So get started on the right foot from the beginning. Also, it is nice to just have a config.h file lying around because you can have all your configuration specific C preprocessor directives in one place. In fact, if you are one of these people writing peculiar system software where you get to #include 20 header files on every single source file you write, you can just have them on all thrown into config.h once and for all. In the next chapter we will tell you about the LF macros that get distributed with autotools and this tutorial. These macros do require you to use the `config.h' file. The bottom line is: `config.h' is your friend; trust the config.h.
FIXME: write about VPATH builds and how to modify optimization
In software engineering, people start from a precise, well-designed specification and proceed to implementation. In research, the specification is fluid and immaterial and the goal is to be able to solve a slightly different problem every day. To have the flexibility to go from variation to variation with the least amount of fuss is the name of the game. By fuss, we refer to debugging, testing and validation. Once you have a code that you know gives the right answer to a specific set of problems, you want to be able to move on to a different set of similar problems with reinventing, debugging and testing as little as possible. These are the two distinct situations that computer programmers get to confront in their lives.
Software engineers can take good care of themselves in both situations. It's part of their training. However, people whose specialty is the scientific problem and not software engineering, must confront the hardest of the two cases, the second one, with very little training in software engineering. As a result they develop code that's clumsy in implementation, clumsy in usage, and with only redeeming quality the fact that it gives the right answer. This way, they do get the work of the day done, but they leave behind them no legacy to do the work of tomorrow. No general-purpose tools, no documentation, no reusable code.
The key to better software engineering is to focus away from developing monolithic applications that do only one job, and focus on developing libraries. One way to think of libraries is as a program with multiple entry points. Every library you write becomes a legacy that you can pass on to other developers. Just like in mathematics you develop little theorems and use the little theorems to hide the complexity in proving bigger theorems, in software engineering you develop libraries to take care of low-level details once and for all so that they are out of the way everytime you make a different implementation for a variation of the problem.
On a higher level you still don't create just one application. You create many little applications that work together. The centralized all-in-one approach in my experience is far less flexible than the decentralized approach in which a set of applications work together as a team to accomplish the goal. In fact this is the fundamental principle behind the design of the Unix operating system. Of course, it is still important to glue together the various components to do the job. This you can do either with scripting or with actually building a suite of specialized monolithic applications derived from the underlying tools.
The name of the game is like this: Break down the program to parts. And the parts to smaller parts, until you get down to simple subproblems that can be easily tested, and from which you can construct variations of the original problem. Implement each one of these as a library, write test code for each library and make sure that the library works. It is very important for your library to have a complete test suite, a collection of programs that are supposed to run silently and return normally (exit(0);) if they execute successfully, and return abnormally (assert(false); exit(1);) if they fail. The purpose of the test suite is to detect bugs in the library, and to convince you, the developer, that the library works. The best time to write a test program is as soon as it is possible! Don't be lazy. Don't just keep throwing in code after code after code. The minute there is enough new code in there to put together some kind of test program, just do it! I can not emphasize that enough. When you write new code you have the illusion that you are producing work, only to find out tomorrow that you need an entire week to debug it. As a rule, internalize the reality that you know you have produced new work everytime you write a working test program for the new features, and not a minute befor