Hacker News new | ask | show | jobs
by snprbob86 5862 days ago
Uuugh... XML... how I hate you. Everyone should need to learn Lisp, even if you never ever program it, simply to avoid developing some of these poisonous XML-flavored tools. He mentions Ant specifically. Let me tell you, as an unwilling Microsoft Build expert, XML should be NOWHERE NEAR your build system. He puts down Makefiles, but as someone who wrote a Makefile for the first time after years of Ant and MSBuild, it was like a breath of fresh air. The intentional lack of power is what makes it so great. If anything, Makefiles are too powerful and too close to turing complete.

Here is what a make file should look like:

1) vpath statements for various file extensions

2) Phony targets for logical build units, including "all"

3) Generic rules for mapping .abc to .xyz; these rules should have exactly one line of code which executes an external script/tool

4) A list of edges in the dependency graph

5) A few variables as necessary to eliminate redundant edges

If you put any logic in your Makefiles, you are doing it wrong.

If your builds are slow, add empty dummy files for larger culling by timestamps. If timestamps are insufficient, codify early out logic into tools.

Not having logic in my Makefiles enables parallel execution and strong support for incremental builds. If I were to use Lisp as a build system, I'd create a DSL that had these same properties; forbidding arbitrary logic in my dependency graph. It's about finding the right balance to inject expressiveness without losing desirable properties of the DSL. This is why every developer needs to understand more about programming language design. Anytime you create any type of file format, you are doing it. And anytime you are writing any type of file format, you are reverse engineering it. Understanding the intended separation of logic for Makefiles helps me write better Makefiles.

1 comments

> If anything, Makefiles are too powerful and too close to turing complete.

"Close to"? Not a formal proof of Turing-completeness (and may only work with GNU make, not sure), but...

  [me@host: ~]% cat fibo.mk
  dec = $(patsubst .%,%,$1)

  not = $(if $1,,.)

  lteq = $(if $1,$(if $(findstring $1,$2),.,),.)
  gteq = $(if $2,$(if $(findstring $2,$1),.,),.)
  eq = $(and $(call lteq,$1,$2),$(call gteq,$1,$2))
  lt = $(and $(call lteq,$1,$2),$(call not,$(call gteq,$1,$2)))

  add = $1$2
  sub = $(if $(call not,$2),$1,$(call sub,$(call dec,$1),$(call dec,$2)))

  fibo = $(if $(call lt,$1,..),$1,$(call add,$(call fibo,$(call dec,$1)),$(call fibo,$(call sub,$1,..))))

  numeral = $(words $(subst .,. ,$1))

  go = $(or $(info $(call numeral,$(call fibo,$1))),$(call go,.$1))

  _ := $(call go,)
  [me@host: ~]% make -f fibo.mk
  0
  1
  1
  2
  3
  5
  8
  13
  21
  34
  55
  89
  144
  233
  377
  610
  987
  1597
  ^C
"The language of GNU make is indeed functional, complete with combinators (map and filter), applications and anonymous abstractions. GNU make does support lambda-abstractions."

http://okmij.org/ftp/Computation/#Makefile-functional