Skip to main content
gamedev.net
🔒 Locked

Makefile question - SOLVED

Started by Replicon Jun 4, 2006 at 1:24 PM 3 replies 1.1k views
Original Post
Replicon
Replicon
Why is it that the $@ variable is not available in the dependency list, but only in the body of the makefile block. Those are odd scoping rules, and I'm trying to get around it somehow. I'll give a simple example to show what I mean: Suppose I have something like this:

prog1: $(OBJS) prog1.o
	@echo "Linking $@..."
	@$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.o

prog2: $(OBJS) prog2.o
	@echo "Linking $@..."
	@$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.o
This works fine. Clearly, I'm separating the executable's linker object from the libraries' ones, since I have more than one executable. That's fine and dandy. But what if I don't want to have that ugly repeating code block? I can have a variable called DESTS, containing "prog1 prog2" and try to do something like this:

$(DESTS): $(OBJS) $@.o
	@echo "Linking $@..."
	@$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.o
This works great if I don't have that $@.o in the dependency list and compile the .o separately somewhere else, but if I try to do what the sample above shows, it says it can't find ".o" (in other words, $@ is empty until the echo statement below). Am I totally on crack here? Is there a way to do this nicely? The problem with setting up .o compilation of the exe's outside of that block is that if I change just the code in (say) prog1.cpp, then it will not relink everything, because prog1.o is not in the dependency list..... help? :) [Edited by - Replicon on June 4, 2006 11:49:50 PM]
jamessharpe
jamessharpe
If you're using GNU make > =3.80 you can use eval and call to do what you want:

# Creates rules to create a library# $(eval $(call make-exe prog-name,objs))define make-exe   $1: $2 $1.o      @echo "Linking $@..."      @$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.oendef$(eval $(call prog1,$(objs)))$(eval $(call prog2,$(objs)))
JohnBolton
JohnBolton
You could do this:
    all: $(DESTS)        %: %.o        @echo "Linking $@..."        @$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.o 
In theory that should work, but having "%" as a target may be a problem because Make will try to apply the rule to every file.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Replicon
Replicon
Quote:
Original post by jamessharpe
If you're using GNU make > =3.80 you can use eval and call to do what you want:

# Creates rules to create a library# $(eval $(call make-exe prog-name,objs))define make-exe   $1: $2 $1.o      @echo "Linking $@..."      @$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.oendef$(eval $(call prog1,$(objs)))$(eval $(call prog2,$(objs)))


That's a cool and interesting approach :). Interestingly, when I have several eval calls like you do in your sample, it only executes the first one (no errors). Also, if instead of putting it in the body, I put it under a target (say 'default:'), it warns about overriding commands for target and ignoring old commands for target. Very odd behaviour. I also tried doing something like that with a foreach on $(DESTS), but again, it only executed the first one.



Quote:
JohnBolton
all: $(DESTS)        %: %.o        @echo "Linking $@..."        @$(LD) $(LDFLAGS) -o $@ $(OBJ) $@.o 


This looks like it works, but it (by default) deletes all the .o's it created and only leaves the binary behind, which defeats the purpose. Why does it do an rm on all those .o files? It's not executing my own clean target, it's a builtin of some sort.... gah!
Replicon
Replicon
Bingo! I just realized what eval actually does hehe sorry for the confusion :-). I was able to use a foreach to generate all my targets. My magic Makefile is now working!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.