1 / 19

Makefiles

Makefiles. Multiple Source Files (1). Obviously, large programs are not going to be contained within single files. C provides several techniques to ensure that these multiple files are managed properly. These are not enforced rules but every good C programmer know how to do this.

gordonp
Download Presentation

Makefiles

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Makefiles

  2. Multiple Source Files (1) • Obviously, large programs are not going to be contained within single files. • C provides several techniques to ensure that these multiple files are managed properly. • These are not enforced rules but every good C programmer know how to do this. • A large program is divided into several modules, perhaps using abstract data types. • The header (.h) file contains function prototypes of a module. • The (.c) file contains the function definitions of a module. • Each module is compiled separately and they are linked to generate the executable file.

  3. Multiple Source Files (2) • C programs are generally broken up into two types of files. .c files: • contain source code (function definitions) and global variable declarations • these are compiled once and never included .h files: • these are the “interface” files which “describe” the .c files • type and struct declarations • const and #define constant declarations • #includes of other header files that must be included • prototypes for functions

  4. Example - Main Program sample.c #include <stdio.h> #include "my_stat.h" int main() { int a, b, c; puts("Input three numbers:"); scanf("%d %d %d", &a, &b, &c); printf("The average of %d %d %d is %f.\n", x,y,z,average(a,b,c)); return 0; }

  5. /* my_stat.h */ #define PI 3.1415926 float average(int x, int y, int z); float sum( int x, int y, int z); /* my_stat.c */ #include "my_stat.h" float average(int x, int y, int z) { return sum(x,y,z)/3; } float sum(int x, int y, int z) { return x+y+z; } Example - Module my_stat

  6. Example - Compile the Sample Program • You need my_stat.c and my_stat.h to compile the my_stat module to object code cc –c my_stat.c • You need my_stat.h and sample.c to compile sample.c to object code cc –c sample.c • You need my_stat.o and sample.o to generate an executable file cc –o sample sample.o my_stat.o • Therefore, the module my_stat can be reused just with the my_stat.o and my_stat.h. In fact, this is how the standard libraries work. (Libraries are just collections of object code, with headers describing functions and types used in the libraries.)

  7. The make Utility (1) • Programs consisting of many modules are very tedious to compile manually. • This can be addressed by using the make utility. all: sample sample: sample.o my_stat.o cc –o sample sample.o my_stat.o sample.o: sample.c my_stat.h cc –c sample.c my_stat.o: my_stat.c my_stat.h cc –c my_stat.c clean: rm sample *.o core Target Dependencies These indentation are from a tab (not spaces!!!) Commands

  8. The make Utility • A make rule is of the form… targets : dependencies commands • Atarget is a filename, where the rules tell us how to create that file sample: sample.omy_stat.o cc –o sample sample.omy_stat.o • The target is the executable file sample, which requires that sample.o and my_stat.o already exist • The command is executed to carry out the action • which in this case is to create the executable program sample

  9. The make Utility • A target can also be a so-called phony target • A phony target is a rule for creating a file that is never actually created • A phony target is a set of commands that are executed when we ask for that file to be created, e.g. clean: rm *.o sample • In this case the target clean has no dependencies • So it doesn’t require that any other files exist before the command is executed • The command will always be executed, provided that there is no file in the current directory called clean • If there is a file in the current directory called clean, the make system will be satisfied that the file already exists, so no action is needed • But the command does not create a file called clean, instead it deletes some files in the current directory

  10. The make Utility • A make rule is of the form… target : dependencies commands • The dependencies tell us what files we need to create the target • If these dependencies files already exist and are up to date, then the make system will run the command(s) associated with the rule • But if the dependencies… • Do not exist, or • Are not up to date • … the make system will follow the rules for creating the dependencies files

  11. The make Utility • A target file is considered to be out of date if… • It doesn’t exist at all or • The target file is older than any of its prerequisite files • The age of files is determined by the time they were created or last modified (their timestamp) • You can see the timestamp of files in the current directory using ls -l • The make utility is great for large programs with many files • If you modify a source file, only the files that depend on the source file are recompiled • The make utility looks after this by checking the timestamps on all the files listed in each dependency

  12. The make Utility • A make rule is of the form… targets : dependencies commands • A command is a normal Unix command like you would type at the command line • The command is normally expected to be instructions for building the target file • Typically invoking the compiler • But you can invoke other tools, such as parser generators • But as we have seen in the case of dummy targets • The command does not have to create the target file • The command can do anything the programmer writes

  13. The make Utility • Save the file with name "Makefile" (or "makefile") at the same directory. • For every time you want to make your program, type make • The make utility will • Find the Makefile • Check rules and dependencies to see if an update is necessary. • Re-generate the necessary files that need updating. • For example: • If only sample.c is newer than sample, then only the following commands will be executed: • cc –c sample.c • cc –o sample sample.o my_stat.o

  14. The make Utility (1) • Programs consisting of many modules are very tedious to compile manually. • This can be addressed by using the make utility. all: sample sample: sample.o my_stat.o cc –o sample sample.o my_stat.o sample.o: sample.c my_stat.h cc –c sample.c my_stat.o: my_stat.c my_stat.h cc –c my_stat.c clean: rm sample *.o core Target Dependencies These indentation are from a tab (not spaces!!!) Commands

  15. The make Utility (3) • To clean all generated files: make clean • To re-compile, you can • Remove all generated files and make again. • make clean; make • Or you can: • touch my_stat.h and thenmakeagain • This changes the time stamp of my_stat.h, so make thinks it necessary to make all the files.

  16. Example Three C source files and one header file: compute.c includes no header files, calls no functions in other files init.c includes “myprogram.h” calls functions in io.c io.c includes “myprogram.h” calls functions in compute.c How do we build a makefile that compiles and links these files in the correct order?

  17. Example # the first target is the default target all: myprogram # define the components of the program, the dependencies between them # and the actions necessary to build each component myprogram: io.o init.o compute.o gcc – o myprogram io.o init.o compute.o # define the dependencies and how to build each of the three source files compute.o: compute.c gcc –Wall –c –o compute.o compute.c init.o: init.c myprogram.h gcc –Wall –c –o init.o init.c io.o: io.c myprogram.h gcc –Wall –c –o io.o io.c

  18. # remove some repetition by defining things once at the start CC=gcc CFLAGS=-Wall COMPILE=$(CC) $(CFLAGS) -c # all is the default target all: myprogram # define the components of the program, the dependencies between them # and the actions necessary to build each component myprogram: io.o init.o compute.o gcc – o myprogram io.o init.o compute.o # define the dependencies and how to build each of the three source files compute.o: compute.c $(COMPILE) –o compute.o compute.c init.o: init.c myprogram.h $(COMPILE) –o init.o init.c io.o: io.c myprogram.h $(COMPILE) –o io.o io.c

  19. # remove some repetition by defining things once at the start CC=gcc CFLAGS=-Wall COMPILE=$(CC) $(CFLAGS) -c # all is the default target all: myprogram # define the components of the program, the dependencies between them # and the actions necessary to build each component myprogram: io.o init.o compute.o gcc –o myprogram io.o init.o compute.o # remove even more repetition from the file: # define dependencies on header files init.o io.o: myprogram.h # compile all .c source files to .o object files %.o: %.c $(COMPILE) –o $@ $< # note $@ denotes the target; $< denotes the source

More Related