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

Reply via email to