Welcome! Log In Create A New Profile

Advanced

Multiple Projects: One Makefile?

Posted by dancinninja 
Multiple Projects: One Makefile?
June 20, 2010 04:52AM
Hey all, I was wondering if this was possible. I have 14 cpp files, each with a "main" function in them. Individually they all work, but having 14 projects and 14 makefiles is a bit of a pain, particularly when I need to change something in the Makefile (I'm also testing compiler codes).

Is it possible to have one project with a Makefile that loops through all of the cpp files and creates dols/elfs for each? This is how the directories are set up:

Project_Folder/src/simple/triangle_example.cpp
Project_Folder/src/simple/quad_example.cpp
Project_Folder/src/advanced/color_tests.cpp
...etc...

Only the names of the directories and files have been changed to protect the innocent. I use the standard Makefile that comes with the DevkitPro examples, so I'm trying to modify that. Thanks!
Re: Multiple Projects: One Makefile?
June 20, 2010 05:15AM
Sure, why not? SDL Wii builds from several makefiles, see here: [code.google.com]

And Snes9x GX builds two dols: [code.google.com]
Re: Multiple Projects: One Makefile?
June 20, 2010 05:33AM
So I need makefiles for each cpp file then?
Re: Multiple Projects: One Makefile?
June 21, 2010 03:43AM
Quote
dancinninja
So I need makefiles for each cpp file then?
No, there are ways of having a single makefile reference multiple .cpp files. Also, you can have each one make it's own executable. Just look up makefile tutorials on google.
Re: Multiple Projects: One Makefile?
June 21, 2010 06:38AM
That was the first thing that I tried. The results were great for learning to compile to one file, but I didn't find any to build multiple executables (or dols, if you prefer) with one Makefile. I guess I'll just keep searching.
Re: Multiple Projects: One Makefile?
June 21, 2010 11:17AM
Make is a pretty simple tool and it's not that hard to build multiple targets. However, the "wii_rules" makefile has been setup for just 1 target.

For example, I first build an executable which needs to be run to generate an header file which the rest of my sources use. Make takes care of building that executable, running it, and then building the rest:

TARGET := gb

LDFLAGS := -lSDL
CFLAGS := -Wall -Wextra -Wno-unused-parameter -O3

Q := @

CC := gcc
CPP := g++

OBJDIR := .obj

SRC_GB_GEN := gb_src/gb_gen.cpp

SRC_GB := gb_src/cpu.cpp gb_src/link.cpp gb_src/sound.cpp gb_src/cpu_instruction.cpp gb_src/rom.cpp gb_src/timer.cpp gb_src/sgb.cpp gb_src/video.cpp
SRC_CPP := main.cpp $(SRC_GB)
SRC_C := 

OBJS := $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SRC_CPP))) $(addprefix $(OBJDIR)/,$(subst .c,.o,$(SRC_C)))

Q := @

all: $(TARGET)

clean:
	rm -rf $(OBJDIR)
	rm -rf $(TARGET)

.PHONY: all clean

$(TARGET): $(OBJS)
	@echo "LD $(TARGET)"
	$(Q)$(CPP) -o $(TARGET) $(OBJS) $(LDFLAGS)

-include $(OBJS:.o=.d)

$(OBJDIR)/%.o: %.cpp
	@mkdir -p `dirname $(OBJDIR)/$*.o`
	@echo "CC $*.cpp"
	$(Q)$(CPP) -c $*.cpp -o $(OBJDIR)/$*.o $(CFLAGS)
	
#	@g++ -MM $(CFLAGS) $*.cpp > $(OBJDIR)/$*.d
#	@mv -f $(OBJDIR)/$*.d $(OBJDIR)/$*.d.tmp
#	@sed -e 's|.*:|$(OBJDIR)/$*.o:|' < $(OBJDIR)/$*.d.tmp > $(OBJDIR)/$*.d
#	@sed -e 's/.*://' -e 's/\\$$//' < $(OBJDIR)/$*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(OBJDIR)/$*.d
#	@rm -f $(OBJDIR)/$*.d.tmp
	@$(CPP) -MM $(CFLAGS) $*.cpp | sed -e 's|.*:|$(OBJDIR)/$*.o:|' > $(OBJDIR)/$*.d

$(OBJDIR)/%.o: %.c
	@mkdir -p `dirname $(OBJDIR)/$*.o`
	@echo "CC $*.c"
	$(Q)$(CC) -c $*.c -o $(OBJDIR)/$*.o $(CFLAGS)
	
	@$(CC) -MM $(CFLAGS) $*.c | sed -e 's|.*:|$(OBJDIR)/$*.o:|' > $(OBJDIR)/$*.d

#GB instruction table generator
gb_src/cpu_gen_inst.h: gb_gen
	./gb_gen
gb_src/cpu_gen_inst_nm.h: gb_gen
	./gb_gen

gb_gen: $(OBJDIR)/gb_src/gb_gen.o
	@echo "LD gb_gen"
	g++ -o gb_gen $(OBJDIR)/gb_src/gb_gen.o
Re: Multiple Projects: One Makefile?
June 23, 2010 11:38AM
Why don't you just create 14 simple makefiles like this?

include ../common

and ../common is the makefile with all the rules you want. This way, when you modify common makefile, every project will notice those changes.
Re: Multiple Projects: One Makefile?
July 05, 2010 02:07AM
Why not use what the examples use and have a makefile call make in each directory? Would that work for you?

SUBDIRS:= `ls | egrep -v '^(CVS)$$'`

DATESTRING	:=	$(shell date +%Y)$(shell date +%m)$(shell date +%d)

all:
	@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;

clean:
	@rm -f *.bz2
	@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;

dist: clean
	@tar --exclude=.svn -cvjf wii-examples-$(DATESTRING).tar.bz2 *
Re: Multiple Projects: One Makefile?
July 05, 2010 05:50AM
I feel so stupid. I am still not comprehending this. I've gone over a few makefile tutorials, and still I am left with a dumbstruck face. I guess one of the problems is that the number of files has now climbed to over 30 and they are grouped by folder. I did not want to have to put each one into a separate folder within a folder, but I guess I'll have to. Thank you all for the help. I'll keep on plugging away.
Re: Multiple Projects: One Makefile?
July 05, 2010 01:33PM
If they are all being compiled into 1 file.

Do something like this:

Source = source source/folder1 source/folder2 etc
Re: Multiple Projects: One Makefile?
July 05, 2010 07:48PM
Unfortunately, they are to be compiled into multiple files, one for each cpp file, in fact. It's like I said in my first post, the files are arranged like so:

Project_Folder/src/simple/triangle_example.cpp
Project_Folder/src/simple/quad_example.cpp
Project_Folder/src/advanced/color_tests.cpp

Except now it's 30 files instead of just a few.
Re: Multiple Projects: One Makefile?
July 06, 2010 12:16PM
And with something like that?

#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
SystemName=$(shell uname)

ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC")
endif

include $(DEVKITPPC)/wii_rules

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET		:=	source/exe
BUILD		:=	build
SOURCES		:=	source source/... $(TARGET)
DATA		:=	data  
INCLUDES	:=	include

#---------------------------------------------------------------------------------
# MS Visual Studio Style Fix
#---------------------------------------------------------------------------------
STYLEFIX	= 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------

CFLAGS	= -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS	=	$(CFLAGS)

LDFLAGS	=	-g $(MACHDEP) -Wl,-Map,$(notdir $@).map

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS	:=  -ltinyxml -lasnd -lwiiuse -lbte -logc -lm -lpngu -lpng -lfat -lfreetype -lmetaphrasis -lz

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS	:=	$(PORTLIBS)

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT	:=	$(CURDIR)/$(TARGET)

export VPATH	:=	$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
					$(foreach dir,$(DATA),$(CURDIR)/$(dir))

export DEPSDIR	:=	$(CURDIR)/$(BUILD)

#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
EXEFILES     :=	$(foreach dir,$(TARGET),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
	export LD	:=	$(CC)
else
	export LD	:=	$(CXX)
endif

export OFILES	:=	$(addsuffix .o,$(BINFILES)) \
					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
					$(sFILES:.s=.o) $(SFILES:.S=.o)

export TARGETS := $(EXEFILES:.cpp=.dol) $(EXEFILES:.c=.dol)

#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE	:=	$(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
					-I$(CURDIR)/$(BUILD) \
					-I$(LIBOGC_INC)

#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
					-L$(LIBOGC_LIB)

export OUTPUT	:=	$(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean

#---------------------------------------------------------------------------------
$(BUILD):
	@[ -d $@ ] || mkdir -p $@
	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
	@echo clean ...
	@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol

#---------------------------------------------------------------------------------
run:
	wiiload $(TARGET).dol
	
#---------------------------------------------------------------------------------
else

DEPENDS	:=	$(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OFILES) $(TARGETS)

-include $(DEPENDS)

#---------------------------------------------------------------------------------
# This rule links in binary data with the .* extension
#---------------------------------------------------------------------------------

endif
#---------------------------------------------------------------------------------

Re: Multiple Projects: One Makefile?
July 07, 2010 08:51PM
Gah! I'm soooo close! Arasium, using your makefile, I have gotten the closest yet. Right now, It still thinks it's making just one file, instead of 30 (one for each cpp file). Can I have multiple targets in a makefile? Is that possible?

Thank you all so much! You've been so helpful. This has certainly been a great learning experience.
Re: Multiple Projects: One Makefile?
July 09, 2010 03:51AM
I believe you can have multiple targets, but I'm not at my house so i can't look at the rest of the makefile to be certain.
Re: Multiple Projects: One Makefile?
July 09, 2010 09:19AM
Have you search in the "build" folder. Theorically, the dols will be here....

I can modify some lines in order to create the dols in the main folder.

Edit: Can you send me a sample of your code in a zip file (with your folder structure). It will help me to create the makefile.



Edited 1 time(s). Last edit at 07/09/2010 09:21AM by arasium.
Re: Multiple Projects: One Makefile?
July 10, 2010 11:01PM
The link has been removed and purged.



Edited 2 time(s). Last edit at 07/25/2010 03:48AM by dancinninja.
Re: Multiple Projects: One Makefile?
July 12, 2010 09:58AM
This should works (it doesn't compile on my lapotop, but the makefile seems correct):

#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
SystemName=$(shell uname)

ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC")
endif

export	LIBOGC_INC	:=	$(DEVKITPRO)/libogc/include
export	LIBOGC_LIB	:=	$(DEVKITPRO)/libogc/lib/wii

MACHDEP =  -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float

include $(DEVKITPPC)/base_rules

#---------------------------------------------------------------------------------
%.dol: %.elf
	@echo output ... $(notdir $@)
	@elf2dol $< $@

#---------------------------------------------------------------------------------
%.tpl : %.scf
	@echo $(notdir $<)
	@gxtexconv -s $< -d $(DEPSDIR)/$*.d -o $@

#---------------------------------------------------------------------------------
%.elf: %.o
	@echo linking ... $(notdir $@)
	@$(LD)  $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET		:=	exe
BUILD		:=	build
SOURCES		:=	src/Lighting src/Simple
DATA		:=	data  
INCLUDES	:=	include

#---------------------------------------------------------------------------------
# MS Visual Studio Style Fix
#---------------------------------------------------------------------------------
STYLEFIX	= 2>&1 | sed -e 's/\([a-zA-Z\.]\+\):\([0-9]\+\):\([0-9]\+:\)\?\(.\+\)/\1(\2):\4/' -e 's/undefined/error: undefined/'

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------

CFLAGS	= -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS	=	$(CFLAGS)

LDFLAGS	=	-g $(MACHDEP) -Wl,-Map,$(notdir $@).map

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS        := -lz -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS	:=	$(PORTLIBS)

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT	:=	$(CURDIR)/$(TARGET)

export VPATH	:=	$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
					$(foreach dir,$(DATA),$(CURDIR)/$(dir))

export DEPSDIR	:=	$(CURDIR)/$(BUILD)

#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES	:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES		:=	$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES	:=	$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
EXEFILES	:=	$(foreach dir,$(TARGET),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
	export LD	:=	$(CC)
else
	export LD	:=	$(CXX)
endif

export OFILES	:=	$(addsuffix .o,$(BINFILES)) \
					$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
					$(sFILES:.s=.o) $(SFILES:.S=.o)

export ELFFILES := $(OFILES:.o=.elf)					
export DOLFILES := $(OFILES:.o=.dol)

export TARGETS := $(EXEFILES:.cpp=.dol) $(EXEFILES:.c=.dol)

#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE	:=	$(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \
					$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
					-I$(CURDIR)/$(BUILD) \
					-I$(CURDIR)/$(INCLUDES) \
					-I$(LIBOGC_INC)

#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS	:=	$(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
					-L$(LIBOGC_LIB)

.PHONY: $(BUILD) clean

#---------------------------------------------------------------------------------
$(BUILD):
	@[ -d $@ ] || mkdir -p $@
	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
	@echo clean ...
	@rm -fr $(BUILD) $(OUTPUT)

#---------------------------------------------------------------------------------
run:
	wiiload $(TARGET).dol
	
#---------------------------------------------------------------------------------
else

DEPENDS	:=	$(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT): $(OFILES) $(DOLFILES)
	@mkdir -p $(OUTPUT)

-include $(DEPENDS)

#---------------------------------------------------------------------------------
# This rule links in binary data with the .* extension
#---------------------------------------------------------------------------------

endif
#---------------------------------------------------------------------------------

The elfs and dols will be in the build folder. If you wan't the elfs in the main folder, you need to modify some variables.



Edited 1 time(s). Last edit at 07/12/2010 01:36PM by arasium.
Re: Multiple Projects: One Makefile?
July 12, 2010 09:19PM
I could kiss you! Aw MAN is that what I needed! Thank you so very very very very very much!

Did I mention that I was grateful? Awesome. Just... awesome. Thank you!

Oh, every time that I change one thing it links every output file. For example, if I alter "sample.cpp" and compile it, I would like to just compile and link sample.elf. What it does now is link sample.elf, triangles.elf, quads.elf, anotherthing.elf, fiftyobjects.elf, etc., even though I didn't change anything in anything but "sample.cpp". Nothing depends on sample.cpp. Did that make any sense at all? I hope so.



Edited 1 time(s). Last edit at 07/19/2010 02:21AM by dancinninja.
Re: Multiple Projects: One Makefile?
July 25, 2010 12:27AM
Quote
dancinninja
I set up a Google-site and added the files. I left out most of them to keep everything a lot smaller.

[link removed]

Thank you very much! I really appreciate your help.

Those are copyrighted Nintendo files. Please refrain from posting such content on these forums.
Re: Multiple Projects: One Makefile?
July 25, 2010 03:50AM
Oh my heavens, I am so sorry. I have deleted that and I promise not to do that again. I feel like such a fool. My apologies once more.
Sorry, only registered users may post in this forum.

Click here to login