|We have been successfully using recursive Makefiles for many libraries and
|executables from many different directories. We enhanced the scheme to use
|sublibraries to minimize the time spent archiving especially on slow CPU's
|with 1000 module libraries. The sublibrary enhancement reduced our time on
|one platform from 24 hours to 8 hours. We would like to avoid the sublibrary
|scheme altogther; however, we keep running into make's limitations, or our
|misunderstandings of make. We now would like to build each object (source
|and object in different directories) without archiving until the end of all
|of the compilation for that library. The .c.o rule seems to imply that the
|source and objects are in the same directory, so we attempted to specify each
|object on a separate dependency line (even those with no depencies) but could
|not take advantage of a common compile line. Is there a way to do this?
I understand you want two things, that aren't directly related:
a) postpone archiving until each object of the library has been made.
b) separate source and object files in different directories.
Ad a): This is what we do here too, it saves considerable time & CPU
cost. In a BSD environment you can do an 'ar q' to quickly build the
archive(s) (I think it works for System V too, at least on our Pyramid).
Say your target executable needs libraries $(LIB_a), $(LIB_b) etc.
which contain respectively $(OBJECTS_a), $(OBJECTS_b) etc., a rule to
build say $(LIB_a) would be
$(LIB_a) : $(OBJECTS_a)
The rule to build the final target would look something like:
$(TARGETPROG) : main.o $(LIB_a) $(LIB_b)
By always doing a complete rebuild of each library, one avoids the
quadratic behaviour that can result from 'ar'-ing each module
separately. In the complete rebuild case ar is started only once and
each module put at the end of the archive (without checking whether it
already exists). In the separate rebuild case the archive has to be
read and written (almost entirely) each time.
b) A solution for this could be to dynamically generate the Make
dependencies and rules, then pass them to Make, something like this:
CDIR = /usr/me/srcdir
ODIR = /usr/me/objdir
SOURCES = myfile1.c myfile2.c # or perhaps *.c
OBJECTS = `echo $(SOURCES)|sed "s^\([^ ]*\)\.c^$(ODIR)/\1.o^g"`
(cd $(CDIR); ls $(SOURCES))|\
(echo all : $(OBJECTS); cat)|\
$(MAKE) $(MFLAGS) -f -
Note that the $(OBJECTS) are full pathnames in this case and generated
dynamically from the $(SOURCES) list.