0

I am trying to creat a makefile for my project, but I really don't understand this devil thing.

When I was doing it in Java, with ant, it was much more simplier.

The structure of my program is: http://imageshack.com/a/img39/6592/jsxa.png

I read about creating makefiles but, when they answer a question similiar, they just put the done makefile and don't explain a lot about what they're doing.

So, what I need to do is create a makefile that stay in a folder named foo (foo/makefile) together with the src folder(foo/src/). The makefile needs to create a folder named bin (foo/bin/) and put *.o files in there. Then build the program (DisqueRango.cpp contais the main function) and run it using 4 arguments: "-e couriers.csv -c menu.csv".

I'm not asking for the done makefile. What I need is an explanation about what I need to do it by myself.

Thank you indeed.

makefile of src/clients/

CC := g++

OBJ = *.cpp

all: prog

prog:
    $(CC) -c $(OBJ)

makefile of src/disquerango/ (contais main function)

CC := g++

BASEDIR := ..
MODULES := clients couriers products read requests
OBJS    := $(addsuffix /*.o, $(addprefix $(BASEDIR)/,$(MODULES)))

.PHONY: clean

all:
    $(CC) -o disquer DisqueRango.cpp $(OBJS)

and the makefile who call them all (same folder of src):

CC  := g++

BASEDIR := src
PROJN   := disquerango
MODULES := clients couriers products read requests disquerango
OBJS    := $(addprefix $(BASEDIR)/,$(MODULES))

all: compila run limpa

compila:
        for dir in $(OBJS); do (cd $$dir; ${MAKE} all); done

run: compila
    ./$(BASEDIR)/$(PROJN)/disquer -e entregadores.csv -c cardapio.csv

limpa:
    rm -f $(BASEDIR)/$(PROJN)/disquer
    for dir in $(OBJS); do (cd $$dir; rm -f *.o); done
ddz
  • 526
  • 3
  • 15
  • Why do you have directories inside your project? What for? Do you intend to build part of your project as a reusable library? See e.g. [this](http://stackoverflow.com/a/20146082/841108) & [that](http://stackoverflow.com/a/21423765/841108) answers... – Basile Starynkevitch Feb 17 '14 at 19:10
  • I have directories cause the teacher want it. It's a project of graduation class. – ddz Feb 17 '14 at 19:12
  • 1
    Read [recursive make considered harmful](http://miller.emu.id.au/pmiller/books/rmch/). – Basile Starynkevitch Feb 17 '14 at 19:13
  • 2
    Have you tried reading the manual? It has pretty good introductory material. http://www.gnu.org/software/make/manual/html_node/index.html – MadScientist Feb 17 '14 at 19:14
  • Basil: that's a good article but it's written for people who already know how to write a makefile, discussing the pros and cons of specific styles of makefile. I don't think it's a good text to explain makefiles to anyone. – MadScientist Feb 17 '14 at 19:14
  • I recommend outputting the compiled object files into a common directory that is separate from the source file directories. The link step(s) would use this common object directory. For the source files, include the relative paths in the make file dependencies. – rcgldr Feb 17 '14 at 19:57

1 Answers1

1

This may take a few iterations. You must start with the small and simple, and work up to the large and complex.

First, create bin/ yourself.

Now write a makefile that can build one object file:

bin/DisqueRango.o: src/DisqueRango.cpp
    g++ -c src/DisqueRango.cpp -o bin/DisqueRango.o

Get that working, and understand how it works, post a comment to tell us the result, and we'll proceed.

EDIT:

src/clients/makefile:

CC := g++

OBJ = *.cpp

all: prog

prog:
    $(CC) -c $(OBJ)

This makefile is effective but crude. It will rebuild all objects every time it is run, even if they are already up to date. We could add another command, mv *.o ../../bin, which would put them all into bin/, but I think it is better to improve the basic structure now, while the clients codebase is still simple.

The statement OBJ = *.cpp gives the variable OBJ the value *.cpp; the wildcard will not be expanded until the variable is used in the shell command. To assign a list of files to the variable, we use the wildcard function. To transform a list of source files (foo.cpp) into a list of object files (foo.o), we use the patsubst function. To build the object files we use a pattern rule, and within that rule we use automatic variables to refer to the source file (foo.cpp) and the target (foo.o).

CC := g++

SRC := $(wildcard *.cpp)             # foo.cpp bar.cpp baz.cpp
OBJ := $(patsubst %.cpp,%.o,$(SRC))  # foo.o bar.o baz.o

all: $(OBJ)

%.o: %.cpp
    $(CC) -c $< -o $@

Test that much to verify that it works. Now to have this makefile put the object files in bin/, we make a small change:

CC := g++
BIN := ../../bin


SRC := $(wildcard *.cpp)
OBJ := $(patsubst %.cpp,$(BIN)/%.o,$(SRC))

all: $(OBJ)

$(BIN)/%.o: %.cpp
    $(CC) -c $< -o $@

Verify that that much works, and we'll move on to src/disquerango/makefile.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • I did something that can generate .o files and link them all, using a feel makefiles, one in each folder. for dir in $(OBJS); do (cd $$dir; ${MAKE} all); done did it for me but i coudn't cread bin folder and put all .o inside. Would I be cheating if I use shell commands to do this? heh – ddz Feb 17 '14 at 20:06
  • Multiple makefiles are *sometimes* a good solution (I do not subscribe to "Recursive Make Considered Harmful"). If you are sure that you want to take this approach, then edit your question to include one of the makefiles (e.g. `src/clients/makefile`) and we'll modify it to put the object files in `bin/`. – Beta Feb 17 '14 at 20:18