Thanks for replying! I know you are swamped. On Jul 13, 2007, at 3:58 PM, Simon Marlow wrote:
Peter Tanski wrote:# $(call one_target,target) define one_target $(1) : @echo "$(1)" endef # for $(word n,text), if n > num words, evaluates to empty # $(call depend_rec,first_target,rest) define depend_rec $$(eval $$(if $$(word 2, $(2)),\ $$(call depend_rec,\ $$(firstword $(2)),$$(wordlist 2, $$(words $(2)), $(2))),\ $$(call one_target,$(2)))) $(1) : $(2) @echo "$(1)" endef $(eval $(call depend_rec,$(firstword $(dirs)),\ $(wordlist 2,$(words $(dirs)),$(dirs))))My biggest concern about this is that it is pretty opaque. And it's not just the syntax: I know that to understand it I have to follow through 2 (or more?) levels of expansion.
It's one of those things that is easier to write than read--the syntax isn't pretty. If you want to see the result, the easiest thing to do is duplicate the block and replace the top-level $(eval ) with $(warning ), then Make outputs the expansion for you.
I'm wary of diving into $(call) and $(eval) territory. Perhaps I shouldn't be; I'm prepared to be convinced, but as it stands I don't understand the above code at all (and I suspect that even if I did understand it, it is still sufficiently complicated that a comment to explain its workings would be much longer than the code itself).
As it is, it actually gets much clearer than the original makefile because each top-level $(eval ), like depend_rec above, contains the whole build for each library, similar to creating a separate makefile for each library (another option but more manual).
At the end of this Make will have created targets for each of the items in the list in reverse order:six : [commands] five : six [commands] ... one : two three four five six [commands]Following this, Make would easily be able to handle building in parallel for libraries/Makefile.Ok, I don't understand how this would allow parallel building. Haven't you just expressed a serial dependency? To allow parallel building you have to tell make about the actual dependencies between libraries (i.e. the build-depends fields from the .cabal file). Even then, the biggest library is still base by far, and that can't be built in parallel with anything else, so the wins are quite small.
For the libraries it is serial but necessarily so in most cases (most others depend on base). My last question to Ian was whether I could make the internals for each library--boot, configure, makefile, build--independent but I don't think that is possible, either, since the Setup step may require that a previous library is available. So now that I think about it maybe I can't make the internals independent. The result would still be a tree that I doubt Make would execute independently:
setup/Setup.base : configure.base : setup/Setup.base GNUmakefile.base : configure.base build.base : GNUMakefile.base setup/Setup.old-locale: [build.base] -- if this depends on build.base, everything must be serial configure.old-locale: setup/Setup.old-locale GNUMakefile.old-locale: configure.old-locale build.old-locale: GNUMakefile.old-locale [build.base] -- if this is where old-locale depends on base then it would be parallel -- only if Make can parallelize branches (which I don't think it can)When I was talking about "parallel", my chief goal was to force Make to play nice with "-j", so you wouldn't have to do little workarounds to avoid build errors. With an explicit dependancy order, as above, Make will not have the same problem it would with a list, since with "-j" saying:
build : $(SUBDIRS)would be executed in parallel and then Make would probably finish building Cabal before base (and then you get link errors, correct?).
Attached is a modified version of $(TOP)/libraries/Makefile. It is just an untested sketch of the idea but it might help clarify things.
Cheers, Pete
Makefile
Description: Binary data
_______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
