The issue explained
Say directory structure is as follows:
$ tree . |-- Makefile `-- lib.cpp 0 directories, 2 files
With lib.cpp
:
void libfunc()
{
}
and Makefile
:
lib.a: lib.o Makefile $(AR) rcuvs $@ $<
The issue:
$ make g++ -c -o lib.o lib.cpp ar rcuvs lib.a lib.o a - lib.o $ make make: `lib.a' is up to date. $ touch Makefile $ make ar rcuvs lib.a lib.o $ make ar rcuvs lib.a lib.o ...
So there is a flaw in how ar
tool operates on replacing archive members
when used with make
: if output file already exists, but none of input
files is newer than corresponding file in the archive, modification
date of the archive remains the same. As a result, make file rule is always
triggered.
It happens only when ar
is told to update object files. Which is done in
this case using r
switch and u
modifier. From man ar
:
r Insert the files member... into archive (with replacement).
u Normally, ar r... inserts all files listed into the archive. If you would like to insert only those of the files you list that are newer than existing members of the same names, use this modifier. The u modifier is allowed only for the operation r (replace). In particular, the combination qu is not allowed, since checking the timestamps would lose any speed advantage from the operation q.
The solution (or workaround)
Add touch library.a
after calling ar
. Updated Makefile
:
lib.a: lib.o Makefile $(AR) rcuvs $@ $< touch $@
Now output is as expected:
$ make ar rcuvs lib.a lib.o touch lib.a $ make make: `lib.a' is up to date.
// load comments