How to Read Two Files When Executing a Makefile in Gnu
A Simple Makefile Tutorial
Makefiles are a simple style to organize code compilation. This tutorial does non even scratch the surface of what is possible using make, but is intended equally a starters guide then that you tin quickly and hands create your own makefiles for small to medium-sized projects.
A Simple Example
Let'due south start off with the following three files, hellomake.c, hellofunc.c, and hellomake.h, which would stand for a typical main program, some functional code in a split up file, and an include file, respectively.
hellomake.c | hellofunc.c | hellomake.h |
---|---|---|
#include <hellomake.h> int primary() { // call a function in another file myPrintHelloMake(); return(0); } | #include <stdio.h> #include <hellomake.h> void myPrintHelloMake(void) { printf("Hello makefiles!\northward"); render; } | /* example include file */ void myPrintHelloMake(void); |
Normally, you would compile this collection of code by executing the post-obit command:
gcc -o hellomake hellomake.c hellofunc.c -I.
This compiles the 2 .c files and names the executable hellomake. The -I. is included so that gcc volition look in the current directory (.) for the include file hellomake.h. Without a makefile, the typical approach to the examination/modify/debug cycle is to use the up arrow in a terminal to go back to your terminal compile command and so you don't have to type it each time, especially once you've added a few more .c files to the mix.
Unfortunately, this approach to compilation has ii downfalls. First, if y'all lose the compile command or switch computers you lot have to retype it from scratch, which is inefficient at best. Second, if you are only making changes to ane .c file, recompiling all of them every time is also time-consuming and inefficient. And so, it's time to see what nosotros tin can do with a makefile.
The simplest makefile you could create would look something like:
Makefile 1hellomake: hellomake.c hellofunc.c gcc -o hellomake hellomake.c hellofunc.c -I.
If yous put this rule into a file called Makefile or makefile and and then blazon make on the command line it will execute the compile command as you have written it in the makefile. Annotation that brand with no arguments executes the first rule in the file. Furthermore, by putting the listing of files on which the command depends on the first line after the :, make knows that the rule hellomake needs to be executed if any of those files modify. Immediately, you lot have solved problem #ane and can avoid using the up arrow repeatedly, looking for your last compile command. Nonetheless, the system is even so not existence efficient in terms of compiling just the latest changes.
One very important thing to note is that there is a tab before the gcc control in the makefile. At that place must be a tab at the get-go of any control, and make will not be happy if it's not at that place.
In social club to be a bit more efficient, let'south try the post-obit:
Makefile 2CC=gcc CFLAGS=-I. hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o
So at present we've defined some constants CC and CFLAGS. It turns out these are special constants that communicate to make how nosotros want to compile the files hellomake.c and hellofunc.c. In particular, the macro CC is the C compiler to utilize, and CFLAGS is the list of flags to pass to the compilation command. By putting the object files--hellomake.o and hellofunc.o--in the dependency listing and in the rule, make knows information technology must first compile the .c versions individually, and and then build the executable hellomake.
Using this form of makefile is sufficient for well-nigh pocket-sized scale projects. However, in that location is one thing missing: dependency on the include files. If you were to make a change to hellomake.h, for case, make would non recompile the .c files, fifty-fifty though they needed to be. In order to fix this, we demand to tell make that all .c files depend on certain .h files. We can practise this by writing a simple rule and adding it to the makefile.
Makefile threeCC=gcc CFLAGS=-I. DEPS = hellomake.h %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o
This improver kickoff creates the macro DEPS, which is the set of .h files on which the .c files depend. And so we define a rule that applies to all files ending in the .o suffix. The rule says that the .o file depends upon the .c version of the file and the .h files included in the DEPS macro. The dominion then says that to generate the .o file, brand needs to compile the .c file using the compiler defined in the CC macro. The -c flag says to generate the object file, the -o $@ says to put the output of the compilation in the file named on the left side of the :, the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above.
Equally a terminal simplification, let's employ the special macros $@ and $^, which are the left and right sides of the :, respectively, to make the overall compilation rule more than general. In the instance below, all of the include files should be listed as part of the macro DEPS, and all of the object files should be listed as part of the macro OBJ.
Makefile 4CC=gcc CFLAGS=-I. DEPS = hellomake.h OBJ = hellomake.o hellofunc.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ) $(CC) -o $@ $^ $(CFLAGS)
Then what if we want to start putting our .h files in an include directory, our source lawmaking in a src directory, and some local libraries in a lib directory? Also, can we somehow hide those annoying .o files that hang effectually all over the place? The answer, of course, is yes. The following makefile defines paths to the include and lib directories, and places the object files in an obj subdirectory within the src directory. Information technology also has a macro defined for any libraries you want to include, such as the math library -lm. This makefile should be located in the src directory. Note that information technology also includes a dominion for cleaning upwards your source and object directories if you blazon make make clean. The .PHONY dominion keeps brand from doing something with a file named clean.
Makefile 5IDIR =../include CC=gcc CFLAGS=-I$(IDIR) ODIR=obj LDIR =../lib LIBS=-lm _DEPS = hellomake.h DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) _OBJ = hellomake.o hellofunc.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) $(LIBS) .PHONY: clean make clean: rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
And then at present you accept a perfectly skillful makefile that yous tin can change to manage small and medium-sized software projects. You can add multiple rules to a makefile; you can fifty-fifty create rules that call other rules. For more information on makefiles and the make function, check out the GNU Make Manual, which will tell you more than you ever wanted to know (actually).
Source: https://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
0 Response to "How to Read Two Files When Executing a Makefile in Gnu"
Enregistrer un commentaire