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.

Coding > Unexpected Makefile behavior

#168051 - sgeos - Wed Apr 08, 2009 10:57 am

Given the following Makefile:
Code:
LIBS = librng.a

.PHONY : all
all : $(LIBS) Makefile

%/lib.a : force_look
        ls $*/*.a
        cd $*; $(MAKE) $(MFLAGS) lib.a

lib%.a : %/lib.a
        cp $< $@
        ls $*/*.a

.PHONY : force_look
force_look :
        true


I get the following output:
Code:
$ make
true
ls rng/*.a
rng/librng.a
cd rng; make  lib.a
make[1]: Entering directory `/home/USER/cpp/maze/lib/rng'
rm -f lib.a
ar cq lib.a RNG.o
make[1]: Leaving directory `/home/USER/cpp/maze/lib/rng'
cp rng/lib.a librng.a
ls rng/*.a
rng/lib.a  rng/librng.a


The problem is that when everything is said and done, lib.a does not exist in rng/
Code:
$ ls rng/*.a
rng/librng.a


This is not the case if I explicitly make rng/lib.a. Why is make doing this?

#168053 - gauauu - Wed Apr 08, 2009 2:53 pm

I've had this happen before -- as far as I can tell, make thinks your lib.a is an intermediate file, and thus deletes it when finished with it.

I've ran into various workarounds, searching on google about make deleting intermediate files.

#168060 - sgeos - Wed Apr 08, 2009 5:40 pm

I found information about this here. It appears that the solution is to explicitly mention the file anywhere, like this:
Code:
.PHONY : do-not-delete
do-not-delete : me.file or-me.file

Is there a way to have libmyfile.a depend on myfile/libmyfile.a using a pattern rule? The following does not work:
Code:
lib%.a : %/lib%.a

Right now I'm always running the rule and using cp -u as a work around, but this approach does not feel right.

#168070 - kusma - Thu Apr 09, 2009 12:18 am

sgeos wrote:
I found information about this here. It appears that the solution is to explicitly mention the file anywhere, like this:
Code:
.PHONY : do-not-delete
do-not-delete : me.file or-me.file

Is there a way to have libmyfile.a depend on myfile/libmyfile.a using a pattern rule? The following does not work:
Code:
lib%.a : %/lib%.a

Right now I'm always running the rule and using cp -u as a work around, but this approach does not feel right.

I think what you're searching for might be the ".SECONDARY" pseudo-target.

#168074 - sgeos - Thu Apr 09, 2009 12:43 am

kusma wrote:
I think what you're searching for might be the ".SECONDARY" pseudo-target.

That was mentioned in link above, but it appears that .SECONDARY does not support pattern rules. Also, .SECONDARY is buggy according to the maintainer at the time the information in the above link was written. Explict mention using a dummy target was recommended by the maintainer.

#168085 - gauauu - Thu Apr 09, 2009 3:19 pm

sgeos wrote:

Is there a way to have libmyfile.a depend on myfile/libmyfile.a using a pattern rule? The following does not work:


This is where my lack of knowledge of makefiles starts showing itself, but maybe something along the general idea of:
Code:

lib%.a : $(patsubst lib%.a,%/lib%.a, $@)


With the idea that $@ would be libmyfile.a, and the patsubst would change it to myfile/libmyfile.a?

#168089 - sgeos - Thu Apr 09, 2009 6:24 pm

gauauu wrote:
Code:
lib%.a : $(patsubst lib%.a,%/lib%.a, $@)

With the idea that $@ would be libmyfile.a, and the patsubst would change it to myfile/libmyfile.a?

EDIT: patsubst changes it to myfile/lib%.a

This seemed to work, but upon testing it didn't seem to update files after I made changes. It also appears that I need to try to recursively remake every library anyway, so this is what I am currently using:
Code:
SRCDIR = rng programargument
INCDIR = ../include
DSTLIB = $(patsubst %,lib%.a,$(SRCDIR))

.PHONY : all
all : $(DSTLIB) Makefile

lib%.a : force_look
        cd $*; $(MAKE) $(MFLAGS) lib$*.a
        cp -u $*/$@ $@
        -cp -u $*/*.h $(INCDIR)
        -cp -u $*/*.hpp $(INCDIR)

.PHONY : force_look
force_look :
        true

I was hoping to have lib%.a depend on %/lib%.a, and have %/lib%.a depend on force_look, but that seemed to involve voodoo beyond my abilities and this seems to do the trick.

Thanks for your help though.

#169635 - Karatorian - Mon Jul 27, 2009 5:24 pm

Too keep (GNU) make from deleting intermediate files, you can use the .PRECIOUS directive, like so:
Code:

.PRECIOUS: %.img %.pal

Depending on what you're looking for, this could be the proper solution, or just a work around. Basically, when you run make without an argument, you're telling it that you want "librng.a". It's sort of implied that you don't care about "rng/lib.a". If "rng/lib.a" is supposed to be a target, it should be specified as such. If it's not supposed to be a target, but you want to avoid rebuilding it every time (basically, you want to cache it), precious is the way to go.

#169667 - sgeos - Tue Jul 28, 2009 4:37 pm

I saw .PRECIOUS, but I'd need to go back and look into this again. Thanks for the information.