Re: Guile support in GNU make
Paul Smith <[email protected]>
| Newsgroups | gmane.comp.gnu.make.devel |
|---|---|
| Organization | GNU's Not Unix! |
| Message-ID | <1326572016.3482.144.camel@homebase> |
On Tue, 2011-09-20 at 18:16 -0400, Paul Smith wrote: > Over the last weekend I've been playing with adding (optional of > course) support for Guile as an embedded scripting language into GNU > make. Hi all. I'm ready to commit the Guile embedded scripting support. Boris, I understand and agree with your points about providing a loadable module feature, and I actually have partial code available now to do that. I'll send a note about that today or tomorrow. However, I've decided Guile is going to be provided specifically (although optionally) in addition to any generic loadable module interface. I've attached the section of the manual describing the new function and the default Guile implementation that's embedded into GNU make when Guile is compiled in. I'll commit these changes later today if you want to see the source code. Any comments on this implementation are welcome. Cheers! -- ------------------------------------------------------------------------------- Paul D. Smith <[email protected]> Find some GNU make tips at: http://www.gnu.org http://make.mad-scientist.net "Please remain calm...I may be mad, but I am a professional." --Mad Scientist _______________________________________________ Make-alpha mailing list [email protected] https://lists.gnu.org/mailman/listinfo/make-alpha
guile-doc.txt
(text/plain, 4.7 KB)
8.13 The `guile' Function
=========================
GNU make may be built with support for GNU Guile as an embedded
extension language. You can check the `.FEATURES' variable for the
word `guile' to determine if your version of GNU make provides this
capability.
GNU Guile implements the Scheme language. A review of GNU Guile and
the Scheme language and its features is beyond the scope of this
manual: see the documentation for GNU Guile and Scheme.
If GNU Guile is available as an extension language, there will be one
new `make' function available: `guile'. The `guile' function takes one
argument which is first expanded by `make' in the normal fashion, then
passed to the GNU Guile evaluator function. The result of the
evaluator is converted into a string and used as the expansion of the
`guile' function in the makefile.
8.13.1 Conversion of Guile Results
----------------------------------
When the `guile' function is evaluated, `make' will convert the result
of the function into a string and use it as the result of the
evaluation. The conversion of different Guile types into a string is
as follows:
`#f'
The empty string: in `make' the empty string is considered false.
`#t'
The string `t': in `make' any non-empty string is considered true.
`symbol'
`number'
A symbol or number is converted into the string representation of
that symbol or number.
`character'
A printable character is converted to the same character.
`string'
A string containing only printable characters is converted to the
same string.
`list'
A list is converted recursively according to the above rules. This
implies that any structured list will be flattened (that is, a
result of `'(a b (c d) e)' will be converted to the `make' string
`a b c d e').
`other'
Any other Guile type results in an error. In future versions of
`make', other Guile types may be converted.
As a consequence of these conversion rules you must be careful what
results your Guile forms evaluate to. If there is no natural result
for the script (that is the script exists solely for its side-effects,
not for its result), you should have it return `#f' to avoid syntax
errors in your makefile from result conversions.
8.13.2 Interfaces from Guile to `make'
--------------------------------------
In addition to the `guile' function available in makefiles, there are
three functions exported into GNU Guile by `make', for use in your
Guile scripts.
The `make' program creates a new module, `gnu make', and exports
these functions as public interfaces from that module:
`gmk-expand'
This GNU Guile function takes a single string as an argument. The
string is expanded by `make' using normal expansion rules. The
result of the expansion is converted into a string and provided to
GNU Guile as the result of the function.
`gmk-eval'
This function takes a single string as an argument. The string is
evaluated by `make' as if it were a makefile. This is the same
capability available via the `eval' function (*note Eval
Function::). The result of the `gmk-eval' function is always the
empty string.
`gmk-var'
This function takes a single string as an argument. The string is
interpreted as the name of a `make' variable, which is then
expanded. The result of the expansion is converted into a string
and provided as the result of the function in GNU Guile.
8.13.3 Example Using Guile in `make'
------------------------------------
Here is a very simple example using GNU Guile to manage writing to a
file. This set of Guile code simply opens a file, then allows writing
strings to it (one string per line), then closes it again. Note that
because we cannot store complex values such as Guile ports in `make'
variables, we'll keep the port as a global variable in the Guile
interpreter.
This code defines the Guile functions:
define GUILEIO
;; A simple Guile IO library for GNU make
(define MKPORT #f)
(define (mkopen name mode)
(set! MKPORT (open-file name mode))
#f)
(define (mkwrite s)
(display s MKPORT)
(newline MKPORT)
#f)
(define (mkclose)
(close-port MKPORT)
#f)
endef
# Internalize the Guile IO functions
$(guile $(GUILEIO))
Now you can use these Guile functions to create files. Suppose you
need to operate on a very large list, which cannot fit on the command
line, but the utility you're using accepts the list as input as well:
prog: $(PREREQS)
@$(guile (mkopen "tmp.out" "w")) \
$(foreach X,$^,$(guile (mkwrite "$(X)"))) \
$(guile (mkclose))
$(LINK) < tmp.out
gmk-default.scm
(text/x-scheme, 1.9 KB)
;; Contents of the (gnu make) Guile module
;; Copyright (C) 2011 Free Software Foundation, Inc.
;; This file is part of GNU Make.
;;
;; GNU Make is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 3 of the License, or (at your option)
;; any later version.
;;
;; GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
;; details.
;;
;; You should have received a copy of the GNU General Public License along
;; with this program. If not, see <http://www.gnu.org/licenses/>.
(define (to-string-maybe x)
(cond
;; In GNU make, "false" is the empty string
((or (not x)
(unspecified? x)
(null? x)
(and (string? x) (string-null? x)))
#f)
;; We want something not false... not sure about this
((eq? x #t) "t")
;; Basics
((or (symbol? x) (number? x))
(object->string x))
((char? x)
(string x))
;; Printable string (no special characters)
((and (string? x)
(eq? (string-length (string-delete x char-set:printing)) 0))
x)
;; No idea: fail
(else (error "Unknown object:" x))))
(define (obj-to-str x)
(let ((acc '()))
(define (walk x)
(cond ((pair? x) (walk (car x)) (walk (cdr x)))
((to-string-maybe x) => (lambda (s) (set! acc (cons s acc))))))
(walk x)
(string-join (reverse! acc))))
;; eval (GNU make eval) the input string S
(define (gmk-eval s)
(gmk-expand (format #f "$(eval ~a)" (obj-to-str s))))
;; Return the value of the GNU make variable V
(define (gmk-var v)
(gmk-expand (format #f "$(~a)" (obj-to-str v))))
;; Export the public interfaces
(export gmk-expand gmk-eval gmk-var)