This document may be copied and distributed provided that George Peter Staplin is given credit.
This tutorial consists of an explanation of using common flags with GCC to fix software that does not compile, examples to help you compile your own programs, and information about creating a simple makefile.
The most common type of errors when compiling software from source code are caused by the include and library paths not being correct. The authors system may have include files and libraries in different places, and/or symbolic links to include files or libraries.
A source code file named x_draw.c will be compiled that uses the X Window System. The example below lists errors about missing X11 header/include files, despite the fact that they exist on the system. The problem is that the compiler does not know the path to the header/include files.
$ gcc x_draw.c x_draw.c:5: X11/Xlib.h: No such file or directory x_draw.c:6: X11/Xutil.h: No such file or directory x_draw.c:7: X11/keysym.h: No such file or directory x_draw.c:8: X11/keysymdef.h: No such file or directory x_draw.c:9: jpeglib.h: No such file or directory
To tell the compiler the path to the X11 include files -I/usr/X11R6/include is used.
$ gcc x_draw.c -I/usr/X11R6/include x_draw.c:9: jpeglib.h: No such file or directory
To fix the last include file error message the compiler needs to know the path to the jpeglib.h header file. On this system it is located in /usr/local/include.
$ gcc x_draw.c -I/usr/X11R6/include -I/usr/local/include
The compiler will now try to link the object file into an executable. An object file ends with an .o extension. On this system when the linking begins many errors appear.
/var/tmp/ccH14605.o: Undefined symbol `_jpeg_std_error' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_stdio_src' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_read_header' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_start_decompress' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_destroy_decompress' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_read_scanlines' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_finish_decompress' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_jpeg_destroy_decompress' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_XFreeGC' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_XDestroyWindow' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_XFlush' referenced from text segment /var/tmp/ccH14605.o: Undefined symbol `_XCloseDisplay' referenced from text segment
The beginning errors are jpeg functions. To solve the JPEG errors the linker needs to be told which libraries to link with. On this system the path to the JPEG library is /usr/local/lib/libjpeg.a. There are two ways to tell the linker the path to the JPEG library, which are demonstrated in the examples below.
Example 1$ gcc x_draw.c -I/usr/X11R6/include -I/usr/local/include /usr/local/lib/libjpeg.aExample 2
$ gcc x_draw.c -I/usr/X11R6/include -I/usr/local/include -L/usr/local/lib -ljpeg
The first example specifies the full path to the library. The second example tells the linker to look in the /usr/local/lib directory and to use the jpeg library. The linker option -l instructs the linker to use a library that has the string jpeg in it. Sometimes the linker will be confused by the available libraries in a directory if -l is used, in such cases specifying the full path is generally a good idea.
When compiling with the jpeg flag the linker is listing errors about undefined X symbols.
$ gcc x_draw.c -I/usr/X11R6/include -I/usr/local/include -L/usr/local/lib -ljpeg /var/tmp/ccl31739.o: Undefined symbol `_XOpenDisplay' referenced from text segment /var/tmp/ccl31739.o: Undefined symbol `_XCreateWindow' referenced from text segment /var/tmp/ccl31739.o: Undefined symbol `_XClearWindow' referenced from text segment /var/tmp/ccl31739.o: Undefined symbol `_XMapRaised' referenced from text segment
The solution is to instruct the compiler where the X libraries are and which library to link with. In this case the linker should link with libX11.a in /usr/X11R6/lib or the shared object (*.so) version of that library.
If you are uncertain which library contains the symbol for a particular function, you can use the nm program to find out what symbols a library or executable provides. Some programs may not have symbol information that nm can read. Symbol information can be removed from an executable using the strip program.
$ nm libX11.a | less
Context.o:
00000000 t _ResizeTable
00000268 T _XDeleteContext
00000218 T _XFindContext
00000120 T _XSaveContext
000000b0 t __XFreeContextDB
00000000 t ___gnu_compiled_c
U _calloc
U _free
U _malloc
00000000 t gcc2_compiled.
The ldd program provides concise information about executable library dependencies.
$ ldd x_draw
x_draw:
-lX11.6 => /usr/X11R6/lib/libX11.so.6.1 (0x4001c000)
-ljpeg.62 => /usr/local/lib/libjpeg.so.62.0 (0x400b2000)
-lc.23 => /usr/lib/libc.so.23.1 (0x400cf000)
By now the complete compile command looks something like this:
$ gcc x_draw.c -I/usr/X11R6/include -I/usr/local/include -L/usr/local/lib -ljpeg -L/usr/X11R6/lib -lX11
The program has successfully compiled and linked. The directory should now contain a file named a.out. This file can be executed at a shell prompt using ./a.out. You can specify the name of the output executable in your command with the -o flag.
$ gcc somefile.c -o my_executable
Make is a tool for automation of commands. Instead of typing out long commands repeatedly one command is issued, such as make, or make program. The makefile contains information about the commands to issue and what the commands will create. Make saves a programmer time by compiling only files that have been modified since the last make.
The example below is a simple makefile.
all: x_draw.o link
x_draw.o: x_draw.c
gcc x_draw.c -c -I/usr/local/include -I/usr/X11R6/include -iX11
link: x_draw.o
gcc x_draw.o -o x_draw -L/usr/X11R6/lib -lX11 -L/usr/local/lib -ljpeg
clean:
rm x_draw.o x_draw
The top line of the example with all: is the target that is invoked when make is run. When make or make all is executed the targets in all will be invoked, which are x_draw.o and link in this case. The x_draw.o target requires x_draw.c. If x_draw.c has not been saved/updated since the last time make was executed it will not compile it, unless make clean is executed.
Notice that the command to compile x_draw.c to an object file is indented. The indent is a tab, which is required by make. The gcc command uses the -c flag which causes gcc to not invoke the linker, so it compiles an object .o file, and not an executable.
The link target uses the x_draw.o file created by the x_draw.o target, and links it into an executable named x_draw.
Makefiles can use variables to save the programmer from retyping common strings. Suppose for example that you wanted to have a variable that stores the name of the output executable.
PROGRAM=my_xdrawThe link target can now use the PROGRAM variable as the output executable name.
link: x_draw.o gcc x_draw.o -o $(PROGRAM) -L/usr/X11R6/lib -lX11 -L/usr/local/lib -ljpeg
Information can be appended to a variable that holds a list using +=. This can be useful because it saves a programmer time, by allowing the placement of += anywhere after the initial definition. All commands after the += will use the new information that was added.
For further information see the GNU make manual and the manual pages for make, and mkdep. -- MattWalsh - 16 Mar 2002