Updating archives with make

I’m trying to decrease the time it takes to build my application. Basically,
I have several source files separated into several directories. At the
present time, my makefiles are quite simple. One source is compiled at a
time, then the resulting object file is added to a single archive. Doing so
is far from being efficient. I would prefer to update the archive only once
per directory, when all the object files are up-to-date.

Make built-in rules update the archive after each object is updated. So far,
I haven’t been able to write a set of rules to update the archive only once.
I have read chapter 11 of the GNU make on-line documentation at the
following address, but with no luck…

http://www.gnu.org/software/make/manual/html_chapter/make_11.html

Some time ago, I worked on a SGI host and I recall that they had a special
makefile – something like /usr/include/make/makelib.mk – that implemented
exactly what I want to do. But I no longer have access to such a host…

Is there someone out there that has a brilliant idea :wink:

Bernard

The goal I use when making my libraries is:

$LIB): $(OBJS)
echo Rebuilding Library $@
$(AR) $(ARFLAGS) $(LIB) $?

Where:
AR := ar
ARFLAGS := r

and
$? is defines by make as "The names of all of the prerequisits that
are newer than the target.

I hope this helps.


Bernard Leclerc <bernard@whittom-leclerc.ca> wrote:
BL > I’m trying to decrease the time it takes to build my application. Basically,
BL > I have several source files separated into several directories. At the
BL > present time, my makefiles are quite simple. One source is compiled at a
BL > time, then the resulting object file is added to a single archive. Doing so
BL > is far from being efficient. I would prefer to update the archive only once
BL > per directory, when all the object files are up-to-date.

BL > Make built-in rules update the archive after each object is updated. So far,
BL > I haven’t been able to write a set of rules to update the archive only once.
BL > I have read chapter 11 of the GNU make on-line documentation at the
BL > following address, but with no luck…

BL > http://www.gnu.org/software/make/manual/html_chapter/make_11.html

BL > Some time ago, I worked on a SGI host and I recall that they had a special
BL > makefile – something like /usr/include/make/makelib.mk – that implemented
BL > exactly what I want to do. But I no longer have access to such a host…

BL > Is there someone out there that has a brilliant idea :wink:

BL > Bernard


\

Bill Caroselli – Q-TPS Consulting
1-(708) 308-4956 <== Note: New Number
qtps@earthlink.net

Just a few more comments about speeding up your makes.

I am very impatient too. (And damn proud of it!)

If you are running make from a pterm under photon, do everything you
can to minimize the amount of text that is displayed. Scrolling text
in a pterm is just too damn slow. Want proof? Try this:

time make uncond
(use whatever goal to use to force a make of everything)
then try this:
time make uncond > /dev/null

The other thing I do to speed up my makes is that I compile and link
everything into a directory under /tmp which is a ramdisk on my system.
Then I copy the executable to where ever is needs to end up.


Bernard Leclerc <bernard@whittom-leclerc.ca> wrote:
BL > I’m trying to decrease the time it takes to build my application. Basically,
BL > I have several source files separated into several directories. At the
BL > present time, my makefiles are quite simple. One source is compiled at a
BL > time, then the resulting object file is added to a single archive. Doing so
BL > is far from being efficient. I would prefer to update the archive only once
BL > per directory, when all the object files are up-to-date.

BL > Make built-in rules update the archive after each object is updated. So far,
BL > I haven’t been able to write a set of rules to update the archive only once.
BL > I have read chapter 11 of the GNU make on-line documentation at the
BL > following address, but with no luck…

BL > http://www.gnu.org/software/make/manual/html_chapter/make_11.html

BL > Some time ago, I worked on a SGI host and I recall that they had a special
BL > makefile – something like /usr/include/make/makelib.mk – that implemented
BL > exactly what I want to do. But I no longer have access to such a host…

BL > Is there someone out there that has a brilliant idea :wink:

BL > Bernard


\

Bill Caroselli – Q-TPS Consulting
1-(708) 308-4956 <== Note: New Number
qtps@earthlink.net

Bill Caroselli <qtps@earthlink.net> wrote:

BC > The goal I use when making my libraries is:

BC > $LIB): $(OBJS)
BC > echo Rebuilding Library $@
BC > $(AR) $(ARFLAGS) $(LIB) $?

Actually:
$LIB): $(OBJS)
@echo Rebuilding Library $@
@$(AR) $(ARFLAGS) $(LIB) $?

Add the ‘@’ to speed up by not printing the command line.


Bill Caroselli – Q-TPS Consulting
1-(708) 308-4956 <== Note: New Number
qtps@earthlink.net

Bill, this rule works when you have a single directory where sources
reside. Assume you have two directories (src/dir1 and src/dir2) and
let’s say that the archive $(LIB) is defined as src/libapp.a. A rule
like the one you use will work fine when you first build objects in dir1
and dir2. But if you delete src/libapp.a (without deleting objects in
dir1 and dir2) and do make, you will notice that none of the objects
from dir2 will appear in the archive. Why? Because the date on the file
src/libapp.a will be newer than the date of any objects in dir2.

Bernard



“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:bog98s$oan$2@inn.qnx.com

The goal I use when making my libraries is:

$LIB): $(OBJS)
echo Rebuilding Library $@
$(AR) $(ARFLAGS) $(LIB) $?

Where:
AR := ar
ARFLAGS := r

and
$? is defines by make as "The names of all of the prerequisits that
are newer than the target.

I hope this helps.

How about:
$LIB): $(OBJS1) $(OBJS2)
echo Rebuilding Library $@
$(AR) $(ARFLAGS) $(LIB) $?

I think this will make any of the necessary obj’s first and then
compare their timestamps to the LIB timestamp.

If it doesn’t work for you, maybe someone else can help.
Sorry. I gave it my best shot.


Bernard Leclerc <bernard.leclerc@mindready.com> wrote:
BL > Bill, this rule works when you have a single directory where sources
BL > reside. Assume you have two directories (src/dir1 and src/dir2) and
BL > let’s say that the archive $(LIB) is defined as src/libapp.a. A rule
BL > like the one you use will work fine when you first build objects in dir1
BL > and dir2. But if you delete src/libapp.a (without deleting objects in
BL > dir1 and dir2) and do make, you will notice that none of the objects
BL > from dir2 will appear in the archive. Why? Because the date on the file
BL > src/libapp.a will be newer than the date of any objects in dir2.

BL > Bernard



BL > “Bill Caroselli” <qtps@earthlink.net> wrote in message
BL > news:bog98s$oan$2@inn.qnx.com

The goal I use when making my libraries is:

$LIB): $(OBJS)
echo Rebuilding Library $@
$(AR) $(ARFLAGS) $(LIB) $?

Where:
AR := ar
ARFLAGS := r

and
$? is defines by make as "The names of all of the prerequisits that
are newer than the target.

I hope this helps.


Bill Caroselli – Q-TPS Consulting
1-(708) 308-4956 <== Note: New Number
qtps@earthlink.net

Actually, I don’t see why both won’t work. Can you post your makefile?

Bill Caroselli <qtps@earthlink.net> wrote:
BC > How about:
BC > $LIB): $(OBJS1) $(OBJS2)
BC > echo Rebuilding Library $@
BC > $(AR) $(ARFLAGS) $(LIB) $?

BC > I think this will make any of the necessary obj’s first and then
BC > compare their timestamps to the LIB timestamp.

BC > If it doesn’t work for you, maybe someone else can help.
BC > Sorry. I gave it my best shot.


BC > Bernard Leclerc <bernard.leclerc@mindready.com> wrote:
BC > BL > Bill, this rule works when you have a single directory where sources
BC > BL > reside. Assume you have two directories (src/dir1 and src/dir2) and
BC > BL > let’s say that the archive $(LIB) is defined as src/libapp.a. A rule
BC > BL > like the one you use will work fine when you first build objects in dir1
BC > BL > and dir2. But if you delete src/libapp.a (without deleting objects in
BC > BL > dir1 and dir2) and do make, you will notice that none of the objects
BC > BL > from dir2 will appear in the archive. Why? Because the date on the file
BC > BL > src/libapp.a will be newer than the date of any objects in dir2.

BC > BL > Bernard

Bill, here is an example:


First, the directory content:

~/src> ls -Rv

…:
dir1/ dir2/ Makefile

…/dir1:
Makefile source1.c

…/dir2:
Makefile source2.c


Then, the content of the 3 Makefiles:

~/src> cat Makefile
all:
make -C dir1 LIB=…/libapp.a
make -C dir2 LIB=…/libapp.a
clean:
-rm libapp.a dir{1,2}/*.o

~/src> cat dir1/Makefile
$(LIB) : source1.o
ar -cru $@ $^

~/src> cat dir2/Makefile
$(LIB) : source2.o
ar -cru $@ $^


I’m using the default rule for compiling a C source.

If you’re running make, chances are you will end up with a single file
in the archive. Also, if you simply delete libapp.a and run make, only
source1.o will be archived.

Try this:
~/src> make clean
~/src> make

Here is the output I obtain when I run make after a clean:

~/src> make
make -C dir1 LIB=…/libapp.a
make[1]: Entering directory /home/blc/src/dir1' cc -c -o source1.o source1.c ar -cru ../libapp.a source1.o make[1]: Leaving directory /home/blc/src/dir1’
make -C dir2 LIB=…/libapp.a
make[1]: Entering directory /home/blc/src/dir2' cc -c -o source2.o source2.c make[1]: Leaving directory /home/blc/src/dir2’

And here is what ends up in the archive:

~/src> ar tv libapp.a
rw-rw-r-- 103/100 721 Nov 10 13:18 2003 source1.o


Conclusion: a simple rule like the one you are using is not enough to
correctly handle an archive made of objects from several directories.

Reason: with this rule, make looks for the modification time of the
archive while we should look for the modification time of the member
(the object file) inside the archive.

Any other ideas?


Bernard



“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:booe3q$cua$2@inn.qnx.com

Actually, I don’t see why both won’t work. Can you post your
makefile?

Bill Caroselli <> qtps@earthlink.net> > wrote:
BC > How about:
BC > $LIB): $(OBJS1) $(OBJS2)
BC > echo Rebuilding Library $@
BC > $(AR) $(ARFLAGS) $(LIB) $?

BC > I think this will make any of the necessary obj’s first and
then
BC > compare their timestamps to the LIB timestamp.

BC > If it doesn’t work for you, maybe someone else can help.
BC > Sorry. I gave it my best shot.