Makefiles etc

Ian Lynagh igloo@earth.li
Sat, 28 Sep 2002 13:38:27 +0100


Hi all,

I've been looking at the fputils build system, and amongst various typos
and pet peeves[0] there are a few more serious things I have noticed and
I also have a few questions. I will refer mostly to names of the final
built Makefiles as that is what it was easiest to follow.




mk/config.mk:

    # Yuckage: for ghc/utils/parallel -- todo: nuke this dependency!!
    BASH                    = /usr/local/bin/bash

If it's going to be there shouldn't the correct location of bash be
detected? [just hardcoded in mk/config.mk.in]




mk/config.mk:

    PRINTER         = lpr

as far as I can see this is not used. Its presence seems very odd to me.



mk/config.mk:

    # Pin a suffix on executables? If so, what (Windows only).
    exeext=
[...]
    #
    # Under Windows, we have to deal with .exe suffixes
    #
    EXE_SUFFIX=

seems to be duplication.




mk/paths.mk:

    # make depend defaults
    #
    # The default set of files for the dependency generators to work on
    # is just their source equivalents.
[...]
    # make TAGS defaults
    #
    # The default set of files for the dependency generators to work on
    # is just their source equivalents.

Is the second comment wrong?




mk/suffix.mk:

    .PRECIOUS: %.hs

If my understanding of the special targets is correct then .SECONDARY is
what is wanted here (and elsewhere). If happy opens foo.hs for writing
and ^C is pressed then a 0 size file will be created, but it make is
rerun then it will have an uptodate timestamp so won't be recreated.
iI am not familiar with happy so it could be this isn't an issue in this
case.

    % cat Makefile

    .SECONDARY: foo
    .PRECIOUS: bar

    foo:
            touch foo
            sleep 10

    bar:
            touch bar
            sleep 10

    % make foo
    touch foo
    sleep 10
    make: *** Deleting file `foo'
    make: *** wait: No child processes.  Stop.
    make: *** Waiting for unfinished jobs....
    make: *** wait: No child processes.  Stop.
    % make bar
    touch bar
    sleep 10
    make: *** wait: No child processes.  Stop.
    make: *** Waiting for unfinished jobs....
    make: *** wait: No child processes.  Stop.
    % ls
    Makefile  bar
    %




mk/suffix.mk:
    ifneq "$(BootingFromHc)" "YES"
    %_hsc.c %_hsc.h %.hs : %.hsc
        $(HSC2HS) $(HSC2HS_OPTS) $<
        @touch $(patsubst %.hsc,%_hsc.c,$<)
    endif

Am I right in thinking that the touch is done because hsc2hs won't
always generate all the files and the rule doesn't want to be triggered
next time make is called if one of them isn't created?





mk/suffix.mk:
%.$(way_)o : %.$(way_)s
    @$(RM) $@
    $(HC) $(GHC_CC_OPTS) -c $< -o $@

Why is the target first deleted?




mk/suffix.mk:
    %.$(way_)o : %.$(way_)s
        @$(RM) $@
        $(AS) $(AS_OPTS) -o $@ $< || ( $(RM) $@ && exit 1 )

I can't remember if GNU make is required for building fptools, but if so
then .DELETE_ON_ERROR provides a much nicer way of doing this across all
rules:

    % cat Makefile

    .DELETE_ON_ERROR:

    foo:
            touch foo
            false

    % make foo
    touch foo
    false
    make: *** [foo] Error 1
    make: *** Deleting file `foo'
    %

While I'm here, you seem to have an ugly mixture of true/false and exit
0/1, including things like "then true; else exit 1" in Makefile.
Personally I prefer true and false, but I'm not hugely fussed.




mk/suffix.mk:
    %.tab.c %.tab.h : %.y
        @$(RM) $*.tab.h $*.tab.c y.tab.c y.tab.h y.output
        $(YACC) $(YACC_OPTS) $<
        $(MV) y.tab.c $*.tab.c
        @chmod 444 $*.tab.c
        $(MV) y.tab.h $*.tab.h
        @chmod 444 $*.tab.h

This of course has potential problems make -j. Also, why are the chmods
hidden?




mk/suffix.mk:
    %.html : %.sgml
        @$(RM) $@
    #   $(PERL) $(COLLATEINDEX) -N -o index.sgml
    #   $(JADE) -t sgml -V html-index -d $(SGMLSTYLESHEET) -c $(DOCBOOK_CATALOG) $<
    #   $(PERL) $(COLLATEINDEX) -N -o index.sgml
        $(SGML2HTML) $(SGML2HTML_OPTS) $<
    # touch the .html file so that it is seen to be built
        @touch $@

What is the touch for here?





mk/suffix.mk:
    % : %.pp
        rm -f $@
        $(CPP) $(CPP_OPTS) -x c $< | $(SED) -e '/^#/d' > $@

Shouldn't this use $(RM)?
There are more of these in Makefile and probably elsewhere, and for
other commands.

I would prefer a $(RMD) over $(RM) -r or rm -rf too.




On, for example, binary-dist-pre:: in Makefile which is something like

    foo:
        @for i in 1 2 3; \
        do \
            echo bar $$i; \
            bar $$i; \
        done'

this seems incredibly ugly, especially given the length of some of the
commands. Perhaps something like this could be used instead?

    foo:
        @sh -cx '\
        for i in 1 2 3; \
        do \
            bar $$i; \
        done'





    touch $(BIN_DIST_TMPDIR)/$(BIN_DIST_NAME)/Makefile.in

in Makefile is unneccesary as various things are about to be appended to
it.





I would write

    $(MV) $(BIN_DIST_TMPDIR)/$(BIN_DIST_NAME)/bin/$(TARGETPLATFORM)/$$i  $(BIN_DIST_TMPDIR)/$(BIN_DIST_NAME)/bin/$(TARGETPLATFORM)/$$i.prl;

(in Makefile) as

    $(MV)
    $(BIN_DIST_TMPDIR)/$(BIN_DIST_NAME)/bin/$(TARGETPLATFORM)/$$i{,.prl};

Admittedly that looks a bit strange if you haven't seen it before, but
it has the advantage of making it clear that the directory is staying
the same.




Makefile:

Given

    binary-pack::
        ( cd $(BIN_DIST_TMPDIR); $(TAR) chzf $(BIN_DIST_NAME).tar.gz $(BIN_DIST_NAME) )

why doesn't

    ifneq "$(way)" ""
    package-way-dist::
        ( cd $(BIN_DIST_TMPDIR); $(FIND) $(BIN_DIST_NAME)/ \( -name "*$(_way).a" -o -name "*.$(way_)hi" \) -print | xargs tar cvf $(BIN_DIST_TMPDIR)/ghc-$(ProjectVersion)-$(way)-$(TARGETPLATFORM).tar )
        gzip $(BIN_DIST_TMPDIR)/ghc-$(ProjectVersion)-$(way)-$(TARGETPLATFORM).tar
    endif

use the z switch to tar too? [and $(TAR) vs tar again]

package-way-dist isn't marked as PHONY either.




Makefile:

    dist-manifest ::
        cd $(SRC_DIST_DIR); $(FIND) . \( -type l -o -type f \) -exec ls -lLG {} \; | sed -e 's/\.\///' > MANIFEST.tmp ; mv MANIFEST.tmp MANIFEST

Why not write directly to MANIFEST?
And errors in early commands will not be noticed by make.



Makefile:

    SRC_DIST_PATHS = $(patsubst %, $(SRC_DIST_NAME)/%, $(SRC_DIST_FILES) $(SRC_DIST_DIRS))

This is just

    SRC_DIST_PATHS = $(addprefix $(SRC_DIST_NAME)/, $(SRC_DIST_FILES) $(SRC_DIST_DIRS))

no?




Thanks
Ian

[0] Reliance on tab stops being every 8 chars for alignment anyone?

_______________________________________________
Cvs-ghc mailing list
Cvs-ghc@haskell.org
http://www.haskell.org/mailman/listinfo/cvs-ghc