Sign in to follow this  

Mingw32 Makefile Question

This topic is 4334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I wanted to make a makefile for compiling source files found in multiple directories. Platform: win32 + mingw The dir tree looks like this:
project directory:|
|   make.bat
|   makefile
|---common
|       gt_types.h
|       
|---kernel
|       gt_kernel.cpp
|       gt_kernel.h
|       gt_task.cpp
|       gt_task.h
|       
|---main
|       main_console.cpp
|       
|---render
|       gt_render.cpp
|       gt_render.h
|       
|---script
|       gt_script.cpp
|       gt_script.h
|       
|---_obj
|       
|--_release




In the end, the makefile I obtained looks like this:
## Project Name
NAME = gt_engine

## General CC options
CC = g++.exe
CFLAGS = -Wall -O2
DIR_REL = _release
DIR_DBG = _debug
DIR_OBJ = _obj

## Project Directories
DIR_COMMON = common
DIR_RENDER = render
DIR_KERNEL = kernel
DIR_MAIN   = main
DIR_SCRIPT = script

## Objects
objects =
        main_console.o  \  	gt_render.o	\	gt_script.o	\	gt_kernel.o	\	gt_task.o

objects_path = $(addprefix $(DIR_OBJ)\, $(objects))

## Include Directories 
include_dirs =
        -I$(DIR_COMMON) \        -I$(DIR_RENDER) \        -I$(DIR_KERNEL) \        -I$(DIR_MAIN) \        -I$(DIR_SCRIPT)

## Makefile targets
release:$(objects)
        g++ -o $(DIR_REL)\$(NAME) $(objects_path)

main_console.o:
        $(DIR_MAIN)\main_console.cpp         $(DIR_KERNEL)\gt_kernel.h
        g++ -c $(DIR_MAIN)\main_console.cpp $(include_dirs) -o $(DIR_OBJ)\main_console.o

## Kernel object files
gt_kernel.o:
        $(DIR_KERNEL)\gt_kernel.cpp         $(DIR_COMMON)\gt_types.h     	$(DIR_KERNEL)\gt_kernel.h   
        g++ -c $(DIR_KERNEL)\gt_kernel.cpp $(include_dirs) -o $(DIR_OBJ)\gt_kernel.o

gt_task.o:
        $(DIR_KERNEL)\gt_task.cpp         $(DIR_COMMON)\gt_types.h          $(DIR_KERNEL)\gt_task.h 
        g++ -c $(DIR_KERNEL)\gt_task.cpp $(include_dirs) -o $(DIR_OBJ)\gt_task.o

## Render object files
gt_render.o:
        $(DIR_RENDER)\gt_render.cpp         $(DIR_COMMON)\gt_types.h            $(DIR_KERNEL)\gt_task.h             $(DIR_RENDER)\gt_render.h 
        g++ -c $(DIR_RENDER)\gt_render.cpp $(include_dirs) -o $(DIR_OBJ)\gt_render.o

## Script object files
gt_script.o:
        $(DIR_SCRIPT)\gt_script.cpp         $(DIR_COMMON)\gt_types.h         $(DIR_KERNEL)\gt_task.h         $(DIR_SCRIPT)\gt_script.h
        g++ -c $(DIR_SCRIPT)\gt_script.cpp $(include_dirs) -o $(DIR_OBJ)\gt_script.o




Basically it compiles all the source files from the specified directories, puts the obtained object files in \_obj directory, links all the object files and puts the executable in \_release directory. I tried to use VPATH but I couldn't make it work for this situation.(I don't know if it is really possible) 1. My question is if this could be made more simple? 2. Should I create a separate makefile for each source module found in a sub-directory? 3. In the long term, would you use such a makefile or not? Thank you,

Share this post


Link to post
Share on other sites
Please try to keep it simple.

If you put all your source in one directory, you can make the Makefile simpler.

You may be able to do so anyway.

If you just write a general rule to make a .o file from a .cpp file, then you can avoid having a separate rule for each .o

Then you can make your exe depend on all your .o files, and there you are, job done.

What I normally do is, rather than have proper dependencies, just make all .o files depend on all .h files.

Then absolutely everything should depend on Makefile itself, so that if you change any of the Makefile settings it does a full rebuild.

Mark

Share this post


Link to post
Share on other sites
Separating your files into different folders is a good choice. But you should also separate your source files from your header files. Your folder structure should look like this:

project-dir
+--Makefile
+--bin
+--docs
| +--API
+--include
| +--common
| | +--gt_types.h
| +--kernel
| | +--gt_kernel.h
...
+--src
| +--kernel
| | +--gt_kernel.cc
...

Your makefile should contain rules for compiling a .cc to .o, but in a general way (note the use of tabs):
$(OBJDIR)/%.o : %.cc
$(CXX) -c $(CPPFLAGS) $(CCFLAGS) -o $@ $<

The VPATH is used to tell make where to look for files that are on the right side of a rule, i.e. %.cc will match any file in the VPATH directory that ends in .cc.
Note that GNU make provides a better way than setting VPATH:

SOURCES += main.cc kernel/gt_kernel.cc
SEARCH_DIRS = $(sort $(dir $(SOURCES)))
vpath %.cc $(addprefix machine/$(TARGET)/$(SRCDIR)/, $(SEARCH_DIRS))
vpath %.cc $(addprefix $(SRCDIR)/, $(SEARCH_DIRS))



A common problem when using VPATH are include files. As there are no default dependencies of your .cc files from the header files, you have to create them manually:

$(DEPDIR)/%.d: %.cc
@set -e; rm -f $@; $(CXX) -MM $(CPPFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,$(OBJDIR)/\1.o $(DEPDIR)/$@ : ,g' < $@.$$$$ > $@; echo -e "\t\$$(CXX) -c \$$(CPPFLAGS) \$$(CCFLAGS) -o \$$@ \$$<" >> $@; rm -f $@.$$$$


Then include the dependency in your Makefile (put this in the last line):
sinclude $(addprefix $(DEPDIR)/, $(addsuffix .d, $(sort $(basename $(notdir $(SOURCES))))))
Note that $(DEPDIR) is a variable that contains the directory to place dependency files, i.e. use "DEPDIR = dep".



Another option is to use qmake made by Trolltech.
http://www.trolltech.com/
Just cd into your project directory and type:
qmake -project
qmake
make
The first line creates a .pro file.
The second line creates a Makefile.
The third one creates your application.

Share this post


Link to post
Share on other sites
Following nmi suggestions, I decided to use the following dir tree:

project-dir
+--Makefile
+--bin
| +--obj
+--docs
| +--API
+--include
| +--common
| | +--gt_types.h
| +--kernel
| | +--gt_kernel.h
...
+--src
| +--kernel
| | +--gt_kernel.cc
...

And I found this solution:

## Project Name
NAME = gt_engine

## General CC options
DIR_BIN = bin
DIR_INC = include
DIR_SRC = source
DIR_OBJ = obj

## Project Directories
search_dirs = ai common render kernel main script

vpath %.o $(DIR_BIN)\$(DIR_OBJ)\
vpath %.h $(addprefix $(DIR_INC)\, $(search_dirs))
vpath %.cpp $(addprefix $(DIR_SRC)\, $(search_dirs))

## Objects
objects = main_console.o gt_render.o gt_kernel.o gt_task.o gt_script.o


release: $(objects)
$(CC) -o $(DIR_BIN)\$(NAME) $(addprefix $(DIR_BIN)\$(DIR_OBJ)\, $(objects))

CC = g++
CFLAGS = $(addprefix -I$(DIR_INC)\, $(search_dirs))

%.o : %.cpp
$(CXX) -c $(CPPFLAGS) $(CFLAGS) -o $(DIR_BIN)\$(DIR_OBJ)\$@ $<




So - no link errors, all the object files are put in the \bin\obj dir and the final executable file is in bin\ dir and I can keep my dir tree. I don't even need to specify dependencies.

If there are any other suggestions, please tell me.

+rate for nmi



Share this post


Link to post
Share on other sites

This topic is 4334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this