OK, here is a short introduction to make and makefiles:
Compiling, linking and running programs is a quite repetitive task: every change in any program file will make it necessary to recompile, relink and re-run the program. Well, in fact: no. Yes, you will have to run the program again, but you do not need to compile and link all the program sources - just the relevant parts. What the relevant parts are in each case is called a "dependency": object files are depending on certain source files, libraries and binaries are depending on the objects. What you do in a makefile is to create rules, how to get a depending file from its dependencies.
Lets try an example: we have 5 source files "src1", "src2", etc. and 3 header files "h1", "h2", "h3". Together they should form a library (src2-4) and a binary (src1 and src5). Lets say our compile command is "compile" and our linkage editor is called "link". "link -b" will create binaries, "link -l" will create libraries.
The first you have to do is to consider what is depending on what: every source file goes into one object file, but maybe not every header is used in every source. Lets say "h1" is used in every source, "h2" only in src4 and "h3" only in src2 and src4. The resulting objects will go into two files (see above, a binary and a library). Here are these dependencies:
As you see every entry on the right side is depending on one or several entries on the left. "make" now does the following: it compares file dates on the files on the left and the right side and if a target (the right side) is older than any of its dependencies it recreates this target. For instance, if "src1" would change, "make would create "obj1" anew. Now, because "bin1" has a changed dependency, it is also recreated, but "lib1" is not, because nothing has changed in its path. Would you have changed "h1", everything would have been recreated.
We are now ready to create our makefile. A makefile consists of rules, which in turn have three parts:
- the target: the file which has to be created
- the dependencies: all the files necessary to create the target
- the action: the command(s) necessary to create the target from the dependencies.
The format is:
So we write first the rules to create the objects from the sources and headers:
Now all the sources get compiled, but not linked yet. Let us add these rules too:
You will notice the rule "all", which has no commands at all. This is the default rule "make" will try to execute if no other rule is given as parameter.
You can name this file simply "Makefile" and call "make" without any parameter. "make" will look for a rule file called "Makefile" (capitalized "M") by default and execute the "all" rule and all necessary rules for this target in it if it finds one. But you can also call one of its rules, for instance "make bin1" or "make obj3". It will execute only this rule then (if that target is not up to date).
Now, ok, the program gets compiled and linked, but is that all "make" can do?
No, not at all. It is true in was invented to compile and link programs, but you can do everything which you can press into such rules. For instance you can create an installation rule. For the installation of our example program the binary should go to "/usr/local/bin/bin1.exe" and the library to "/usr/local/lib/bin1/lib1.a". Lets add such a rule:
Notice that there is no file "install" and it isn't created in the process. It is perfectly valid to have rules where the target doesn't exist. As this rule ins not depending on "all" you can still compile and link your program with "make" (without parameter) and install it by "make install".
It is also not necessary for a target to have dependencies: we could also add the following rule, to clean our compile-directory of old objects and binaries or to force a complete recreation of everything in a new run:
"make clean" would no remove all the compiler leftovers from previous make-runs.
To add even more flexibility to your makefiles, suppose you would want to change the compiler. Right now you use "compiler", but suppose there is a new compiler "comp_new", you would want to use. And suppose, too, that you want to use certain default compiler flags when you create your objects. You could change youe makefile in every line of course, but you can also use variables. The basic syntax for the assignment and the usage of a variable is:
So we change the makefile a last time:
"make" is not limited to programming at all. I have seen people using it to do their backup, process automated mails and what not. The limitation is only what you are able to imagine.
For this you will probably find some more features (which i have intentionally left out for clarity) handy: rules for processing whole classes of files, so that you don't have to write the rule for every file anew, complex variables which change their contents depending on which file has invoked the rule (like: "$<", "$@", and so on) , etc., etc..
I suggest reading the man page and probably one or the other book about "make" (yes, there have been books written about the topic) to find out more. This here is just meant as a starter and I'll keep it at that.
I hope this helps.
bakunin
These 2 Users Gave Thanks to bakunin For This Post:
I am new to creating makefiles.
I have several fortran programs in a folder called as "test" and also have several subroutines in another folder (which is inside this test folder) called as libry
My makefile is in the folder "test"
I want to create a makefile which can access the files in... (2 Replies)
Hi, I'm trying to run the module load command in a Makefile and i'm getting the following error:
make: module: command not found
Why is this? Is there any way to run this command in a Makefile?
NOTE: command - module load msjava/sunjdk/1.5.0 works fine outside of the Makefile (2 Replies)
I have 2 libraries in 2 different directories that I build with Makefiles.
library B depends on library A. If I modify a .cpp file in library A and run lib B's Makefile can I have B's makefile to automatically rebuild library A?
I am now rebuilding A, followed by B... but I'd like B to... (0 Replies)
Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted!
1. The problem statement, all variables and given/known data:
Basically, the prompt is make a makefile with various sub makefiles in their respective subdirectories. All code... (1 Reply)
Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted!
1. The problem statement, all variables and given/known data:
I have been trying to make the program swap but i have been getting errors with the makefile such as
driver.o:... (1 Reply)
I'm really confused how to use a makefile.
Are you supposed to be make a file from emacs called MakeFile and put code in there to compile?
I am trying to create a makefile to compile two .cpp files in my current directory to produce two .o files and then link them...
What I did was make a... (1 Reply)
Dear all,
I have a quite simple question about how to manipulate "makefile.am". I intend to:
1. "CFLAGS" and "CXXFLAGS" have no value at all. I know that these values get "-g -O2" by default. On the other hand, when I try to set them as "CFLAGS = " in "makefile.am", I get warning messages... (4 Replies)
Hey everybody,
This may be stup*d question for you, but i am new in unix and i wonder how can i make the rules for translating and linking my .c "primjer1.c", "primjer2.c" and "primjer3.c" in makefile.
Thank you. (7 Replies)
Hi All,
We have moved our OS from Sun Solaris to Linux and also some of the compilers.
Our old makefile used to be as below:
CC=cc
FLAGS=-G -KPIC -DLG_SOLARIS_OS
DEFINES=-DSunOS
SYSLIBS=-lc
.SUFFIXES : .c
.c.o : ;$(CC) -c $(FLAGS) $(DEFINES) $*.c -o $*.o
... (3 Replies)