Now that the software is correctly configured, all that remains is for it to be compiled. This stage is usually easy, and does not pose serious problems.
The favorite tool of the free software community to compile sources is make. It has two advantages:
Actions which must be
executed to obtain a compiled version of the sources are stored in a
file often named Makefile
or
GNUMakefile
. Actually, when make
is called, it reads this file – if it exists – in
the current directory. If not, the file may be specified by using
make's -f
option.
make operates in accordance with a system of
dependencies, so compiling a
binary file (“target ”) requires going
through several stages (“dependencies”). For instance, to
create the (imaginary) glloq
binary file, the
main.o
and init.o
object files
(intermediate files of the compilation) must be compiled and then
linked. These object files are also targets, whose dependencies are
their corresponding source files.
This text is only a minimal introduction to survival in the merciless world of make. For an exhaustive documentation, refer to Managing Projects with Make, 2nd edition, O'Reilly, by and .
Usually, the use of make follows several conventions. For instance:
make without argument just executes the compilation of the program, without installation.
make
install compiles the program (but not always), and then
installs the required files at the right place in the file system.
Some files are not always correctly installed
(man
, info
), they may have
to be copied by the user himself. Sometimes, make
install has to be executed again in sub-directories.
Usually, this happens with modules developed by third
parties.
make clean clears all the temporary files created by the compilation, and also the executable file in most cases.
The first stage is to compile the program, and therefore to type (imaginary example):
$ make gcc -c glloq.c -o glloq.o gcc -c init.c -o init.o gcc -c main.c -o main.o gcc -lgtk -lgdk -lglib -lXext -lX11 -lm glloq.o init.o main.o -o glloq
Excellent, the binary file is correctly compiled. We are ready to go to the next stage, which is the installation of the files of the distribution (binary files, data files, etc). See Section 5, “Installation”.
If you are curious enough to look in the
Makefile
file, you will find known commands
(rm, mv, cp, etc), but also strange
strings, looking like $(CFLAGS)
.
They are
variables which are strings which
are usually set at the beginning of the Makefile
file, and then replaced by the value they are associated with. It is
quite useful when you want to use the same compilation options several
times in a row.
For instance, to
print the string “foo
” on the screen
using make all:
TEST = foo all: echo $(TEST)
Most of the time, the following variables are set:
CC
:
This is the compiler. Usually, it is cc, which is in most
free systems synonymous with gcc. When in doubt, put
gcc here.
LD
:
This is the program used to ensure the final compilation stage (see
section Section 1.2.2, “The four steps of compilation”). By default, this is
ld.
CFLAGS
:
These are the additional arguments that are given to the compiler
during the first compilation stages. Among them:
-I<path>
:
Tells to the compiler where to search for some additional
headers (eg: -I/usr/X11R6/include
allows
inclusion of the header files that are in directory
/usr/X11R6/include
).
-D<symbol>
:
Defines an additional symbol, useful for programs whose
compilation depends on the defined symbols (ex: use the
string.h
file if
HAVE_STRING_H
is defined).
There are often compilation lines like:
$(CC) $(CFLAGS) -c foo.c -o foo.o
LDFLAGS
(or LFLAGS
): These are arguments used during the
final compilation stage. Among them:
Do not panic, it can happen to anyone. Among the most common causes:
glloq.c:16:
decl.h: No such file or directory
The compiler did not manage to find the corresponding header. Yet, the software configuration step should have anticipated this error. Here is how to solve this problem:
Check that
the header really exists on the disk in one of the following
directories: /usr/include
,
/usr/local/include
,
/usr/X11R6/include
or one of their
sub-directories. If not, look for it on the whole disk (with
find or locate), and if you still do not
find it, check that you have installed the library corresponding
to this header. You can find examples of the find and
locate commands in their respective manual
pages.
Check that
the header is really readable (type less
<path>/<file>.h
to test this)
If it is in a
directory like /usr/local/include
or
/usr/X11R6/include
, you sometimes have to
add a new argument to the compiler. Open the corresponding
Makefile
(be careful to open the right
file, those in the directory where the compilation fails
[36]) with your favorite text editor (Emacs,
Vi, etc). Look for the faulty line, and add the
string -I<path>
– where
<path>
is the path where the
header in question can be found – just after the call
of the compiler (gcc
, or sometimes
$(CC)
). If you do not know where to add this
option, add it at the beginning of the file, after
CFLAGS=<something>
or after
CC=<something>
.
Launch make again, and if it still does not work, check that this option (see the previous point) is added during compilation on the faulty line.
If it still does not work, call for help from your local guru or call for help from the free software community to solve your problem (see section Section 6.2, “Technical support”).
glloq.c:28:
`struct foo' undeclared (first use this function)
The structures are special data types that all programs use. A lot of them are defined by the system in headers. That means the problem is certainly caused by a missing or misused header. The correct procedure for solving the problem is:
try to check whether the structure in question is defined by the program or by the system. A solution is to use the command grep in order to see whether the structure is defined in one of the headers.
For instance, when you are in the root of the distribution:
$ find . -name '*.h'| xargs grep 'struct foo' | less
Many lines may appear on the screen (each time that a function using this type of structure is defined for instance). If it exists, pick out the line where the structure is defined by looking at the header file obtained by the use of grep.
The definition of a structure is:
struct foo { <contents of the structure> };
Check if it
corresponds with what you have. If so, this means that the
header is not included in the faulty .c
file. There are two solutions:
If not, do
the same thing with the system header files (which are usually
in directories /usr/include
,
/usr/X11R6/include
, or
/usr/local/include
). But this time, use the
line #include
<<filename>.h>
.
If this
structure still does not exist, try to find out which library
(i.e. set of functions put together in a single package) it
should be defined in (look in the INSTALL
or README
file to see which libraries are
used by the program and their required versions). If the version
that the program needs is not the one installed on your system,
you will need to update this library.
If it still does not work, check that the program properly works with your architecture (some programs have not been ported yet on all the UNIX® systems). Check also that you have correctly configured the program (when configure ran, for instance) for your architecture.
This is a problem that is quite complicated to solve, because it s often an error that appears at a certain line, but after the compiler has met it. Sometimes, it is simply a data type that is not defined. If you meet an error message like:
main.c:1: parse error before `glloq_t main.c:1: warning: data definition has no type or storage class
then the problem
is that the glloq_t
type is not defined. The
solution to solve the problem is more or less the same as that in
the previous problem.
This problem is easy to solve: there is not
enough space on the disk to generate a binary file from the
source file. The solution consists of making free space on
the partition which contains the install directory (delete
temporary files or sources, uninstall any programs you do
not use, resize the partition, etc.). Check if you
decompressed it in /tmp
, rather than in
/usr/local/src
, which avoids needlessly
saturating the /tmp
partition. Check
whether there are core
files[37] on your disk. If so, delete them
or make them get deleted if they belong to another
user.
/usr/bin/ld:
cannot open -lglloq: No such file or directory
That clearly
means that the ld program (used by gcc during
the last compilation stage) does not manage to find a library. To
include a library, ld searches for a file whose name is
in the arguments of type -l<library>
.
This file is lib<library>.so
. If
ld does not manage to find it, it produces an error
message. To solve the problem, follow the steps below:
Check that
the file exists on the hard disk by using the locate
command. Usually, the graphic libraries can be found in
/usr/X11R6/lib
. For instance:
$ locate libglloq
If the search is unrewarding, you can make a search with the find command (eg: find /usr -name "libglloq.so*"). If you still cannot find the library, you will have to install it.
Once the
library is located, check that it is accessible by
ld: the /etc/ld.so.conf
file specifies where to find these libraries. Add the
incriminate directory at the end (you may have to reboot your
computer for this to be taken into account). You can also add
this directory by changing the contents of the environment
variable LD_LIBRARY_PATH
. For instance, if
the directory to add is /usr/X11R6/lib
,
type:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib
If it still
does not work, check that the library format is an executable
file (or ELF) with the file command. If it is a
symbolic link, check that the link is good and does not point at
an non-existent file (for instance, with nm
libglloq.so). The permissions may be wrong (if you use
an account other than root
and if the library is
protected against reading, for example).
glloq.c(.text+0x34):
undefined reference to `glloq_init'
It is a problem of a symbol that was not solved during the last compilation stage. Usually, it is a library problem. There may be several causes:
the first
thing to do is to find out whether the symbol is
supposed to be in a library. For instance,
if it is a symbol beginning with gtk
, it
belongs to the gtk
library. If the name of
the library is easily identifiable
(frobnicate_foobar
), you may list the
symbols of a library with the nm command. For
example,
$ nm libglloq.so 0000000000109df0 d glloq_message_func 000000000010a984 b glloq_msg 0000000000008a58 t glloq_nearest_pow 0000000000109dd8 d glloq_free_list 0000000000109cf8 d glloq_mem_chunk
Adding the
-o
option to nm allows you
to print the library name on each line, which makes the search
easier. Lets imagine that we are searching for the symbol
bulgroz_max
, a crude solution is to make a
search like:
$ nm /usr/lib/lib*.so | grep bulgroz_max $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max $ nm /usr/local/lib/lib*.so | grep bulgroz_max /usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max
Wonderful!
The symbol bulgroz_max
is defined in the
frobnicate
library (the capital letter
T
is before its name). Then, you only have to
add the string -lfrobnicate
in the
compilation line by editing the Makefile
file: add it at the end of the line where
LDFLAGS
or LFGLAGS
(or
CC
at worst) are defined, or on the line
corresponding to the creation of the final binary file.
the
compilation is being made with a version of the library which is
not the one allowed for by the software. Read the
README
or INSTALL
files of the distribution to see which version must be
used.
not all the
object files of the distribution are correctly linked. The file
where this function is defined is lacking. Type nm -o
*.o to see which one it is and add the corresponding
.o
file on the compilation line if it is
missing.
the problem function or variable may be non-existent. Try to delete it: edit the problem source file (its name is specified at the beginning of the error message). It is a desperate solution whose consequence will certainly be a chaotic execution of the program with a (segfault at startup, etc).
Segmentation
fault (core dumped)
Sometimes, the compiler hangs immediately and produces this error message. I have no advise except suggesting that you install a more recent version of your compiler.
Compilation needs temporary workspace during
the different stages; if it does not have space, it
fails. So, you may have to clean the partition, but be
careful some programs being executed (X server,
pipes, etc.) can hang if some files are deleted. You must
know what you are doing! If /tmp
is
part of a partition that does not only contain it (for
example the root), search and delete some possible
core
files. Resizing is also an
option, if there's enough free space or some other partition
can be temporarily reduced.
make/configure in infinite recursion
It is often a problem of time in your system. Indeed, make needs to know the date in the computer and the date of the files it checks. It compares the dates and uses the result to know whether the target is more recent than the dependence.
Some date problems may cause make to endlessly build itself (or to build and build again a sub-tree in infinite recursion). In such a case, the use of touch (whose use here is to set the files in question to the current time) usually solves the problem.
$ touch *
Or also (cruder, but efficient):
$ find . | xargs touch
[36] Analyze the error message returned by
make. Normally, the last lines should contain a
directory (a message like make[1]: Leaving
directory `/home/queen/Project/foo'
). Pick
out the one with the highest number. To check that it is the
good one, go to that directory and execute make
again to obtain the same error.
[37] File generated by the system when a process tries to access a memory location that it is not allowed to. These files are used to analyze the reason of such a behavior to correct the problem.