Link to home
Start Free TrialLog in
Avatar of pixitron
pixitron

asked on

Simple Makefile issue

Hi,
I'm getting started with the arm/linux/gnu flow and I wish to have a makefile with multiple targets, as i'm cross compiling for a arm platform but i also want to check everything is running ok on my X86 laptop.  But with my makefile below it always seems to pick up the ARM rule, despite the fact i issue from the command line make as opposed to make ARM? Also as i'm new to makefile, if you've any suggestions how to make my makefile "better" that would be great too! thanks

EXE := prog
SRCS:= src/a.cpp src/b.cpp  
OBJS = $(SRCS:%.cpp=%.o)
INCDIR = -I. -I.. -Iincludes
#------------------------------------------------------------------------
CC        := g++
ARMCC     := arm-linux-g++
#Optimization and debug info options
OPT       := -O3
DEBUG     := -01 -g
PROFILE   := -pg
OTHER     := -Wall -Wno-deprecated -Wno-char-subscripts
OTHER_ARM := -barm-linux -Wa,-mcpu=arm9tdmi -Wall -Wno-deprecated -Wno-char-subscripts
CFLAGS    := $(OPT) $(OTHER)
#------------------------------------------------------------------------
# Default rule:
$(EXE) : $(OBJS)
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)
      /bin/rm -f $(OBJS) includes/*~ *~ src/*~
%.o : %.cpp
      $(CC) $(CFLAGS) $(INCDIR) -c -o $@ $<  
#------------------------------------------------------------------------
#Debug
debug : $(OBJS)
      $(CC) $(OPT) $(OTHER) $(DEBUG) -o $(EXE) $(OBJS)
%.o : %.cpp
      $(CC) $(OPT) $(OTHER) $(DEBUG) -c -o $@ $<        
#------------------------------------------------------------------------
#Profile
profile : $(OBJS)
      $(CC) $(OPT) $(OTHER) $(PROFILE) -o $(EXE) $(OBJS)
%.o : %.cpp
      $(CC) $(OPT) $(OTHER) $(PROFILE) -c -o $@ $<       
#------------------------------------------------------------------------
#Cross compile for ARM
ARM : $(OBJS)
      $(ARMCC) $(OTHER_LINK) $(OPT) $(INCDIR) -o $(EXE) $(OBJS)
%.o : %.cpp
      $(ARMCC) $(CFLAGS) $(INCDIR) -c -o $@ $<  

#------------------------------------------------------------------------
clean:
      /bin/rm -f $(EXE) $(OBJS) includes/*~ *~ src/*~

# Dependancies
b.o : a.h
a.o : a.h
Avatar of jkr
jkr
Flag of Germany image

>># Default rule:
>>$(EXE) : $(OBJS)

That does not really specify the default rule - a default rule would be

.DEFAULT: $(EXE)
Avatar of pixitron
pixitron

ASKER

right that makes more sense. So i made the change. However its still always picking up the arm cross compile rule (well it appears to pick up the arm cross compile rule for the src files and default rule for linking)?
any more ideas?
tried wrapping the ARM crosscompile rules in an ifdef arm,, but if i type  make arm, make then compains there is no rule for arm
You have multiple rules for

%.o : %.cpp

The last one defined wins.  If you have several different options, it is better to have several different makefiles and to have a master makefile invoking one of the others.
Thanks cup,

thats exactly the behaviour i'm seeing all right (last rule winning). How would i go about having a master/slave makefiles? (any links would be great). Also would each of the "slave" makefiles then have their own dependancy listings as well (that seems like it would be a nightmare to maintain?).

Taking a step back is there a better way of doing what I'm trying to do?

I'm going to increase the points by 125 for this question.
You have basically gotten it the wrong way round.  The assignments can change, the rules can't.  I've never seen := in makefiles before.  I assume it is the same as =

The top bit is the same until CFLAGS=

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

vanilla: $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

debug:  $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER) $(DEBUG)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

profile:  $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER) $(PROFILE)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

ARM: $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER)
      CC=arm-linux-g++
      LFLAGS=whatever you have in OTHER_ARM
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

From clean: onwards it is the same.  You don't really need a master makefile for this case.  The master makefile idea is recursive normally use it for biggish projects which go over several directories.  The thing to remember is that the first colon and last rule wins.  In a makefile with several targets, if no parameters are provided, it makes the target in the first colon.

Make good use of whatever debugging flags your make provides.  Some provide more debugging information than others.  Some even use default makerules which they pick from somewhere else.  This isn't obvious until you switch on debugging.

Good luck.
"You have basically gotten it the wrong way round..."

AHA! ok this is beginning to make more sense.  

For the ARM target though the compiler for the source code is not g++ its arm-linux-g++, won't the above rule compile the src files with g++ and try to link these files with arm-linux-g++ ?

Also I'm not sure what rule i should have for $(EXE) target - while i try to run the makefile, it compiles the src files but then says :  

make: *** No rule to make target `neuro', needed by `vanilla'.  Stop.

(exe= neuro btw)

Thanks a million for the help! Current Makefile is below

------------------------------------------------------------------------------------------------------------------------------
EXE := neuro
SRCS:= ***********
OBJS = $(SRCS:%.cpp=%.o)
INCDIR = -I. -I.. -Iincludes
#------------------------------------------------------------------------
#Optimization and debug info options
OPT       := -O3
DEBUG     :=  -g
PROFILE   := -pg
OTHER     := -Wall -Wno-deprecated -Wno-char-subscripts
#------------------------------------------------------------------------
%.o: %.cpp
      $(CC) $(CFLAGS) $(INCDIR) -c -o $@ $<

#------------------------------------------------------------------------
vanilla: $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)
#------------------------------------------------------------------------
debug:  $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER) $(DEBUG)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)
#------------------------------------------------------------------------
profile:  $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER) $(PROFILE)
      CC=g++
      LFLAGS=
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

#------------------------------------------------------------------------
#Cross compile for ARM Linux
#Surely compile of src files with g++ will cause a problem??
ARM: $(OBJS) $(EXE)
      CFLAGS=$(OPT) $(OTHER)
      CC=arm-linux-g++
      LFLAGS=-barm-linux -Wa,-mcpu=arm9tdmi -Wall -Wno-deprecated -Wno-char-subscripts
      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)

#------------------------------------------------------------------------
clean:
      /bin/rm -f $(EXE) $(OBJS) includes/*~ *~ src/*~

#------------------------------------------------------------------------
# Source Dependancies




Oops - sorry $(EXE) should not be a dependency.   It should be

vanilla: $(OBJ)
   ...

Ok, however I'm still getting a problem from...

vanilla: $(OBJS)
<TAB>      CFLAGS=$(OPT) $(OTHER)
<TAB>      CC=g++
<TAB>      LFLAGS=
<TAB>      $(CC) $(CFLAGS) $(INCDIR) -o $(EXE) $(OBJS)


CFLAGS=-O3 -Wall -Wno-deprecated -Wno-char-subscripts
/bin/sh: line 1: -Wall: command not found
make: *** [vanilla] Error 127
It looks like the commands are being executed.  Try changing your = to :=
As I said earlier, I haven't used this version of make before.  It looks like  = is a shell assignment and := is a make assignment.
I'm using (GNU) make under linux (RH9). Tried changing = to :=  but it didn't make any difference.


increasing points again
If I can get my Linux box started (about 4 years since I've switched it on) I'll try out your make stuff.  At a guess, it doesn't like the assignments.  I'll try a few experiments to see if I can get it done in one makefile.  The alternative is to have 5 makefiles.
Managed to ressurect my Linux box.   Anyway try this - it uses make recursively.  Not the best option but sometimes make is a pig and it is the easiest way around it

EXE := neuro
SRCS:= a.cpp b.cpp
OBJS = $(SRCS:%.cpp=%.o)
INCDIR = -I. -I.. -Iincludes
#------------------------------------------------------------------------
#Optimization and debug info options
OPT       := -O3
DEBUG     :=  -g
PROFILE   := -pg
OTHER     := -Wall -Wno-deprecated -Wno-char-subscripts
CFLAGS=$(OPT) $(OTHER)
# these may be overridden by the recursive make parameters
EXTRA=
CC=g++
LFLAGS=
#------------------------------------------------------------------------
%.o: %.cpp
      $(CC) $(CFLAGS) $(EXTRA) $(INCDIR) -c -o $@ $<

#------------------------------------------------------------------------
target:  $(OBJS)
      $(CC) $(CFLAGS) $(EXTRA) $(INCDIR) -o $(EXE) $(OBJS)
#------------------------------------------------------------------------
debug:
      make EXTRA="$(DEBUG)"
#------------------------------------------------------------------------
profile:
      make EXTRA="$(PROFILE)"
#------------------------------------------------------------------------
#Cross compile for ARM Linux
#Surely compile of src files with g++ will cause a problem??
ARM:
      make CC=arm-linux-g++ LFLAGS="-barm-linux -Wa,-mcpu=arm9tdmi -Wall -Wno-deprecated -Wno-char-subscripts"

#------------------------------------------------------------------------
clean:
      /bin/rm -f $(EXE) $(OBJS) includes/*~ *~ src/*~

Forgot to say that the command line parameters override local settings.

Use "make -d" to see what is happening.
ASKER CERTIFIED SOLUTION
Avatar of cup
cup

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
excellent! I don't know whether the recursive option is good or bad, but it certaily solves my problem! and I've learned alot about makefiles.

thanks again for the all the effort!