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