I am wondering if it is possible to setup a makefile rule so as to automatically remove object files which are no longer present in the library without having to do a clean build. I have my makefile setup like this.
SRC_FILES = a.c b.c c.c
libtest.a : $(SRC_FILES:.c=.o)
ar -rcs $@ $?
%.o : %.c
gcc -o $@ -c $<
Now suppose i remove c.c
from SRC_FILES
, I want the next make run to delete the corresponding object file from the archive. Is there any way to do this without having to run a clean build? Deleting the archive first and then rebuilding it doesn't work since the rule is never invoked when the library is more recent than all its dependencies. I also don't wanna rebuild the library if nothing actually changed, so making it a .PHONY wont work either.
There's nothing automatic or built-in that you can do. make
just isn't very good at noticing this sort of thing. The simplest thing you can do that would "solve" this problem would be to keep a FORCE
d target that contains a list of the source files represented in the archive, include that file as a prerequisite of libtest.a
and compare the contents of the file against the contents of the archive and rebuild/add/delete/etc. to/from the library as appropriate.
libtest.lst: FORCE $(SRC_FILES:.c=.o)
printf '%s\\n' $(filter-out $<,$^) > $@
libtest.a: libtest.lst $(SRC_FILES:.c=.o)
ar t $@ > $@.contents
if diff -q $@.contents libtest.lst; then \
ar ....; \
fi
rm $@.contents
Or if you don't care about avoiding the rebuilding forget the listing/diffing/etc. and just re-run the ar
command to build the archive.
As an additional improvement you could add the diffing logic to the libtest.lst
recipe instead so that it only updates the libtest.lst
file if it changes (to avoid make
thinking it needs to run the libtest.a
rule when the library contents haven't changed). Something like this.
libtest.lst: FORCE $(SRC_FILES:.c=.o)
printf '%s\\n' $(filter-out $<,$^) | sort > $@.tmp
cmp -s $@ $@.tmp || mv $@.tmp $@
rm -f $@.tmp
libtest.a: libtest.lst $(SRC_FILES:.c=.o)
ar -rcs $@ $(filter-out $<,$?)