makefile turing-complete

¿Los makefiles están completos?



turing-complete (2)

Ahora para una respuesta negativa: GNU hace activamente bloquea algunos mecanismos para crear recursión:

1) Variables expandidas recursivamente

no son recursivas en el sentido de "función recursiva": no se pueden definir en términos de sí mismos:

Actually make detects the infinite loop and reports an error.

(No veo cómo permitirlos podría ser útil en la práctica, por cierto).

2) Encadenamiento de reglas

no puede ser recursivo, tampoco:

No single implicit rule can appear more than once in a chain. (...) This constraint has the added benefit of preventing any infinite loop in the search for an implicit rule chain.

(Perdí bastante tiempo al depurar mis Makefiles, además de todas las otras cosas que dificultan el mantenimiento de los makefiles).

PD para un proyecto reciente. Escribí un parche para GNU make 3.82 que elimina esta limitación con una nueva opción -M (ver discusión ). Funciona bien para mí.

Últimamente en el trabajo, he estado haciendo una traducción de Makefiles a un sistema de compilación alternativo. He visto algunos códigos Make bastante bonitos en algunos lugares usando mapas funcionales, filtros y construcciones foreach. Esto me sorprendió ya que creo que los scripts de compilación deben ser tan declarativos como sea posible.

De todos modos, esto me hizo pensar: es el lenguaje Makefile (digamos que la última versión de GNU es específica) ¿Turing está completo?


Sí, mira esto . Una vez que tienes lambda, todo está cuesta abajo desde allí.

Aquí hay un ejemplo plagiado de Fibonacci

Esto debería ser suficiente para construir una base para una mayor generalidad (tengo que volver al trabajo, o jugaría más).

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))) mul = $(if $(call not,$2),$2,$(call add,$1,$(call mul,$1,$(call dec,$2)))) fibo = $(if $(call lt,$1,..),$1,$(call add,$(call fibo,$(call dec,$1)),$(call fibo,$(call sub,$1,..)))) fact = $(if $(call lt,$1,..),.,$(call mul,$1,$(call fact,$(call dec,$1)))) numeral = $(words $(subst .,. ,$1)) go = $(or $(info $(call numeral,$(call mul,$1,$1)) $(call numeral,$(call fibo,$1)) $(call numeral,$(call fact,$1)) ),$(call go,.$1)) _ := $(call go,)

Esto imprime cuadrados, números de Fibonacci y factoriales. Parece que hay un límite de 16 bits para los tamaños de los números. Gorrón.