Hello Ian,
On Jul 14, 2007, at 8:34 PM, Ian Lynagh wrote:
On Sat, Jul 14, 2007 at 07:43:49PM -0400, Peter Tanski wrote:
On Jul 14, 2007, at 5:07 PM, Ian Lynagh wrote:
On Fri, Jul 13, 2007 at 04:56:44PM -0400, Peter Tanski wrote:
$(foreach SUBDIR,$(SUBDIRS),build.library.$(SUBDIR)): \
build.library.% build-stamp.library.%: ...
<commands>
touch build-stamp.library.$*
The problem with the $(foreach ) is the overlap between
build.library.
$(SUBDIR) and build.library.% .
Actually, the problem is that we're only allowed one pattern in the
middle section (which should match the targets in the first section).
For example, with unix, this expands
to:
build.library.unix : build.library.% build-stamp.library.% : ...
I think you're misunderstanding the syntax. It's using "Static Pattern
Rules", which restricts what the pattern is allowed to match to the
list
of targets given. i.e. rather than the normal
<target patterns> : <prereqs>
we have
<targets> : <target pattern> : <prereqs>
I certainly did. I would have recognised
build.library.unix : build.library.%:configure.library.%
but having two patterns in the middle section and everything on
separate lines threw me off (maybe it should have clued me in). As
it is, though, if it wasn't a static pattern rule, if you would have:
filename.c : filename.%
that is clearly circular.
I tend not to use static pattern rules because Make can't use one
rule for several different directories:
source_dirs := src/includes src/powerpc src/powerpc/asm src
source_files := $(foreach dir,$(source_dirs),$(wildcard $(dir)/*.c))
Now you have a list of source files in different directories so you
can't use one rule without VPATH, requiring Make in the build
directory, or give up VPATH and run recursive Make from each
subdirectory or write everything out (as Cmake would). That is too
limiting or it sullies with my precious source directories.
I'm not sure if we actually need the explicit target list for the
libraries Makefile; it might be worth removing it and seeing if it
works.
Essentially use Make to parse the target commands and pass them to
the appropriate Cabal? If Cabal can handle that, it seems like the
best idea yet. (More on this below.)
Concerning rebuilds, if Make can see all the targets individually, as
files, then you should be able to dispense with the build-stamp
files.
I'm not sure what you mean. There isn't a file we can use to know if
configure has been run, for example, which is why we use stamp files.
We don't want to rerun configure each time we remake a library.
What about the timestamps for the .setup-config or .installed-pkg-
config? Those are created or updated by Cabal configuration runs.
You could force a rebuild by making the PHONY rebuild.$
(SUBDIR) a dependancy of FORCE: but then it might still rebuild base
if you want to force a rebuild of unix--I haven't used FORCE before,
though I have used 'make -o file'. I'm not sure why you would want
to do this often--if Make can 'see' everything then you should be
able to say 'make unix' and Make would only rebuild changed files as
it normally does.
make can't see everything as each library has a separate Makefile.
Some things are also still hidden by the Cabal abstraction.
I was thinking about that. As it is now, Cabal stands in place of
the recursive-Makefile: normally you would have a top-level Makefile
call the lower-level Makefile and if the lower-level Makefile sees
that everything is up to date, it returns; otherwise it runs the
commands. The only alternative to Cabal would be to have the top-
level Makefile run the Cabal-generated Makefile recursively.
Of course, this means the libraries should be in
the Makefile based on their library name (libunix.a) and the
directory names should be declared PHONY.
PHONY: unix
libunix.a :
[commands]
unix: libunix.a
This doesn't work:
Suppose you make some changes to the unix library, and run "make
unix".
make checks that libunix.a is up-to-date and, seeing as it has no
dependencies, concludes that it is. This you can't rebuild the
library.
I left out libunix.a's dependancies for brevity--I should have elided
them. (Imagine I meant standard Make without Cabal in between, where
Make sees every file.) That seems to be the most robust alternative
to running everything through Cabal but it negates the purpose of
using Cabal. (If this were my project, that is probably what I would
do; it is nice and simple, if a bit ham-handed. Hybrid Make-as-
command-line-parser only works if the underlying build system handles
_everything_: like running xcodebuild from a Makefile for the
convenience typing only 'make <target>' or just 'make'.) Another
alternative would be to update Cabal so it can configure and build
multiple "projects." Now that would be excellent!
My make doesn't have the FORCE you talk about above, so I'm not
sure if
that solves the problem. I can't see how it would without also meaning
that base always gets rebuilt, though.
I think FORCE came out with Make 3.80.
The way I was proposing to change libraries/Makefile, I would have in
the end made PHONY targets for the library names
(configure.library.unix, above) and add the library file-names as the
command-targets.
This sounds like it would rerun configure for each change to the
library
sources?
I hope it was clear from above. Tag-files are fine, especially if
you place them in a central directory so you may use them for other
purposes (listing the completed steps in a log-file, for example) but
if they hide the things Make needs to see then the only solution is
to make enough artificial things you might as well have told Make in
the first place.
$(foreach bsubdir,$(BASE_SUBDIRS),$(eval $(call mkrule_one_Library,$
(bsubdir))))
Hard to say without knowing what you plan to generate, but like Simon,
I'm not keen on the idea of generating the make rules. It would
make it
a lot harder for people to understand, I think.
The curious thing is that only stalwarts like you and Simon seem to
work on the build system--everyone else seems to work on source files
only. I could be entirely wrong about this (I apologise to anyone
else who does!). I doubt anyone would complain if the system was
fast and convenient. Please don't construe this as sycophantic: I
have read your papers on Template Haskell and years ago I learned
basic Haskell from Simon M's book; you two could run circles around
me if you played with $(eval ) for even fifteen minutes. $(eval ) is
just meta-programming of another kind, though I haven't seen anyone
use it recursively before. $(call ) is also easy to understand and
terribly convenient for avoiding repetitious commands. If you don't
believe me, at least pity this poor soul who has spent several weeks
trying to learn and work with this build system, and make it better!
Cheers,
Pete
_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc