cynorr

Learn what I touched.

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Makefiles by example


Compiling your source code file can be tedious, specially when you want to include sereral source files and have to copy the compiling commond everytime you want to do it.
Well, I have news for you... Your days of commond line compiling are mostly over, because you well learn how to write Makefiles.
Makefiles are special format files that togather with make utility will help you automagically build and mange your projects.

For this session you will need these files: Download

I recommond creating a new directory ans placing all the files in there.

Note:I use g++ for compiling. You are free to change it to a compiler of your choice.

The make utility

If you run

make

this program will look for a file named makefile in your dircetory, and then execute it.
If you have several makefiles, then you can execute them with commond:
make -f MyMakefile
There are several other sitches to the make utility. For more info, man make.

Build process

  • Compiler takes the source files and outputs object files
  • linker takes the object files and creates an executable

Compiling by hand

The trivial way to compile the files and obtain the executable, is by running the commond:

g++ main.cpp hello.cpp factorial.cpp -o hello

The basic Makefile

The basic makefile is composed of:
target: dependencies
[tab] system commond
This sample applied to our sample would look like:(Makefile-1 contain following:)

all:
      g++  main.cpp hello.cpp factorial.cpp -o hello 

To run the makefile on your files, type:

make -f makefile-1

On this first sample we see that our target is called all. This is default target for makefiles.
The make utility will execute this target if no other one is specified.
We all see that there are no dependencies for target all, so make safely execute the system commond specified.
Finally, make compiles the program according to commond line we gave it.

Using dependencise##

Sometimes it is useful to use different targets. This is because if your modify a single file in your project, you don't have to recompile everything, only what you modified.
Here ia an example:

all: hello 

hello:main.o factorial.o hello.o
       g++ main.o factorial.o hello.o -o hello
main.o:main.cpp
        g++ -c main.cpp
factorial.o:factorial.cpp
        g++ -c factorial.cpp
hello.o:hello.cpp
        g++ -c hello.cpp
clean:
        rm -rf *o hello

Now we see that the target all has only dependcies, but no system commond. In order for make to execute correctly, it has to meet all the dependencies of the called target ( in this case all).
Each of the dependencies are searched through all the targets available and executed if found.
In this example we see a target called clean. It is useful to have such target if you want to have a fast way to get rid of all the object files and executables.

Using vairalbes and commonts

You can also use vairalbes when you write Makefiles. It comes in handy in situation where you want to change the compiler, or the compiler options.

# I am a comment, and I want to say the variable CC will be 
# the compiler to use
CC = g++
# Hey!, I am comment number 2. I want to say that CFLAGS will be the
# options I'll pass to compiler.
CFLAGS = -c -Wall

all:hello
    
hello: main.o factorial.o hello.o 
       $(CC) main.o factorial.o hello.o -o hello

main.o:main.cpp
       $(CC) $(CFLAGS) main.cpp

factorial.o:factorial.cpp
       $(CC) $(CFLAGS) factorial.cpp

hello.o:
       $(CC) $(CFLAGS) hello.cpp

clean:
       rm -f *o hello

As you can see, varialbe can be very useful sometimes. To use them, just assign a value to a variable before you start to write your targets. After that, you can just use them with the dereference operator $(VAR).

Where to go from here

With the brief introduction to Makefiles, you can create some sophisticated mechanism for compiling your projects. However, this is a tip of iceberg. I don't expect anyone to fully understand the example presented below without consulted some Make Documentation(which I had to myself) or read pages 347 to 354 of your Unix book.

CC = g++
CFLAGS = -c  -Wall
LDFLAGS =    
SOURCES = main.cpp hello.cpp factorial.cpp
OBJECT = $(SOURCES:.cpp = .o)
EXECUTABLE = hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE):$(OBJECTS)
       $(CC) $(LDFLAGS) $(OBJECTS) -O $@

.cpp.o:
       $(CC) $(CFLAGS) $< -O $@

If you understand the last example, you could adapt it to your own personal projects changing only 2 lines,
no matter how many additional files you hava!!!

posted on 2014-10-26 19:01  cynorr  阅读(233)  评论(0编辑  收藏  举报