17.4. Compilation

Now that the software is correctly configured, all that remains is for it to be compiled. This stage is usually easy, and does not set serious problems.

17.4.1. make

The favorite tool of the free software community to compile sources is make. It has two interests:

Actions that 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 the option -f with make.

17.4.2. Rules

make operates in accordance with a system of dependencies, so compiling a binary file ("target") requires to go 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 the source files.

This text is only a minimal introduction to survive in the merciless world of make. If you want to learn more, I advise you to go to website of APRIL, where you can find more detailed documentation about make. For an exhaustive documentation, refer to Managing Projects with Make, 2nd edition, O'Reilly, by Andrew Oram and Steve Talbott.

17.4.3. Go, go, go!

Usually, the use of make follows several conventions. For instance:

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

17.4.4. Explanations

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 that 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:

  1. CC: This is the compiler. Usually, it is cc, which is in most of free systems synonymous with gcc. When in doubt, put here gcc.

  2. LD: This is the program used to ensure the final compilation stage (see section The four steps of compilation). By default, this is ld.

  3. CFLAGS: These are the additional arguments that are given to the compiler during the first compilation stages. Among them:

    • -I<path>: Specifies to the compiler where to search some additional headers (eg: -I/usr/X11R6/include allows to include the headers that are in directory /usr/X11R6/include).

    • -D<symbol>: Defines an additional symbol, useful for programs whose compilations depend 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
  4. LDFLAGS (or LFLAGS): These are arguments used during the last compilation stage. Among them:

    • -L<path>: Specifies an additional path where to search for libraries (eg: -L/usr/X11R6/lib).

    • -l<library>: Specifies an additional library to use during the last compilation stage.

17.4.5. What if... it does not work?

Do not panic, it can happen to anyone. Among the most common causes:

  1. 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 have sometimes 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 [1]) 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 Technical support).

  2. 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 lacking or misused header. The correct procedure for solving the problem is:

    • try to check whether the structure in question is defined in 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 to what you have. If so, that means that the header is not included in the faulty .c file. There are two solutions:

      • add the line #include "<filename>.h" at the beginning of the faulty .c file.

      • or copy-paste the definition of the structure at the beginning of this file (it is not really neat, but at least it usually works).

    • 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 in which library (i.e. set of functions put together in a single package) it should be defined (see in the INSTALL or README file which are the libraries used by the program and their required versions). If the version that the program needs is not the one installed on your system, 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 Unices). Check also that you have correctly configured the program (when configure ran, for instance) for your architecture.

  3. parse error

    It is a problem that is quite complicated to solve, because it often is an error that appears at a certain line, but after that 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 that in the previous problem.

    Note

    there may be a parse error in the old curses libraries if my memory serves me right.

  4. no space left on device

    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 in making free space on the partition that contains the install directory (delete temporary files or sources, uninstall the programs you do not use). If you have uncompressed it in /tmp, rather do that in /usr/local/src, which avoids needlessly saturating the /tmp partition. Check furthermore whether there are core> files on your disk. If so, delete them or make them get deleted if they belong to another user.

  5. /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 bellow:

    1. 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 can not find the library, you will have to install it.

    2. 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 also can 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 your shell is bash).

    3. 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 another account than root and if the library is protected against read for example).

  6. glloq.c(.text+0x34): undefined reference to `glloq_init'

    It is a matter 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 know whether the symbol is supposed to be in a library. For instance, if it is a symbol beginning by gtk, it belongs to the gtk library. If the name of the library is hardly 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 to print the library name on each line, which make the searches easier. Let's imagine that we search 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 at the creation of the final binary file.

    • the compilation is made with a version of the library that is not the one allowed for the software. Read the README or INSTALL files of the distribution to know 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 know which one it is and add the corresponding .o file on the compilation line if it is missing.

    • the problem function or variable is maybe 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 an anarchic running of the software (segfault at start, etc).

  7. Segmentation fault (core dumped)

    Sometimes, the compiler hangs lamentably and produces this error message. I have no advise except asking you to install a more recent version of your compiler.

  8. no space on /tmp

    Compilation needs temporary workspace during the different stages; if it does not have space, it fails. So, you 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.

  9. 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 induce 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 put the files in argument at the current time) usually solves the problem.

    For instance:

    $ touch *

    Or also (more crude, but efficient):

    $ find . | xargs touch

Notes

[1]

Analyze the error message returned by make. Normally, the last lines should contain a directory (a message like make[1]: Leaving directory `/home/benj/Project/foo'). Pick out the one with the highest number. To check that it is the good one, go to the directory and execute make again to obtain the same error.


Tux on Star from MandrakeSoft Linux is a registered trademark of Linus Torvalds. All other trademarks and copyrights are the property of their respective owners.
Unless otherwise stated, all the content of these pages and all images are Copyright MandrakeSoft S.A. and MandrakeSoft Inc. 2001.
http://www.mandrakelinux.com/