gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > devkitARM :: C++ linking multiple classes into main...?

#49215 - justinGBA - Wed Jul 27, 2005 10:08 am

Im having trouble figuring out how i can get my class linked in to the executable, right now its pulling the headers, but not finding the function defined in the cpp files...

I'm pretty sure its my make file haunting me again... so here is what i got.

Code:

# -----------------------------------------------------------------------------
# \file         makefile
# \brief      The SGADE template make file
# \date         August 23, 2002
#
# \author      Jaap Suter, Mark T. Price
# \modified      Justin Walsh
#
# This file contains the make-instructions for a SGADE project. In
# order to use this make file you need to change
#   GCC_DIR,
#   PROJECT_DIR,
#   SOCRATES_LIB_DIR and
#   SOCRATES_INC_DIR and
# to the locations on your own computer.
#
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Project name definition;
# -----------------------------------------------------------------------------

PROJECT      = main

# -----------------------------------------------------------------------------
# Base directory of the project. Replace this with wherever
# you have put the sample application on your computer
# -----------------------------------------------------------------------------

PROJECT_DIR   = .

# -----------------------------------------------------------------------------
# GCC Version you're using. If you're using the latest DevKitAdv this
# should be correct already.
# -----------------------------------------------------------------------------
GCC_VERSION   = 3.4.4

# -----------------------------------------------------------------------------
# Base directory for GCC Arm-Agb-Elf compiler. Replace with
# wherever you have put it.
# -----------------------------------------------------------------------------

#GCC_DIR  = /usr/local/gbasdk/arm-agb-elf
GCC_DIR  = /Developer/Gameboy\ Advance/devkitARM

# -----------------------------------------------------------------------------
# Socrates library and header directories. Replace this with wherever
# you have put the Socrates on your computer
# -----------------------------------------------------------------------------

SOCRATES_LIB_DIR   = /usr/local/gbasdk/lib
SOCRATES_INC_DIR   = /usr/local/gbasdk/include/sgade

# -----------------------------------------------------------------------------
# Socrates library itself;
# -----------------------------------------------------------------------------
SOCRATES_LIB      = $(SOCRATES_LIB_DIR)/libSocrates.a

# -----------------------------------------------------------------------------
# Compiler directories for includes and libs.
# Assuming you are using Devkit Advance there should be no need to change
# these, since they are derived from the above CMP_DIR directory definition.
# -----------------------------------------------------------------------------

STD_LIB_DIR0 = $(GCC_DIR)/lib/gcc/arm-elf/$(GCC_VERSION)/interwork
STD_LIB_DIR1 = $(GCC_DIR)/arm-elf/lib/interwork

STD_INC_DIR0 = $(GCC_DIR)/lib/gcc/arm-elf/$(GCC_VERSION)/include
STD_INC_DIR1 = $(GCC_DIR)/arm-elf/include

# -----------------------------------------------------------------------------
# Project directories.
# -----------------------------------------------------------------------------

INC_DIR      = $(PROJECT_DIR)/include
SRC_DIR      = $(PROJECT_DIR)/source
CRT0_S_DIR   = $(PROJECT_DIR)
LINK_SCRIPT_DIR = $(PROJECT_DIR)
OBJ_DIR      = $(PROJECT_DIR)/build
ELF_DIR      = $(PROJECT_DIR)/build
DAT_DIR      = $(PROJECT_DIR)/data

# -----------------------------------------------------------------------------
# Define the flags for the compiler, the assembler and the linker;
# -----------------------------------------------------------------------------
C_FLAGS  = -I$(DAT_DIR) -I$(INC_DIR) -I $(SOCRATES_INC_DIR) -I$(STD_INC_DIR0) -I$(STD_INC_DIR1) -I $(SGADE_SRC_DIR) -mthumb -mthumb-interwork -c -g -Wall -fverbose-asm
CPP_FLAGS  = -I$(DAT_DIR) -I$(INC_DIR) -I $(SOCRATES_INC_DIR) -I$(STD_INC_DIR0) -I$(STD_INC_DIR1) -I $(SGADE_SRC_DIR) -mthumb -mthumb-interwork -c -g -Wall -fverbose-asm
S_FLAGS  = -I$(DAT_DIR) -I$(INC_DIR) -I $(SOCRATES_INC_DIR) -I$(STD_INC_DIR0) -I$(STD_INC_DIR1) -mthumb-interwork

L_FLAGS = -lSocrates   -L $(SOCRATES_LIB_DIR) -L$(STD_LIB_DIR0) -L$(STD_LIB_DIR1) -T $(LINK_SCRIPT_DIR)/lnkscript -lgcc -lc -lgcc

# -----------------------------------------------------------------------------
# Define the list of object files
# -----------------------------------------------------------------------------

O_FILES_FROM_C      = #$(PROJECT).o
O_FILES_FROM_CPP   = $(PROJECT).o

O_FILES_FROM_C_FULL_PATH = $(addprefix $(OBJ_DIR)/, $(O_FILES_FROM_C))

O_FILES_FROM_CPP_FULL_PATH = $(addprefix $(OBJ_DIR)/, $(O_FILES_FROM_CPP))

CRT0_O         = $(OBJ_DIR)/crt0.o

#CRTBEGIN_O      = $(STD_LIB_DIR0)/crtbegin.o
#CRTEND_O      = $(STD_LIB_DIR0)/crtend.o

O_FILES_FULL_PATH   = $(CRT0_O) $(CRTBEGIN_O) $(CRTEND_O) $(O_FILES_FROM_C_FULL_PATH)  $(O_FILES_FROM_CPP_FULL_PATH)
                     
# -----------------------------------------------------------------------------
# Define the final dependecy;
# -----------------------------------------------------------------------------
all : $(PROJECT_DIR)/$(PROJECT).gba
   @echo Done

# -----------------------------------------------------------------------------
# Define the copy from .elf to .gba file
# -----------------------------------------------------------------------------
$(PROJECT_DIR)/$(PROJECT).gba : $(ELF_DIR)/$(PROJECT).elf
   @echo Object copying
   @$(GCC_DIR)/bin/arm-elf-objcopy -v -O binary $< $@
      
      
# -----------------------------------------------------------------------------
# Define the linker instruction;
# -----------------------------------------------------------------------------
$(ELF_DIR)/$(PROJECT).elf : $(O_FILES_FULL_PATH) $(SOCRATES_LIB)
   @echo Linking object files
   @$(GCC_DIR)/bin/arm-elf-ld  $(O_FILES_FULL_PATH) -o$@ $(L_FLAGS)    
   
# -----------------------------------------------------------------------------
# Define the C compiles;
# -----------------------------------------------------------------------------
$(O_FILES_FROM_C_FULL_PATH) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
   @echo Making $@
   @$(GCC_DIR)/bin/arm-elf-gcc  -c $< -o$@ $(C_FLAGS)
   
# -----------------------------------------------------------------------------
# Define the CPP compiles;
# -----------------------------------------------------------------------------
$(O_FILES_FROM_CPP_FULL_PATH) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
   @echo Making $@
   @$(GCC_DIR)/bin/arm-elf-gcc  -c $< -o$@ $(CPP_FLAGS)
   
$(O_FILES_FROM_CXX_FULL_PATH) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cxx
   @echo Making $@
   @$(GCC_DIR)/bin/arm-elf-gcc  -c $< -o$@ $(CPP_FLAGS)
   
$(O_FILES_FROM_CC_FULL_PATH) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cc
   @echo Making $@
   @$(GCC_DIR)/bin/arm-elf-gcc  -c $< -o$@ $(CPP_FLAGS)
   
# -----------------------------------------------------------------------------
# Define the assembly of the crt0 file;
# -----------------------------------------------------------------------------
$(CRT0_O) : $(OBJ_DIR)/%.o : $(CRT0_S_DIR)/%.S
   @echo Making $@
   @$(GCC_DIR)/bin/arm-elf-gcc -c $< -o$@ $(S_FLAGS)
      
# -----------------------------------------------------------------------------
# Clean definition;
# -----------------------------------------------------------------------------
.PHONY : clean
clean :
   @echo Cleaning object, .elf and .gba files.
   @/bin/rm -f $(OBJ_DIR)/*.o
   @/bin/rm -f $(ELF_DIR)/$(PROJECT).elf
   @/bin/rm -f $(PROJECT_DIR)/$(PROJECT).gba
   @echo Clean done...


# -----------------------------------------------------------------------------
# EOF;
# -----------------------------------------------------------------------------



please help me get this right.
my suspetions are that either a its not compiling the cpp files, or not linking them into the main binary. not sure how to make my make file account for multiple cpp files and classes and what not.

#49225 - strager - Wed Jul 27, 2005 2:18 pm

justinGBA wrote:
my suspetions are that either a its not compiling the cpp files, or not linking them into the main binary. not sure how to make my make file account for multiple cpp files and classes and what not.


Did you define your class functions as this?
Code:
void myClass::myFunc(int x);

Remember you need the myClass:: in front of the function name for the compiler to detect it is part of the class.

If you want to check if it's compiling or not, make clean then make -n. It will print all the commands that will be executed, without actually running them. If your file is not compiling or not linking, well there's your problem.

If all else fails, try picking up a Makefile template from libgba or somewhere. It allows for a variable number of files of any format (you choose the commands for each one, or use the defaults) without much modification to the Makefile.

#49297 - justinGBA - Thu Jul 28, 2005 8:50 am

i know for a fact that my file is not compiling or linking. I am trying to figure out how they do those multifile makefiles, because when i try it it never works...


Like this one for the DS...
Code:

#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------

ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
endif

include $(DEVKITARM)/ds_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      :=   template
BUILD      :=   build
SOURCES      :=   gfx source data
INCLUDES   :=   include build

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH   :=   -mthumb -mthumb-interwork

# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
# *insists* it has a FPU or VFP, and it won't take no for an answer!
CFLAGS   :=   -g -Wall -O2\
          -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
         -ffast-math \
         $(ARCH)

CFLAGS   +=   $(INCLUDE) -DARM9
CXXFLAGS:=   $(CFLAGS)

ASFLAGS   :=   -g $(ARCH)
LDFLAGS   =   -specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS   := -lnds9
 
 
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS   :=   $(LIBNDS)
 
#---------------------------------------------------------------------------------
# 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))
export DEPSDIR   :=   $(CURDIR)/$(BUILD)

CFILES      :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES      :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin)))
PALFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pal)))
RAWFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.raw)))
MAPFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.map)))
 
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
   export LD   :=   $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
   export LD   :=   $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

export OFILES   :=   $(BINFILES:.bin=.o) $(PALFILES:.pal=.o) $(RAWFILES:.raw=.o) $(MAPFILES:.map=.o) \
               $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
 
export INCLUDE   :=   $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
               $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
               $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
               -I$(CURDIR)/$(BUILD)
 
export LIBPATHS   :=   $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
 
.PHONY: $(BUILD) clean
 
#---------------------------------------------------------------------------------
$(BUILD):
   @[ -d $@ ] || mkdir -p $@
   @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
 
#---------------------------------------------------------------------------------
clean:
   @echo clean ...
   @rm -fr $(BUILD) *.elf *.bin
 
 
#---------------------------------------------------------------------------------
else
 
DEPENDS   :=   $(OFILES:.o=.d)
 
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).ds.gba   :    $(OUTPUT).nds
$(OUTPUT).nds   :    $(OUTPUT).bin
$(OUTPUT).bin   :   $(OUTPUT).elf
$(OUTPUT).elf   :   $(OFILES)
 
#---------------------------------------------------------------------------------
%.nds: %.bin
   @ndstool -c $@ -9 $< -7 ../arm7/arm7.bin
   @echo built ... $(notdir $@)
 
#---------------------------------------------------------------------------------
%.o   :   %.bin
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)
 
#---------------------------------------------------------------------------------
%.o   :   %.raw
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)
   
#---------------------------------------------------------------------------------
%.o   :   %.pal
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)

#---------------------------------------------------------------------------------
%.o   :   %.map
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)
 
-include $(DEPENDS)
 
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------


For some reason they make it work just fine, but mine gets link errors with already defined and what nots.

#49333 - justinGBA - Thu Jul 28, 2005 8:40 pm

Ok, well i got it to include my classes by changing this...

Code:

O_FILES_FROM_CPP   = $(PROJECT).o


to this...

Code:

O_FILES_FROM_CPP   = $(PROJECT).o gba.o gbaSprite.o gbaTileMap.o


there has got to be some kind of command like

for every $NAME.cpp
do $NAME.o

right or something like that?
please help me fix this small annoyance, thanks!

#49403 - strager - Fri Jul 29, 2005 2:05 pm

justinGBA wrote:
there has got to be some kind of command like

for every $NAME.cpp
do $NAME.o

right or something like that?
please help me fix this small annoyance, thanks!


Yup:
Code:

# Generate a list of .cpp files using wildcards
CPP_FILES := $(wildcard *.cpp)
# Change the .cpp extention to .o for the object file name
O_FILES := $(CPP_FILES:.cpp=.o)

#49469 - justinGBA - Sat Jul 30, 2005 12:20 am

cool beans.

i had ones of those in there, but i wasn't using it. i think staring at the makefile for too long made me go crazt and overlook that command. well thanks. now im gold!