We will look at a very simple C program to demonstrate compiling C files individually by hand, to help the make program be more concrete to students who may have only compiled in a Visual Studio or similar environment.
In doing so, we will use the machine lts1.eecs.wsu.edu (“Linux Terminal Server 1”). It can not be accessed from outside EECS, so first ssh to gate1.eecs.wsu.edu AKA ssh-server.eecs.wsu.edu. The nice thing about lts1.eecs.wsu.edu is that, unlike gate1.eecs.wsu.edu, it has the C compiler installed.
The files for today can be found in http://eecs.wsu.edu/~cs224/test/make/.
A single file can contain everything needed for an executable “binary” program. It has to have no unresolved symbols.
The default C compiler on a Unix system is generally the program cc, although often gcc (GNU cc) is used. If there are no options given, and only one C file named, then the compiler will create an executable file called a.out by default. You can give it a different name with the –o name option.
An example is in mainSimple.c.
Unless a program is very small, it is broken up into multiple source code files. When this is done, there are two steps in building your program:
1. Compile the individual .c files into their .o equivalent. Note that, while these .o files are machine code, they are not a complete executable. We do this with the –c option to cc.
2. Link together the .o files to create an executable file. We do this with no arguments to cc, though you usually use the –o name option so it does not give it the binary file name a.out.
Following is a small example. main.c has a trivial main() in it, but it calls func1() and func2(). These are stored in func1.c and func2.c, respectively. Note that if you try to build an executable program from just main.c that won’t work, because it has not defined the symbols func1 func2, only declared them to be external (in defs.h).
Thus, to create an executable program called myMain from those 3 files, we will do the following:
·
cc
–c main.c
·
cc
–c func1.c
·
cc
–c func2.c
· cc –o myMain main.o func1.o func2.o
If we leave off one of the files, we will get an undefined symbol from the linker:
· cc –o myMainOops main.o func1.o
The file Makefile uses no macros. It does use default rules for the C compiler, particularly it knows how to create a .o target from the same base name .c file (BTW, see the program basename). Otherwise, you would have to have a (tedious and identical) rule like this for every C file:
func1.o: func1.c
cc –c func1.c
The file Makefile.Macros has a few typical macros in it. You invoke it like this:
·
make
–f Makefile.Macros
Now you can look at the more detailed make notes again, and they should make a lot more sense!