Sponsored Content
Full Discussion: Makefile help
Top Forums Shell Programming and Scripting Makefile help Post 302715059 by bakunin on Saturday 13th of October 2012 04:16:10 PM
Old 10-13-2012
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:

Code:
src1, h1 ---------> obj1 --------------+
src2, h1, h3  ----> obj2 --+           |
src3, h1  --------> obj3 --+--> lib1   |
src4, h1, h2, h3 -> obj4 --+           |
src5, h1 ---------> obj5 --------------+--> bin1

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:

Code:
target: dep1 dep2 dep3 ....
           command1
           command2
           command3
           ...etc.

So we write first the rules to create the objects from the sources and headers:

Code:
# Sample Makefile v1: compiler calls

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5


Now all the sources get compiled, but not linked yet. Let us add these rules too:

Code:
# Sample Makefile v2: compiler calls and linkage editor

all: bin1 lib1

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b obj1 obj5 --output bin1

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:

Code:
# Sample Makefile v3: compiler calls, linkage editor and installation

all: bin1 lib1

obj1: src1 h1
       compile src1 h1 --output obj1

obj2: src2 h1 h3
       compile src3 h1 h3 --output obj2

obj3: src3 h1
       compile src3 h1 --output obj3

obj4: src4 h1 h2 h3
       compile src1 h1 h2 h3 --output obj4

obj5: src5 h1
       compile src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b obj1 obj5 --output bin1

install: bin1 lib1
       mkdir -p /usr/local/bin 2>/dev/null
       mkdir -p /usr/local/lib/bin1 2>/dev/null
       cp bin1 /usr/local/bin/bin1.exe
       cp lib1 /usr/local/lib/bin1/lib1.a

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:

Code:
clean:
       rm -f *o
       rm -f bin1
       rm -f lib1

"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:

Code:
# the assignment:
VARIABLE = VALUE

# the usage (this will get replaced with the content upon execution):
$(VARIABLE)

So we change the makefile a last time:

Code:
# Sample Makefile v4: compiler calls, linkage editor and installation
# added variables

# switch between these two lines to change compilers:
# COMPILE = compile
COMPILE = comp_new
# our compilers might need different switches:
# CFLAGS = -x1 -y1 -z1
CFLAGS = -X2 -Y2 -Z2

LFLAGS = -a -b -c

obj1: src1 h1
       $(COMPILE) $(CFLAGS) src1 h1 --output obj1

obj2: src2 h1 h3
       $(COMPILE) $(CFLAGS) src3 h1 h3 --output obj2

obj3: src3 h1
       $(COMPILE) $(CFLAGS) src3 h1 --output obj3

obj4: src4 h1 h2 h3
       $(COMPILE) $(CFLAGS) src1 h1 h2 h3 --output obj4

obj5: src5 h1
       $(COMPILE) $(CFLAGS) src5 h1 --output obj5

lib1: obj2 obj3 obj4
       link -l $(LFLAGS) obj2 obj3 obj4 --output lib1

bin1: obj1 obj5
       link -b $(LFLAGS) obj1 obj5 --output bin1

install: bin1 lib1
       mkdir -p /usr/local/bin 2>/dev/null
       mkdir -p /usr/local/lib/bin1 2>/dev/null
       cp bin1 /usr/local/bin/bin1.exe
       cp lib1 /usr/local/lib/bin1/lib1.a

clean:
       rm -f *o
       rm -f bin1
       rm -f lib1


"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:
 

10 More Discussions You Might Find Interesting

1. Programming

about the makefile

can anyone well explain how to create a makefile? especially those commands in the makefile? BTW, what is CFLAG? (2 Replies)
Discussion started by: ligerdave
2 Replies

2. High Performance Computing

help with makefile

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)
Discussion started by: explorer
2 Replies

3. UNIX for Advanced & Expert Users

Makefile problem - How to run module load in a Makefile

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)
Discussion started by: hernandinho
2 Replies

4. UNIX for Advanced & Expert Users

Makefile executing another Makefile first?

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)
Discussion started by: wwuster
0 Replies

5. Homework & Coursework Questions

Help with Simple Multi-Level Makefile (Extremely New at Makefile)

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)
Discussion started by: Tatl
1 Replies

6. Homework & Coursework Questions

Makefile Help

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)
Discussion started by: mgyeah
1 Replies

7. UNIX for Dummies Questions & Answers

Help with MakeFile

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)
Discussion started by: jzhang172
1 Replies

8. Shell Programming and Scripting

Makefile

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)
Discussion started by: Dandan
4 Replies

9. UNIX for Dummies Questions & Answers

MakeFile

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)
Discussion started by: jskako
7 Replies

10. Programming

Makefile for g++

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)
Discussion started by: shash
3 Replies
All times are GMT -4. The time now is 04:56 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy