examples: a small c program to be build through makefile-c.scm
to-rule-set: rule-candidates -> dfs -> '(#{:rule} ...) -> rule-set dfs: depth first topological sort with automatic leaf insertion out-of-date: replaced by templates.scm rule-trans-set: replaced by to-rule-set
This commit is contained in:
parent
5b462916b1
commit
a8dd2ab60b
|
@ -0,0 +1,59 @@
|
||||||
|
MAKEFILE:
|
||||||
|
=========
|
||||||
|
|
||||||
|
<makefile> ::= '(' + "makefile" + <makerule-clause>* + ')'
|
||||||
|
|
||||||
|
<makerule-clause> ::= <rule-clause>
|
||||||
|
| <md5-clause>
|
||||||
|
| <always-clause>
|
||||||
|
| <once-clause>
|
||||||
|
|
||||||
|
<rule-clause> ::= '(' + <rule-clause-identifier>
|
||||||
|
+ <target-spec>
|
||||||
|
+ <prereq-spec>
|
||||||
|
+ <action-spec> + ')'
|
||||||
|
|
||||||
|
<md5-clause> ::= '(' + <md5-clause-identifier>
|
||||||
|
+ <target-spec>
|
||||||
|
+ <prereq-spec>
|
||||||
|
+ <action-spec> + ')'
|
||||||
|
|
||||||
|
<always-clause> ::= '(' + <always-clause-identifier>
|
||||||
|
+ <target-spec>
|
||||||
|
+ <prereq-spec>
|
||||||
|
+ <action-spec> + ')'
|
||||||
|
|
||||||
|
<once-clause> ::= '(' + <once-clause-identifier>
|
||||||
|
+ <target-spec>
|
||||||
|
+ <prereq-spec>
|
||||||
|
+ <action-spec> + ')'
|
||||||
|
|
||||||
|
<rule-clause-identifier> ::= "rule"
|
||||||
|
| "makefile-rule"
|
||||||
|
| "is-out-of-date?"
|
||||||
|
|
||||||
|
<md5-clause-identifier> ::= "md5"
|
||||||
|
| "rule-md5"
|
||||||
|
| "fp-changed?"
|
||||||
|
|
||||||
|
<always-clause-identifier> ::= "always"
|
||||||
|
| "rule-always"
|
||||||
|
| "phony"
|
||||||
|
| "is-out-of-date!"
|
||||||
|
|
||||||
|
<once-clause-identifier> ::= "once"
|
||||||
|
| "rule-once"
|
||||||
|
|
||||||
|
<target-spec> ::= <target> | <target-list>
|
||||||
|
<target> ::= <filename>
|
||||||
|
<target-list> ::= '(' + <filename>+ + ')'
|
||||||
|
|
||||||
|
<prereq-spec> ::= <prereq> | <prereq-list>
|
||||||
|
<prereq> ::= <filename>
|
||||||
|
<prereq-list> ::= '(' + <filename>* + ')'
|
||||||
|
|
||||||
|
<action-spec> ::= <action> | <action-list>
|
||||||
|
<action> ::= '(' + <thunk>* + ')'
|
||||||
|
<action-list> ::= '(' + <action>+ + ')'
|
||||||
|
|
||||||
|
<filename> ::= '"' + {<dir-separator> + { 'a'-'z''A'-'Z''0'-'9' ... }+ }+ + '"'
|
230
dfs.scm
230
dfs.scm
|
@ -1,100 +1,172 @@
|
||||||
|
(define time 0)
|
||||||
|
|
||||||
(define-enumerated-type color :color
|
(define-enumerated-type color :color
|
||||||
is-color?
|
is-color?
|
||||||
the-color
|
the-colors
|
||||||
color-name
|
color-name
|
||||||
color-index
|
color-index
|
||||||
(white grey black))
|
(white grey black))
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; DFS:
|
||||||
|
;;; ====
|
||||||
|
;;;
|
||||||
|
;;; (make-dfs node-name adjacencies ignored-data) ---> #{:dfs}
|
||||||
|
;;;
|
||||||
|
;;; node-name : "this is a node name"
|
||||||
|
;;; adjacencies : (list "another node name" "no node name")
|
||||||
|
;;; ignored-data : "anything you need in each node, eg. a long list..."
|
||||||
|
;;;
|
||||||
|
;;; (dfs->list node) ---> '(node-name adjacencies ignored-data)
|
||||||
|
;;;
|
||||||
|
;;; node : #{:dfs}
|
||||||
|
;;;
|
||||||
|
;;; (dfs-name node) ---> node-name
|
||||||
|
;;; (dfs-adjacencies node) ---> adjacencies
|
||||||
|
;;; (dfs-color node) ---> #{:color}
|
||||||
|
;;; (dfs-ftime node) ---> finishing-time
|
||||||
|
;;; (dfs-ignored node) ---> ignored-data
|
||||||
|
;;;
|
||||||
(define-record-type :dfs
|
(define-record-type :dfs
|
||||||
(really-make-dfs node adjacencies color predec dtime ftime ignored-data)
|
(really-make-dfs name adjacencies color ftime ignored)
|
||||||
is-dfs?
|
is-dfs?
|
||||||
(node dfs-node)
|
(name dfs-name)
|
||||||
(adjacencies dfs-adjacencies)
|
(adjacencies dfs-adjacencies)
|
||||||
;; color (white by default)
|
;; color (white by default)
|
||||||
(color dfs-color)
|
(color dfs-color)
|
||||||
;; predecessor (is #f by default)
|
|
||||||
(predec dfs-predec)
|
|
||||||
;; discovery-time
|
|
||||||
(dtime dfs-dtime)
|
|
||||||
;; finishing-time
|
;; finishing-time
|
||||||
(ftime dfs-ftime)
|
(ftime dfs-ftime)
|
||||||
;; thie is for all node specific information
|
|
||||||
;; and is ignore by the dfs algorithm
|
|
||||||
;; put in there what you like
|
;; put in there what you like
|
||||||
(ignored-data dfs-ignored-data))
|
(ignored dfs-ignored))
|
||||||
|
|
||||||
(define (make-dfs node adjacencies ignored-data)
|
(define (make-dfs node-name adjacencies ignored-data)
|
||||||
(really-make-dfs node adjacencies (color white) 0 0 #f ignored-data))
|
(really-make-dfs node-name adjacencies (color white) 0 ignored-data))
|
||||||
|
|
||||||
(define (dfs->list dfs)
|
(define (dfs->list dfs-node)
|
||||||
(list (dfs-node dfs) (dfs-adjacencies dfs) (dfs-ignored-data dfs)))
|
(list (dfs-name dfs-node) (dfs-adjacencies dfs-node) (dfs-ignored dfs-node)))
|
||||||
|
|
||||||
(define (dfs-timer ch)
|
(define (dfs-lookup-node node-name dag)
|
||||||
(spawn
|
(find (lambda (candidate)
|
||||||
(lambda ()
|
(string=? (dfs-name candidate) node-name))
|
||||||
(let timer-loop ((current-time 0))
|
dag))
|
||||||
(cml-sync-ch/receive ch)
|
|
||||||
(cml-sync-ch/send ch current-time)
|
|
||||||
(timer-loop (+ current-time 1))))))
|
|
||||||
|
|
||||||
(define (dfs-time ch)
|
;;;
|
||||||
(cml-sync-ch/send ch 'get-time)
|
;;; DEPTH FIRST SEARCH:
|
||||||
(cml-sync-ch/receive ch))
|
;;; ===================
|
||||||
|
;;;
|
||||||
|
;;; (dfs dag) ---> sorted-dag
|
||||||
|
;;; (dfs dag auto-leafs?) ---> sorted-dag
|
||||||
|
;;;
|
||||||
|
;;; where
|
||||||
|
;;;
|
||||||
|
;;; dag : '(#{:dfs} ...)
|
||||||
|
;;; auto-leafs? : #t (by default) or #f
|
||||||
|
;;; sorted-dag : the sorted dag
|
||||||
|
;;;
|
||||||
|
;;; auto-leafs?:
|
||||||
|
;;;
|
||||||
|
;;; if auto-leafs? is enabled then every adjacency which is unresolveable
|
||||||
|
;;; in the set of all node-names is assumed to point to a leaf.
|
||||||
|
;;; this leaf is then created automatically: it consists of the node-name
|
||||||
|
;;; which was given by the initiating adjencency, the empty adjacencies
|
||||||
|
;;; list, and the ignored-data-field set to #f.
|
||||||
|
;;; if auto-leafs? is set to #f then it is an error that an adjacency is
|
||||||
|
;;; unresolveable in the list of all node-names.
|
||||||
|
;;;
|
||||||
|
(define (dfs dag . maybe-arg)
|
||||||
|
(let-optionals maybe-arg ((auto-leafs? #t))
|
||||||
|
(set! time 0)
|
||||||
|
(let ((node-names (map dfs-name dag)))
|
||||||
|
(if (not (null? node-names))
|
||||||
|
;; (sort pred todo-list done-list)
|
||||||
|
(sort (lambda (current position)
|
||||||
|
(< (dfs-ftime current) (dfs-ftime position)))
|
||||||
|
;;
|
||||||
|
;; the result of this should be the dag with the ftimes
|
||||||
|
;;
|
||||||
|
(let for-all-nodes ((node-name (car node-names))
|
||||||
|
(nodes-to-do (cdr node-names))
|
||||||
|
(current-dag dag))
|
||||||
|
(let ((current-node (dfs-lookup-node node-name current-dag)))
|
||||||
|
(cond
|
||||||
|
((eq? (dfs-color current-node) (color white))
|
||||||
|
(let ((new-dag (dfs-visit current-dag
|
||||||
|
current-node auto-leafs?)))
|
||||||
|
(if (not (null? nodes-to-do))
|
||||||
|
(for-all-nodes (car nodes-to-do)
|
||||||
|
(cdr nodes-to-do)
|
||||||
|
new-dag)
|
||||||
|
new-dag)))
|
||||||
|
(else (if (not (null? nodes-to-do))
|
||||||
|
(for-all-nodes (car nodes-to-do)
|
||||||
|
(cdr nodes-to-do)
|
||||||
|
current-dag)
|
||||||
|
current-dag)))))
|
||||||
|
'())
|
||||||
|
node-names))))
|
||||||
|
|
||||||
(define (dfs-lookup-adjs dag adj)
|
(define (dfs-visit dag node auto-leafs?)
|
||||||
(let ((maybe-rc ))
|
;; (dfs-dag-show dag node)
|
||||||
(if maybe-rc maybe-rc
|
(let ((name (dfs-name node))
|
||||||
|
(adjs (dfs-adjacencies node))
|
||||||
|
(ignored (dfs-ignored node)))
|
||||||
|
(let* ((current-node (really-make-dfs name adjs (color grey)
|
||||||
|
(dfs-ftime node) ignored))
|
||||||
|
(current-dag (cons current-node (delete node dag))))
|
||||||
|
(if (not (null? adjs))
|
||||||
|
(let for-all-adjs ((current-adj (car adjs))
|
||||||
|
(todo-adjs (cdr adjs)))
|
||||||
|
(let ((maybe-node (dfs-lookup-node current-adj current-dag)))
|
||||||
|
(if maybe-node
|
||||||
|
(begin
|
||||||
|
(if (eq? (dfs-color maybe-node) (color white))
|
||||||
|
(let ((next-dag (dfs-visit current-dag
|
||||||
|
maybe-node auto-leafs?)))
|
||||||
|
(set! current-dag next-dag))
|
||||||
|
(if (eq? (dfs-color maybe-node) (color grey))
|
||||||
|
(error "dfs-visit: cycle detected; node-name: "
|
||||||
|
(dfs-name node)))))
|
||||||
|
(if auto-leafs?
|
||||||
|
(let ((leaf (really-make-dfs current-adj '()
|
||||||
|
(color white) 0 #f)))
|
||||||
|
(set! current-dag (dfs-visit (cons leaf current-dag)
|
||||||
|
leaf auto-leafs?)))
|
||||||
|
(error "dfs-visit: incomplete dag!"))))
|
||||||
|
(if (not (null? todo-adjs))
|
||||||
|
(for-all-adjs (car todo-adjs) (cdr todo-adjs)))))
|
||||||
|
(set! time (+ time 1))
|
||||||
|
(cons (really-make-dfs name adjs (color black) time ignored)
|
||||||
|
(delete current-node current-dag)))))
|
||||||
|
|
||||||
(define (dfs-visit dag node time-ch)
|
(define (dfs-dag-show dag node)
|
||||||
(set! (dfs-color node) (color grey))
|
(newline) (newline) (newline) (newline)
|
||||||
(set! (dfs-dtime node) (dfs-time time-ch))
|
(display "************************************************************\n")
|
||||||
(for-each (lambda (adj)
|
(display (dfs-name node)) (newline)
|
||||||
(cond
|
(display "************************************************************\n")
|
||||||
((eq? (dfs-color adj) (color white))
|
(let ((dfs-node-show (lambda (node)
|
||||||
(begin
|
(newline)
|
||||||
(set! (dfs-predecessor adj) node)
|
(display "~dfs-name: ")
|
||||||
(dfs-visit adj time-ch)))
|
(display (dfs-name node))
|
||||||
;;
|
(newline)
|
||||||
;; ((eq? (dfs-color adj) (color black))
|
(display "~dfs-adjacencies: ")
|
||||||
;; "already been here")
|
(display (dfs-adjacencies node))
|
||||||
;;
|
(newline)
|
||||||
((eq? (dfs-color adj) (color grey))
|
(display "~dfs-color: ")
|
||||||
(error "dfs-visit: cycle detected!"))))
|
(display (dfs-color node))
|
||||||
;; this should be the list of all adjacency-nodes
|
(newline)
|
||||||
;; this is done by map over all adjacencies
|
(display "~dfs-ftime: ")
|
||||||
;; lookup each adj in dag, check if its node-name is adj
|
(display (dfs-ftime node))
|
||||||
(map (lambda (adj)
|
(newline)
|
||||||
(find (lambda (candidate)
|
(display "~dfs-ignored: ")
|
||||||
(eq? (dfs-node candidate) adj))
|
(display (dfs-ignored node))
|
||||||
dag))
|
(newline))))
|
||||||
(dfs-adjs node)))
|
|
||||||
(set! (dfs-color node) (color black))
|
|
||||||
(set! (dfs-ftime node) (dfs-time time-ch)))
|
|
||||||
|
|
||||||
;;; this is the depth first search algorithm
|
|
||||||
;;; dag is a list of nodes of record-type dfs
|
|
||||||
(define (dfs dag)
|
|
||||||
(let* ((time-ch (cml-sync-ch/make-channel))
|
|
||||||
(start-timer (dfs-timer time-ch)))
|
|
||||||
(if (not (null? dag))
|
(if (not (null? dag))
|
||||||
(begin
|
(let visit-each-node ((current-node (car dag))
|
||||||
(let visit-each-node ((current-node (car dag))
|
(nodes-to-do (cdr dag)))
|
||||||
(nodes-to-do (cdr dag)))
|
(dfs-node-show current-node)
|
||||||
(if (eq? (dfs-color current-node) (color white))
|
(if (not (null? nodes-to-do))
|
||||||
(dfs-visit dag current-node time-ch))
|
(visit-each-node (car nodes-to-do) (cdr nodes-to-do))
|
||||||
(if (not (null? nodes-to-do))
|
(begin
|
||||||
(visit-each-node (car nodes-to-do) (cdr nodes-to-do))))
|
(display "************************************************************\n")
|
||||||
;; now sort field (dfs-ftime node) in descendent order
|
(display "************************************************************\n")
|
||||||
...
|
(newline) (newline) (newline) (newline)))))))
|
||||||
))))
|
|
||||||
|
|
||||||
(define (dfs-sort-insert pred item queue)
|
|
||||||
(cond
|
|
||||||
((null? queue) (cons item))
|
|
||||||
((not (pred item (car queue))) (cons item queue))
|
|
||||||
(else (dfs-sort-insert item (cdr queue)))))
|
|
||||||
|
|
||||||
(define (dfs-sort pred todo done)
|
|
||||||
(if (null? todo)
|
|
||||||
done
|
|
||||||
(dfs-sort pred (cdr todo) (dfs-sort-insert pred (car todo) done))))
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
Starting make:
|
||||||
|
==============
|
||||||
|
|
||||||
|
In XEmacs open a new buffer to edit this makefile-c.scm. Make sure you
|
||||||
|
had no active scheme-buffer. This will have the effect that your
|
||||||
|
current working directory is the one with makefile-c.scm in it. Now
|
||||||
|
open a new scheme-buffer with 'M-x run-scheme'. You should have passed
|
||||||
|
(at least) the following arguments to scsh:
|
||||||
|
|
||||||
|
'scsh -lel cml/load.scm -lel concurrency/load.scm'
|
||||||
|
|
||||||
|
Now load the packages.scm file into package config:
|
||||||
|
|
||||||
|
> ,config ,load ../packages.scm
|
||||||
|
|
||||||
|
Open the structures macros and make in package user:
|
||||||
|
|
||||||
|
> ,open macros make
|
||||||
|
|
||||||
|
Load makefile-c.scm:
|
||||||
|
|
||||||
|
> ,load makefile-c.scm
|
||||||
|
|
||||||
|
Start make:
|
||||||
|
|
||||||
|
> (make rule-set (list "test"))
|
||||||
|
|
||||||
|
This should start a build all, install, and test installation process.
|
||||||
|
By default, the installation directory will be ../../image.
|
||||||
|
|
||||||
|
Have fun.
|
|
@ -0,0 +1,3 @@
|
||||||
|
71537751982895759163390057694999171418 config.h
|
||||||
|
14291919577004468625754235508931697268 mymath.c
|
||||||
|
277010555671960749526965727376092322885 manual.tex
|
|
@ -0,0 +1,3 @@
|
||||||
|
#ifndef MY_DELTA_MAX
|
||||||
|
#define MY_DELTA_MAX 0.00000000000001
|
||||||
|
#endif
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "wildio.h"
|
||||||
|
#include "mymath.h"
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
double magic_number = 0.0;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
void *libwildio;
|
||||||
|
int (*show_a_double_call)(double);
|
||||||
|
double (*checkargs_call)(int,char**);
|
||||||
|
|
||||||
|
void *libmymath;
|
||||||
|
double (*sqrt_call)(double), result;
|
||||||
|
|
||||||
|
dlerror();
|
||||||
|
|
||||||
|
if (libwildio=dlopen("libwildio.so.1",RTLD_LAZY))
|
||||||
|
{
|
||||||
|
checkargs_call = dlsym(libwildio,"checkargs");
|
||||||
|
show_a_double_call = dlsym(libwildio,"show_a_double");
|
||||||
|
|
||||||
|
/* magic_number will be set by checkargs */
|
||||||
|
magic_number = (*checkargs_call)(argc,argv);
|
||||||
|
|
||||||
|
if (libmymath=dlopen("libmymath.so.1",RTLD_LAZY)) {
|
||||||
|
sqrt_call = dlsym(libmymath,"sqrt");
|
||||||
|
magic_number = (*sqrt_call)(magic_number);
|
||||||
|
|
||||||
|
result = (*show_a_double_call)(magic_number);
|
||||||
|
|
||||||
|
dlclose(libmymath);
|
||||||
|
dlclose(libwildio);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* last exit */
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
(define image-dir "../../image")
|
||||||
|
(define prefix (string-append image-dir "/" "usr"))
|
||||||
|
(define my-lib-dir (string-append prefix "/" "lib"))
|
||||||
|
(define my-bin-dir (string-append prefix "/" "bin"))
|
||||||
|
(define my-share-dir (string-append prefix "/" "share"))
|
||||||
|
(define my-doc-dir (string-append my-share-dir "/" "doc"))
|
||||||
|
(define my-install-doc-dir (string-append my-doc-dir "/" "show-sqrt-1.0"))
|
||||||
|
|
||||||
|
(define clean-files
|
||||||
|
(list "wildio.o" "mymath.o"
|
||||||
|
"libwildio.so.1.0" "libmymath.so.1.0"
|
||||||
|
"libwildio.so.1" "libmymath.so.1"
|
||||||
|
"libwildio.so" "libmymath.so"
|
||||||
|
"show-sqrt"
|
||||||
|
"manual.dvi" "manual.pdf" "manual.log" "manual.aux"))
|
||||||
|
|
||||||
|
(define rule-set
|
||||||
|
(makefile
|
||||||
|
;;
|
||||||
|
;; build libmymath.*
|
||||||
|
;;
|
||||||
|
(md5 "mymath.o"
|
||||||
|
("config.h" "mymath.c")
|
||||||
|
(lambda ()
|
||||||
|
(run (gcc -fPIC -c ,"mymath.c"))))
|
||||||
|
(rule "libmymath.so.1.0"
|
||||||
|
("mymath.o")
|
||||||
|
(lambda ()
|
||||||
|
(run (gcc -shared ,"-Wl,-soname,libmymath.so.1"
|
||||||
|
-o ,"libmymath.so.1.0" ,"mymath.o"))))
|
||||||
|
;;
|
||||||
|
;; build wildio.*
|
||||||
|
;;
|
||||||
|
(rule "wildio.o"
|
||||||
|
("wildio.c")
|
||||||
|
(lambda ()
|
||||||
|
(run (gcc -fPIC -c ,"wildio.c"))))
|
||||||
|
(rule "libwildio.so.1.0"
|
||||||
|
("wildio.o")
|
||||||
|
(lambda ()
|
||||||
|
(run (gcc -shared "-Wl,-soname,libwildio.so.1"
|
||||||
|
-o ,"libwildio.so.1.0" ,"wildio.o"))))
|
||||||
|
;;
|
||||||
|
;; build the program
|
||||||
|
;;
|
||||||
|
(rule "show-sqrt"
|
||||||
|
("libmymath.so.1" "libwildio.so.1" "main.c" "wildio.h" "mymath.h")
|
||||||
|
(lambda ()
|
||||||
|
(run (gcc -L ,"." -L ,my-lib-dir -rdynamic
|
||||||
|
-o ,(expand-file-name "show-sqrt" (cwd))
|
||||||
|
,(expand-file-name "main.c" (cwd))
|
||||||
|
,(expand-file-name "libwildio.so.1" (cwd))
|
||||||
|
,(expand-file-name "libmymath.so.1" (cwd)) -ldl))))
|
||||||
|
;;
|
||||||
|
;; install libs
|
||||||
|
;;
|
||||||
|
(rule "libmymath.so.1"
|
||||||
|
("libmymath.so.1.0")
|
||||||
|
(lambda ()
|
||||||
|
(create-symlink "libmymath.so.1.0" "libmymath.so.1")))
|
||||||
|
(rule "libmymath.so"
|
||||||
|
("libmymath.so.1")
|
||||||
|
(lambda ()
|
||||||
|
(create-symlink "libmymath.so.1" "libmymath.so")))
|
||||||
|
(rule "libwildio.so.1"
|
||||||
|
("libwildio.so.1.0")
|
||||||
|
(lambda ()
|
||||||
|
(create-symlink "libwildio.so.1.0" "libwildio.so.1")))
|
||||||
|
(rule "libwildio.so"
|
||||||
|
("libwildio.so.1")
|
||||||
|
(lambda ()
|
||||||
|
(create-symlink "libwildio.so.1" "libwildio.so")))
|
||||||
|
(rule (string-append my-lib-dir "/" "libmymath.so.1")
|
||||||
|
((string-append my-lib-dir "/" "libmymath.so.1.0"))
|
||||||
|
(lambda ()
|
||||||
|
(with-cwd my-lib-dir
|
||||||
|
(create-symlink "libmymath.so.1.0" "libmymath.so.1"))))
|
||||||
|
(rule (string-append my-lib-dir "/" "libmymath.so")
|
||||||
|
((string-append my-lib-dir "/" "libmymath.so.1"))
|
||||||
|
(lambda ()
|
||||||
|
(with-cwd my-lib-dir
|
||||||
|
(create-symlink "libmymath.so.1" "libmymath.so"))))
|
||||||
|
(rule (string-append my-lib-dir "/" "libwildio.so.1")
|
||||||
|
((string-append my-lib-dir "/" "libwildio.so.1.0"))
|
||||||
|
(lambda ()
|
||||||
|
(with-cwd my-lib-dir
|
||||||
|
(create-symlink "libwildio.so.1.0" "libwildio.so.1"))))
|
||||||
|
(rule (string-append my-lib-dir "/" "libwildio.so")
|
||||||
|
((string-append my-lib-dir "/" "libwildio.so.1"))
|
||||||
|
(lambda ()
|
||||||
|
(with-cwd my-lib-dir
|
||||||
|
(create-symlink "libwildio.so.1" "libwildio.so"))))
|
||||||
|
(rule (string-append my-lib-dir "/" "libwildio.so.1.0")
|
||||||
|
(my-lib-dir "libwildio.so.1.0")
|
||||||
|
(lambda ()
|
||||||
|
(run (cp ,"libwildio.so.1.0"
|
||||||
|
,(string-append my-lib-dir "/" "libwildio.so.1.0")))))
|
||||||
|
(rule (string-append my-lib-dir "/" "libmymath.so.1.0")
|
||||||
|
(my-lib-dir "libmymath.so.1.0")
|
||||||
|
(lambda ()
|
||||||
|
(run (cp ,"libmymath.so.1.0"
|
||||||
|
,(string-append my-lib-dir "/" "libmymath.so.1.0")))))
|
||||||
|
;;
|
||||||
|
;; install the program
|
||||||
|
;;
|
||||||
|
(rule (string-append my-bin-dir "/" "show-sqrt")
|
||||||
|
(my-bin-dir "show-sqrt")
|
||||||
|
(lambda ()
|
||||||
|
(run (cp ,"show-sqrt"
|
||||||
|
,(string-append my-bin-dir "/" "show-sqrt")))))
|
||||||
|
;;
|
||||||
|
;; build the manual
|
||||||
|
;;
|
||||||
|
(md5 "manual.dvi"
|
||||||
|
("manual.tex")
|
||||||
|
(lambda ()
|
||||||
|
(run (latex ,"manual.tex"))))
|
||||||
|
(rule "manual.pdf"
|
||||||
|
("manual.dvi")
|
||||||
|
(lambda ()
|
||||||
|
(run (dvipdfm -o ,"manual.pdf" ,"manual.dvi"))))
|
||||||
|
;;
|
||||||
|
;; install the manual
|
||||||
|
;;
|
||||||
|
(rule (string-append my-install-doc-dir "/" "manual.pdf")
|
||||||
|
(my-install-doc-dir "manual.pdf")
|
||||||
|
(lambda ()
|
||||||
|
(run (cp "manual.pdf"
|
||||||
|
,(string-append my-install-doc-dir "/" "manual.pdf")))))
|
||||||
|
;;
|
||||||
|
;; install all
|
||||||
|
;;
|
||||||
|
(rule "install"
|
||||||
|
((string-append my-lib-dir "/" "libmymath.so.1.0")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so.1.0")
|
||||||
|
(string-append my-lib-dir "/" "libmymath.so.1")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so.1")
|
||||||
|
(string-append my-lib-dir "/" "libmymath.so")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so")
|
||||||
|
(string-append my-bin-dir "/" "show-sqrt")
|
||||||
|
(string-append my-install-doc-dir "/" "manual.pdf"))
|
||||||
|
(lambda ()
|
||||||
|
(display "install done.\n")))
|
||||||
|
;;
|
||||||
|
;; create checksums.md5
|
||||||
|
;;
|
||||||
|
(once "checksums.md5"
|
||||||
|
("manual.tex" "main.c" "mymath.c"
|
||||||
|
"mymath.h" "wildio.c" "wildio.h" "config.h")
|
||||||
|
(lambda ()
|
||||||
|
(let ((outport (open-output-file (expand-file-name "checksums.md5"
|
||||||
|
(cwd)))))
|
||||||
|
(with-current-output-port outport (display ""))
|
||||||
|
(close-output-port outport))))
|
||||||
|
(rule "config.h"
|
||||||
|
()
|
||||||
|
(lambda ()
|
||||||
|
(let ((outport (open-output-file
|
||||||
|
(expand-file-name "config.h" (cwd)))))
|
||||||
|
(with-current-output-port
|
||||||
|
outport
|
||||||
|
(display "#ifndef MY_DELTA_MAX\n")
|
||||||
|
(display "#define MY_DELTA_MAX 0.000000001\n")
|
||||||
|
(display "#endif\n")
|
||||||
|
(close-output-port outport)))))
|
||||||
|
;;
|
||||||
|
;; clean rules
|
||||||
|
;;
|
||||||
|
(always "clean"
|
||||||
|
()
|
||||||
|
(lambda ()
|
||||||
|
(for-each (lambda (f)
|
||||||
|
(delete-filesys-object (expand-file-name f (cwd))))
|
||||||
|
clean-files)))
|
||||||
|
;;
|
||||||
|
;; clean rules
|
||||||
|
;;
|
||||||
|
(always "mrproper"
|
||||||
|
("clean")
|
||||||
|
(lambda ()
|
||||||
|
(for-each (lambda (f)
|
||||||
|
(delete-filesys-object (expand-file-name f (cwd))))
|
||||||
|
(list "checksums.md5"))))
|
||||||
|
;;
|
||||||
|
;; uninstall all
|
||||||
|
;;
|
||||||
|
(always "uninstall"
|
||||||
|
()
|
||||||
|
(lambda ()
|
||||||
|
(display "uninstall: \n")
|
||||||
|
(for-each (lambda (f)
|
||||||
|
(delete-filesys-object f))
|
||||||
|
(list (string-append my-lib-dir "/" "libmymath.so.1.0")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so.1.0")
|
||||||
|
(string-append my-lib-dir "/" "libmymath.so.1")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so.1")
|
||||||
|
(string-append my-lib-dir "/" "libmymath.so")
|
||||||
|
(string-append my-lib-dir "/" "libwildio.so")
|
||||||
|
(string-append my-bin-dir "/" "show-sqrt")
|
||||||
|
(string-append my-install-doc-dir "/" "manual.pdf")
|
||||||
|
my-install-doc-dir
|
||||||
|
my-doc-dir
|
||||||
|
my-share-dir
|
||||||
|
my-lib-dir
|
||||||
|
my-bin-dir
|
||||||
|
prefix
|
||||||
|
image-dir))
|
||||||
|
(display "uninstall done.\n")))
|
||||||
|
;;
|
||||||
|
;; install dirs
|
||||||
|
;;
|
||||||
|
(once image-dir
|
||||||
|
()
|
||||||
|
(lambda ()
|
||||||
|
(create-directory image-dir)))
|
||||||
|
(once prefix
|
||||||
|
(image-dir)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory prefix)))
|
||||||
|
(once my-lib-dir
|
||||||
|
(prefix)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory my-lib-dir)))
|
||||||
|
(once my-bin-dir
|
||||||
|
(prefix)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory my-bin-dir)))
|
||||||
|
(once my-share-dir
|
||||||
|
(prefix)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory my-share-dir)))
|
||||||
|
(once my-doc-dir
|
||||||
|
(my-share-dir)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory my-doc-dir)))
|
||||||
|
(once my-install-doc-dir
|
||||||
|
(my-doc-dir)
|
||||||
|
(lambda ()
|
||||||
|
(create-directory my-install-doc-dir)))
|
||||||
|
;;
|
||||||
|
;; a small test
|
||||||
|
;;
|
||||||
|
(always "test"
|
||||||
|
("install")
|
||||||
|
(lambda ()
|
||||||
|
(let ((proggy (expand-file-name "show-sqrt" my-bin-dir)))
|
||||||
|
(display "testing ") (display proggy) (newline)
|
||||||
|
(setenv "LD_LIBRARY_PATH" my-lib-dir)
|
||||||
|
(display "# sqrt 2.0:\n")
|
||||||
|
(run (,proggy ,"2.0"))
|
||||||
|
(display "# sqrt 5.0:\n")
|
||||||
|
(run (,proggy ,"5.0"))
|
||||||
|
(display "ok.\n"))))))
|
|
@ -0,0 +1,19 @@
|
||||||
|
\documentclass[a4paper]{report}
|
||||||
|
\usepackage[dvipdfm,hyperindex,hypertex,
|
||||||
|
pdftitle={show-sqrt manual, release 1.0},
|
||||||
|
pdfauthor={Johannes Brügmann}
|
||||||
|
colorlinks=true,linkcolor=blue,pagecolor=blue,urlcolor=blue,
|
||||||
|
pdfstartview=FitW,pdfview=FitW]{hyperref}
|
||||||
|
\usepackage{charter}
|
||||||
|
\author{Real A. Name}
|
||||||
|
\title{show-sqrt rel. 1.0 manual}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
This is the show-sqrt release 1.0 manual.
|
||||||
|
|
||||||
|
show-sqrt comes with a single feature: It calculates the square root
|
||||||
|
of a passed as an argument given positive double value and prints the
|
||||||
|
result on screen (stdout).
|
||||||
|
|
||||||
|
Have fun.
|
||||||
|
\end{document}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
double positive (double x) {
|
||||||
|
|
||||||
|
if (x > 0.0)
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
return 0.0 - x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double sqrt (double a) {
|
||||||
|
|
||||||
|
double x_old = 1.0, x_new = 0.5;
|
||||||
|
|
||||||
|
if (a > 0.0) {
|
||||||
|
do {
|
||||||
|
|
||||||
|
x_old = x_new;
|
||||||
|
x_new = ((a / x_old) + x_old) / 2.0;
|
||||||
|
|
||||||
|
} while (positive(x_old - x_new) > MY_DELTA_MAX);
|
||||||
|
|
||||||
|
return x_new;
|
||||||
|
|
||||||
|
} else exit(1);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
double sqrt (double a);
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int show_a_double (double x) {
|
||||||
|
|
||||||
|
printf(">> double: %09.15f\n", x);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage(char *progname) {
|
||||||
|
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
printf("usage: %s <double-value>\n", progname);
|
||||||
|
exit(ENOTSUP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkargs(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
double darg = 0.0;
|
||||||
|
|
||||||
|
if (argc != 2) usage((char *const) argv[0]);
|
||||||
|
else darg = atof(argv[1]);
|
||||||
|
|
||||||
|
return darg;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
int show_a_double (double x);
|
||||||
|
int checkargs(int argc, char *argv[]);
|
243
macros.scm
243
macros.scm
|
@ -1,132 +1,157 @@
|
||||||
;;; TODO:
|
;;; MAKEFILE:
|
||||||
;;;
|
;;; =========
|
||||||
;;; macros -> functions, eg.
|
|
||||||
;;;
|
|
||||||
;;; (define make-is-out-of-date!
|
|
||||||
;;; (lambda (t . p)
|
|
||||||
;;; (lambda args (cons #t (last args)))))
|
|
||||||
|
|
||||||
(define-syntax make
|
|
||||||
(syntax-rules ()
|
|
||||||
((make ?rule-trans-set (?target-fname0 ...) ?init-state)
|
|
||||||
;;
|
|
||||||
;; ?rule-trans-set or ?target-fname0 could be an expr: eval only once
|
|
||||||
;;
|
|
||||||
(let ((rule-trans-set (known-rules-update ?rule-trans-set)))
|
|
||||||
(let* ((target-fname0 ?target-fname0)
|
|
||||||
(target-rule (known-rules-get rule-trans-set target-fname0)))
|
|
||||||
(if (not (null? (rule-trans-set-rule-candidates rule-trans-set)))
|
|
||||||
(display "rule-candidates not empty.\n"))
|
|
||||||
(if target-rule
|
|
||||||
(rule-make target-rule
|
|
||||||
?init-state
|
|
||||||
(rule-trans-set-rule-set rule-trans-set))
|
|
||||||
(error "target-rule not found in rule-set.")))
|
|
||||||
...))
|
|
||||||
((_ )
|
|
||||||
(error "usage: (make '#{:rule-trans-set} (target0 ...) init-state)\n"))))
|
|
||||||
|
|
||||||
;;; (define-syntax makefile
|
;;; (define-syntax makefile
|
||||||
;;; (syntax-rules ()
|
;;; (syntax-rules ()
|
||||||
;;; ((makefile ?rule0 ...)
|
;;; ((makefile ?rule0 ...)
|
||||||
;;; (let ((rule-trans-set (make-empty-rule-trans-set)))
|
;;; (let ((rule-candidates '()))
|
||||||
;;; (let* ((rule-trans-set (?rule0 rule-trans-set))
|
;;; (let* ((rule-candidates (?rule0 rule-candidates))
|
||||||
;;; ...)
|
;;; ...)
|
||||||
;;; rule-trans-set)))))
|
;;; rule-candidates)))))
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; <makefile> ::= '(' + "makefile" + <makerule-clause>* + ')'
|
||||||
|
;;; <makerule-clause> ::= <rule-clause>
|
||||||
|
;;; | <md5-clause>
|
||||||
|
;;; | <always-clause>
|
||||||
|
;;; | <once-clause>
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
(define-syntax makefile
|
(define-syntax makefile
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((makefile) (make-empty-rule-trans-set))
|
((makefile) (list))
|
||||||
((makefile ?rule0 ?rule1 ...)
|
((makefile ?rule0 ?rule1 ...) (?rule0 (makefile ?rule1 ...)))))
|
||||||
(?rule0 (makefile ?rule1 ...)))))
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; <rule-clause>
|
||||||
|
;;;
|
||||||
|
;;; to achieve consistency only rule will use the rule-tmpvars
|
||||||
|
;;; macro directly and all other macros use this clause
|
||||||
|
;;;
|
||||||
(define-syntax makefile-rule
|
(define-syntax makefile-rule
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((makefile-rule ?target (?prereq0 ...) ?thunk)
|
((makefile-rule ?target ?prereqs ?thunk) (rule ?target ?prereqs ?thunk))))
|
||||||
(makefile-rule-tmpvars () ?target (?prereq0 ...) ?thunk))))
|
|
||||||
|
|
||||||
(define-syntax makefile-rule-tmpvars
|
(define-syntax is-out-of-date?
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((makefile-rule-tmpvars (tmp1 ...) ?target () ?thunk)
|
((is-out-of-date? ?target ?prereqs ?thunk) (rule ?target ?prereqs ?thunk))))
|
||||||
;;
|
|
||||||
;; ?target could be an expr: eval only once
|
(define-syntax rule
|
||||||
;;
|
(syntax-rules ()
|
||||||
(let ((target ?target))
|
((rule ?target (?prereq0 ...) ?thunk)
|
||||||
(lambda (rule-trans-set)
|
(rule-tmpvars () ?target (?prereq0 ...) ?thunk))))
|
||||||
(rule-trans-set-add rule-trans-set
|
|
||||||
target
|
(define-syntax rule-tmpvars
|
||||||
(list tmp1 ...)
|
(syntax-rules ()
|
||||||
(make-is-out-of-date? target tmp1 ...)
|
((rule-tmpvars (tmp1 ...) ?target () ?thunk)
|
||||||
(lambda ?args (?thunk))))))
|
(let ((target ?target)
|
||||||
;;
|
(prereqs (list tmp1 ...)))
|
||||||
;; recursively construct temporary, hygienic variables
|
(lambda (rule-candidates)
|
||||||
;;
|
(cons (list target
|
||||||
((makefile-rule-tmpvars (tmp1 ...) ?target (?prereq0 ?prereq1 ...) ?thunk)
|
prereqs
|
||||||
|
(make-is-out-of-date? target tmp1 ...)
|
||||||
|
(make-rule-build-func target prereqs ?thunk))
|
||||||
|
rule-candidates))))
|
||||||
|
((rule-tmpvars (tmp1 ...) ?target (?prereq0 ?prereq1 ...) ?thunk)
|
||||||
(let ((tmp2 ?prereq0))
|
(let ((tmp2 ?prereq0))
|
||||||
(makefile-rule-tmpvars (tmp1 ... tmp2) ?target (?prereq1 ...) ?thunk)))))
|
(rule-tmpvars (tmp1 ... tmp2) ?target (?prereq1 ...) ?thunk)))))
|
||||||
|
|
||||||
(define-syntax makefile-rule-md5
|
;;;
|
||||||
|
;;; <md5-clause>
|
||||||
|
;;;
|
||||||
|
;;; to achieve consistency only rule-md5 will use the rule-md5-tmpvars
|
||||||
|
;;; macro directly and all other macros use this clause
|
||||||
|
;;;
|
||||||
|
(define-syntax md5
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((makefile-rule-md5 ?fingerprint ?target (?prereq0 ...) ?thunk)
|
((md5 ?target ?prereqs ?thunk) (rule-md5 ?target ?prereqs ?thunk))))
|
||||||
(makefile-rule-md5-tmpvars () ?fingerprint ?target (?prereq0 ...) ?thunk))))
|
|
||||||
|
|
||||||
(define-syntax makefile-rule-md5-tmpvars
|
(define-syntax rule-md5
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((makefile-rule-md5-tmpvars (tmp1 ...) ?fingerprint ?target () ?thunk)
|
((rule-md5 ?target (?prereq0 ...) ?thunk)
|
||||||
;;
|
(rule-md5-tmpvars () ?target (?prereq0 ...) ?thunk))))
|
||||||
;; ?target could be an expr: eval only once
|
|
||||||
;;
|
(define-syntax rule-md5-tmpvars
|
||||||
(let ((target ?target))
|
(syntax-rules ()
|
||||||
(lambda (rule-trans-set)
|
((rule-md5-tmpvars (tmp1 ...) ?target () ?thunk)
|
||||||
(rule-trans-set-add rule-trans-set
|
(let ((target ?target)
|
||||||
target
|
(prereqs (list tmp1 ...)))
|
||||||
(list tmp1 ...)
|
(lambda (rule-candidates)
|
||||||
(make-has-md5-digest=? ?fingerprint
|
(cons (list target
|
||||||
target
|
prereqs
|
||||||
tmp1 ...)
|
(make-md5-sum-changed? target tmp1 ...)
|
||||||
(lambda ?args (?thunk))))))
|
(make-md5-build-func target prereqs ?thunk))
|
||||||
;;
|
rule-candidates))))
|
||||||
;; recursively construct temporary, hygienic variables
|
((rule-md5-tmpvars (tmp1 ...) ?target (?prereq0 ?prereq1 ...) ?thunk)
|
||||||
;;
|
|
||||||
((makefile-rule-md5-tmpvars (tmp1 ...) ?fingerprint ?target
|
|
||||||
(?prereq0 ?prereq1 ...) ?thunk)
|
|
||||||
(let ((tmp2 ?prereq0))
|
(let ((tmp2 ?prereq0))
|
||||||
(makefile-rule-md5-tmpvars (tmp1 ... tmp2) ?fingerprint
|
(rule-md5-tmpvars (tmp1 ... tmp2) ?target (?prereq1 ...) ?thunk)))))
|
||||||
?target (?prereq1 ...) ?thunk)))))
|
|
||||||
|
|
||||||
(define-syntax make-is-out-of-date?
|
;;;
|
||||||
(syntax-rules ()
|
;;; <always-clause>
|
||||||
((make-is-out-of-date? ?target)
|
;;;
|
||||||
(lambda ?args
|
;;; to achieve consistency only rule-always will use the rule-always-tmpvars
|
||||||
(cons (file-not-exists? ?target) ?args)))
|
;;; macro directly and all other macros use this clause
|
||||||
((make-is-out-of-date? ?target ?prereq0 ...)
|
;;;
|
||||||
(lambda ?args
|
(define-syntax phony
|
||||||
(cons (and (file-exists? ?prereq0) ...
|
(syntax-rules ()
|
||||||
(or (file-not-exists? ?target)
|
((phony ?target ?prereqs ?thunk) (rule-always ?target ?prereqs ?thunk))))
|
||||||
(> (file-last-mod ?prereq0)
|
|
||||||
(file-last-mod ?target)))
|
|
||||||
...)
|
|
||||||
(last ?args))))))
|
|
||||||
|
|
||||||
(define-syntax make-is-out-of-date!
|
(define-syntax always
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((make-is-out-of-date? ?target ?prereq0 ...)
|
((always ?target ?prereqs ?thunk) (rule-always ?target ?prereqs ?thunk))))
|
||||||
(lambda ?args
|
|
||||||
(cons #t (last ?args))))))
|
|
||||||
|
|
||||||
(define-syntax make-has-md5-digest=?
|
(define-syntax is-out-of-date!
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((make-has-md5-digest=? ?fingerprint ?target)
|
((is-out-of-date! ?target ?prereqs ?thunk)
|
||||||
(lambda ?args
|
(rule-always ?target ?prereqs ?thunk))))
|
||||||
(cons (or (file-not-exists? ?target)
|
|
||||||
(=? (md5-digest-for-port (open-input-file ?target))
|
|
||||||
?fingerprint))
|
|
||||||
?args)))
|
|
||||||
((make-has-md5-digest=? ?fingerprint ?target ?prereq0 ...)
|
|
||||||
(lambda ?args
|
|
||||||
(cons (or (file-not-exists? ?target)
|
|
||||||
(=? (md5-digest->number (md5-digest-for-port
|
|
||||||
(open-input-file ?target)))
|
|
||||||
(md5-digest->number ?fingerprint)))
|
|
||||||
(last ?args))))))
|
|
||||||
|
|
||||||
|
(define-syntax rule-always
|
||||||
|
(syntax-rules ()
|
||||||
|
((rule-always ?target (?prereq0 ...) ?thunk)
|
||||||
|
(rule-always-tmpvars () ?target (?prereq0 ...) ?thunk))))
|
||||||
|
|
||||||
|
(define-syntax rule-always-tmpvars
|
||||||
|
(syntax-rules ()
|
||||||
|
((rule-always-tmpvars (tmp1 ...) ?target () ?thunk)
|
||||||
|
(let ((target ?target)
|
||||||
|
(prereqs (list tmp1 ...)))
|
||||||
|
(lambda (rule-candidates)
|
||||||
|
(cons (list target
|
||||||
|
prereqs
|
||||||
|
(make-is-out-of-date! target tmp1 ...)
|
||||||
|
(make-always-build-func target prereqs ?thunk))
|
||||||
|
rule-candidates))))
|
||||||
|
((rule-always-tmpvars (tmp1 ...) ?target (?prereq0 ?prereq1 ...) ?thunk)
|
||||||
|
(let ((tmp2 ?prereq0))
|
||||||
|
(rule-always-tmpvars (tmp1 ... tmp2) ?target (?prereq1 ...) ?thunk)))))
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; <once-clause>
|
||||||
|
;;;
|
||||||
|
;;; to achieve consistency only rule-once will use the rule-once-tmpvars
|
||||||
|
;;; macro directly and all other macros use this clause
|
||||||
|
;;;
|
||||||
|
(define-syntax once
|
||||||
|
(syntax-rules ()
|
||||||
|
((once ?target ?prereqs ?thunk)
|
||||||
|
(rule-once ?target ?prereqs ?thunk))))
|
||||||
|
|
||||||
|
(define-syntax rule-once
|
||||||
|
(syntax-rules ()
|
||||||
|
((rule-once ?target (?prereq0 ...) ?thunk)
|
||||||
|
(rule-once-tmpvars () ?target (?prereq0 ...) ?thunk))))
|
||||||
|
|
||||||
|
(define-syntax rule-once-tmpvars
|
||||||
|
(syntax-rules ()
|
||||||
|
((rule-once-tmpvars (tmp1 ...) ?target () ?thunk)
|
||||||
|
(let ((target ?target)
|
||||||
|
(prereqs (list tmp1 ...)))
|
||||||
|
(lambda (rule-candidates)
|
||||||
|
(cons (list target
|
||||||
|
prereqs
|
||||||
|
(make-once target tmp1 ...)
|
||||||
|
(make-once-build-func target prereqs ?thunk))
|
||||||
|
rule-candidates))))
|
||||||
|
((rule-once-tmpvars (tmp1 ...) ?target (?prereq0 ?prereq1 ...) ?thunk)
|
||||||
|
(let ((tmp2 ?prereq0))
|
||||||
|
(rule-once-tmpvars (tmp1 ... tmp2) ?target (?prereq1 ...) ?thunk)))))
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
(define-record-type :rule-set
|
(define-record-type :rule-set
|
||||||
(make-rule-set rules)
|
(make-rule-set rules)
|
||||||
is-rule-set?
|
is-rule-set?
|
||||||
(rules rule-set-rules))
|
(rules rule-set-rules))
|
||||||
|
|
||||||
(define (make-empty-rule-set)
|
(define (make-empty-rule-set)
|
||||||
(make-rule-set '()))
|
(make-rule-set '()))
|
||||||
|
@ -40,10 +40,12 @@
|
||||||
(error "make-rule: rule already exists."))))
|
(error "make-rule: rule already exists."))))
|
||||||
|
|
||||||
(define (rule-set-get-listen-ch rule rule-set)
|
(define (rule-set-get-listen-ch rule rule-set)
|
||||||
(let ((?thing (assq rule (rule-set-rules rule-set))))
|
(let ((maybe-rule (assoc rule (rule-set-rules rule-set))))
|
||||||
(if (and ?thing (pair? ?thing) (is-collect&reply-channel? (cdr ?thing)))
|
(if (and maybe-rule
|
||||||
(cdr ?thing)
|
(pair? maybe-rule)
|
||||||
(error "Rule not found in rule-set."))))
|
(is-collect&reply-channel? (cdr maybe-rule)))
|
||||||
|
(cdr maybe-rule)
|
||||||
|
(error "rule not found in rule-set."))))
|
||||||
|
|
||||||
;;;
|
;;;
|
||||||
;;; RULE-RESULT
|
;;; RULE-RESULT
|
||||||
|
@ -54,7 +56,7 @@
|
||||||
;;; (rule-result-build-func rule-result) --->
|
;;; (rule-result-build-func rule-result) --->
|
||||||
;;; (build-func-result . end-state) oder #f
|
;;; (build-func-result . end-state) oder #f
|
||||||
;;;
|
;;;
|
||||||
;;; (rule-make rule init-state rule-set) ---> rule-result
|
;;; (rule-make rule init-state rule-set) ---> rule-result
|
||||||
;;;
|
;;;
|
||||||
(define-record-type :rule-result
|
(define-record-type :rule-result
|
||||||
(make-rule-result wants-build?-result build-func-result)
|
(make-rule-result wants-build?-result build-func-result)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
(define (make rcs targets . maybe-arg)
|
||||||
|
(let-optionals maybe-arg ((init-state (list)))
|
||||||
|
(let* ((rules (rcs->rules rcs))
|
||||||
|
(rule-set (rules->rule-set rules))
|
||||||
|
(target-rules (map (lambda (t) (lookup-rule t rules))
|
||||||
|
targets)))
|
||||||
|
(map rule-make
|
||||||
|
target-rules (circular-list init-state)
|
||||||
|
(circular-list rule-set)))))
|
|
@ -0,0 +1,9 @@
|
||||||
|
(define (insert pred item ls)
|
||||||
|
(if (or (null? ls) (pred item (car ls)))
|
||||||
|
(cons item ls)
|
||||||
|
(cons (car ls) (insert pred item (cdr ls)))))
|
||||||
|
|
||||||
|
(define (sort pred todo done)
|
||||||
|
(if (null? todo)
|
||||||
|
done
|
||||||
|
(sort pred (cdr todo) (insert pred (car todo) done))))
|
110
packages.scm
110
packages.scm
|
@ -136,6 +136,8 @@
|
||||||
is-rule-set?
|
is-rule-set?
|
||||||
make-rule-result
|
make-rule-result
|
||||||
is-rule-result?
|
is-rule-result?
|
||||||
|
rule-result-wants-build?
|
||||||
|
rule-result-build-func
|
||||||
rule-make))
|
rule-make))
|
||||||
|
|
||||||
(define-structure make-rule make-rule-interface
|
(define-structure make-rule make-rule-interface
|
||||||
|
@ -159,6 +161,8 @@
|
||||||
is-rule-set?
|
is-rule-set?
|
||||||
make-rule-result
|
make-rule-result
|
||||||
is-rule-result?
|
is-rule-result?
|
||||||
|
rule-result-wants-build?
|
||||||
|
rule-result-build-func
|
||||||
rule-make))
|
rule-make))
|
||||||
|
|
||||||
(define-structure make-rule-no-cml make-rule-no-cml-interface
|
(define-structure make-rule-no-cml make-rule-no-cml-interface
|
||||||
|
@ -169,35 +173,91 @@
|
||||||
srfi-9)
|
srfi-9)
|
||||||
(files make-rule-no-cml))
|
(files make-rule-no-cml))
|
||||||
|
|
||||||
(define-interface rule-trans-set-interface
|
|
||||||
(export make-rule-trans-set
|
|
||||||
is-rule-trans-set?
|
|
||||||
make-empty-rule-trans-set
|
|
||||||
make-rule-trans-set
|
|
||||||
rule-trans-set-rule-candidates
|
|
||||||
rule-trans-set-known-rules
|
|
||||||
rule-trans-set-rule-set
|
|
||||||
rule-trans-set-add
|
|
||||||
rule-candidate-get
|
|
||||||
known-rules-get))
|
|
||||||
|
|
||||||
(define-structure rule-trans-set rule-trans-set-interface
|
|
||||||
(open scheme-with-scsh
|
|
||||||
srfi-1
|
|
||||||
srfi-9
|
|
||||||
make-rule)
|
|
||||||
(files rule-trans-set))
|
|
||||||
|
|
||||||
(define-interface macros-interface
|
(define-interface macros-interface
|
||||||
(export (make :syntax)
|
(export (makefile :syntax)
|
||||||
(makefile :syntax)
|
(rule :syntax)
|
||||||
(makefile-rule :syntax)
|
(makefile-rule :syntax)
|
||||||
(make-is-out-of-date? :syntax)))
|
(is-out-of-date? :syntax)
|
||||||
|
(md5 :syntax)
|
||||||
|
(rule-md5 :syntax)
|
||||||
|
(phony :syntax)
|
||||||
|
(always :syntax)
|
||||||
|
(is-out-of-date! :syntax)
|
||||||
|
(once :syntax)
|
||||||
|
(rule-once :syntax)))
|
||||||
|
|
||||||
(define-structure macros macros-interface
|
(define-structure macros macros-interface
|
||||||
(open scheme-with-scsh
|
(open scheme-with-scsh
|
||||||
srfi-1
|
srfi-1
|
||||||
make-rule
|
to-rule-set
|
||||||
rule-trans-set)
|
dfs
|
||||||
|
templates
|
||||||
|
make-rule)
|
||||||
(files macros))
|
(files macros))
|
||||||
|
|
||||||
|
(define-interface to-rule-set-interface
|
||||||
|
(export lookup-rc
|
||||||
|
lookup-fname
|
||||||
|
lookup-rule
|
||||||
|
rcs->dag
|
||||||
|
dag->rcs
|
||||||
|
rcs->rules
|
||||||
|
rules->rule-set))
|
||||||
|
|
||||||
|
(define-structure to-rule-set to-rule-set-interface
|
||||||
|
(open scheme-with-scsh
|
||||||
|
srfi-1
|
||||||
|
templates
|
||||||
|
make-rule
|
||||||
|
dfs)
|
||||||
|
(files to-rule-set))
|
||||||
|
|
||||||
|
(define-interface dfs-interface
|
||||||
|
(export make-dfs
|
||||||
|
dfs->list
|
||||||
|
dfs-dag-show
|
||||||
|
dfs))
|
||||||
|
|
||||||
|
(define-structure dfs dfs-interface
|
||||||
|
(open scheme-with-scsh
|
||||||
|
finite-types
|
||||||
|
threads
|
||||||
|
srfi-1
|
||||||
|
srfi-9
|
||||||
|
misc
|
||||||
|
let-opt
|
||||||
|
(with-prefix rendezvous-channels cml-sync-ch/))
|
||||||
|
(files dfs))
|
||||||
|
|
||||||
|
(define-interface misc-interface
|
||||||
|
(export sort
|
||||||
|
insert))
|
||||||
|
|
||||||
|
(define-structure misc misc-interface
|
||||||
|
(open scheme-with-scsh)
|
||||||
|
(files misc))
|
||||||
|
|
||||||
|
(define-interface templates-interface
|
||||||
|
(export make-rule-build-func
|
||||||
|
make-md5-build-func
|
||||||
|
make-always-build-func
|
||||||
|
make-once-build-func
|
||||||
|
make-is-out-of-date!
|
||||||
|
make-once
|
||||||
|
make-is-out-of-date?
|
||||||
|
make-md5-sum-changed?))
|
||||||
|
|
||||||
|
(define-structure templates templates-interface
|
||||||
|
(open scheme-with-scsh
|
||||||
|
srfi-1
|
||||||
|
srfi-13)
|
||||||
|
(files templates))
|
||||||
|
|
||||||
|
(define-structure make (export make)
|
||||||
|
(open scheme-with-scsh
|
||||||
|
srfi-1
|
||||||
|
macros
|
||||||
|
let-opt
|
||||||
|
to-rule-set
|
||||||
|
make-rule)
|
||||||
|
(files make))
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
;;; TODO:
|
|
||||||
;;;
|
|
||||||
;;; change to topological sort
|
|
||||||
|
|
||||||
;;;
|
|
||||||
;;; RULE-TRANS-SET
|
|
||||||
;;;
|
|
||||||
;;; (make-empty-rule-trans-set) ---> rule-trans-set
|
|
||||||
;;;
|
|
||||||
;;; (make-rule-trans-set rule-candidates known-rules rule-set)
|
|
||||||
;;;
|
|
||||||
;;; (rule-trans-set-rule-candidates rts) ---> (rule-candidate0 ...)
|
|
||||||
;;; (rule-trans-set-known-rules rts) ---> (known-rule0 ...)
|
|
||||||
;;; (rule-trans-set-rule-set rts) ---> rule-set
|
|
||||||
;;;
|
|
||||||
;;; (rule-trans-set-add! rule-trans-set target prereqs wants-build? build-func)
|
|
||||||
;;; ---> rule-trans-set
|
|
||||||
;;;
|
|
||||||
(define-record-type :rule-trans-set
|
|
||||||
(make-rule-trans-set rule-candidates known-rules rule-set)
|
|
||||||
is-rule-trans-set?
|
|
||||||
(rule-candidates rule-trans-set-rule-candidates)
|
|
||||||
(known-rules rule-trans-set-known-rules)
|
|
||||||
(rule-set rule-trans-set-rule-set))
|
|
||||||
|
|
||||||
(define (make-empty-rule-trans-set)
|
|
||||||
(let ((rule-candidates '())
|
|
||||||
(known-rules (alist-cons '() '() '()))
|
|
||||||
(rule-set (make-empty-rule-set)))
|
|
||||||
(make-rule-trans-set rule-candidates known-rules rule-set)))
|
|
||||||
|
|
||||||
;;; o every incoming rule is considered as a rule-candidate
|
|
||||||
;;; o add the new rule-candidate to rule-candidates
|
|
||||||
;;; o run known-rules-update afterwards
|
|
||||||
(define rule-trans-set-add
|
|
||||||
(lambda (rule-trans-set target prereqs wants-build? build-func)
|
|
||||||
(rule-candidate-add rule-trans-set target prereqs wants-build? build-func)))
|
|
||||||
|
|
||||||
(define rule-candidate-add
|
|
||||||
(lambda (rule-trans-set target prereqs wants-build? build-func)
|
|
||||||
(let ((rule-candidates (rule-trans-set-rule-candidates rule-trans-set))
|
|
||||||
(known-rules (rule-trans-set-known-rules rule-trans-set))
|
|
||||||
(rule-set (rule-trans-set-rule-set rule-trans-set))
|
|
||||||
(rule-args (list prereqs wants-build? build-func)))
|
|
||||||
(make-rule-trans-set (alist-cons target rule-args rule-candidates)
|
|
||||||
known-rules
|
|
||||||
rule-set))))
|
|
||||||
|
|
||||||
(define (rule-candidate-del rule-trans-set target)
|
|
||||||
(let ((rule-candidates (rule-trans-set-rule-candidates rule-trans-set))
|
|
||||||
(known-rules (rule-trans-set-known-rules rule-trans-set))
|
|
||||||
(rule-set (rule-trans-set-rule-set rule-trans-set)))
|
|
||||||
(make-rule-trans-set (alist-delete! target rule-candidates)
|
|
||||||
known-rules
|
|
||||||
rule-set)))
|
|
||||||
|
|
||||||
(define (rule-candidate-get rule-trans-set target)
|
|
||||||
(let* ((rule-candidates (rule-trans-set-rule-candidates rule-trans-set))
|
|
||||||
(maybe-rule-candidate (assq target rule-candidates)))
|
|
||||||
(if maybe-rule-candidate
|
|
||||||
(cons target (cdr (assq target rule-candidates)))
|
|
||||||
maybe-rule-candidate)))
|
|
||||||
|
|
||||||
;;; o if a target's prereqs are all in known-rules then the rule-candidate
|
|
||||||
;;; can be added to the known-rules as a freshly created rule
|
|
||||||
;;; o any rule-candidate with () as prereqs can be added to the known-rules
|
|
||||||
;;; as well, so this will be the first element of the known-rules
|
|
||||||
(define known-rules-add
|
|
||||||
(lambda (rule-trans-set target prereqs wants-build? build-func)
|
|
||||||
(let ((rule (make-rule (map (lambda (prereq)
|
|
||||||
(known-rules-get rule-trans-set prereq))
|
|
||||||
prereqs)
|
|
||||||
wants-build?
|
|
||||||
build-func))
|
|
||||||
(rule-candidates (rule-trans-set-rule-candidates rule-trans-set))
|
|
||||||
(known-rules (rule-trans-set-known-rules rule-trans-set))
|
|
||||||
(rule-set (rule-trans-set-rule-set rule-trans-set)))
|
|
||||||
(make-rule-trans-set rule-candidates
|
|
||||||
(alist-cons target rule known-rules)
|
|
||||||
(rule-set-add rule rule-set)))))
|
|
||||||
|
|
||||||
(define (known-rules-get rule-trans-set target)
|
|
||||||
(let* ((known-rules (rule-trans-set-known-rules rule-trans-set))
|
|
||||||
(maybe-rule (assoc target known-rules)))
|
|
||||||
(if maybe-rule (cdr maybe-rule) maybe-rule)))
|
|
||||||
|
|
||||||
(define (known-rules-update rts)
|
|
||||||
(let until-no-change ((last-rcs (length (rule-trans-set-rule-candidates rts)))
|
|
||||||
(rule-trans-set rts))
|
|
||||||
(let* ((rule-candidates (rule-trans-set-rule-candidates rule-trans-set))
|
|
||||||
(candidate-descs (map cons (map car rule-candidates)
|
|
||||||
(map cdr rule-candidates))))
|
|
||||||
(let for-candidates ((current-candidate-desc (car candidate-descs))
|
|
||||||
(to-do-candidate-desc (cdr candidate-descs))
|
|
||||||
(current-rts rule-trans-set))
|
|
||||||
(let ((target (list-ref current-candidate-desc 0))
|
|
||||||
(prereqs (list-ref current-candidate-desc 1))
|
|
||||||
(wants-build? (list-ref current-candidate-desc 2))
|
|
||||||
(build-func (list-ref current-candidate-desc 3)))
|
|
||||||
(let* ((known-rules (rule-trans-set-known-rules current-rts))
|
|
||||||
;;
|
|
||||||
;; if all prereqs of a target are in known-rules
|
|
||||||
;; then the rule-candidate can be added to the known-rules
|
|
||||||
;; after its deletion of the rule-candidates
|
|
||||||
;;
|
|
||||||
(new-rts (if (not (memq #f
|
|
||||||
(map (lambda (prereq)
|
|
||||||
(assoc prereq known-rules))
|
|
||||||
prereqs)))
|
|
||||||
(known-rules-add (rule-candidate-del
|
|
||||||
current-rts
|
|
||||||
target)
|
|
||||||
target prereqs
|
|
||||||
wants-build? build-func)
|
|
||||||
current-rts)))
|
|
||||||
(if (not (null? to-do-candidate-desc))
|
|
||||||
(for-candidates (car to-do-candidate-desc)
|
|
||||||
(cdr to-do-candidate-desc)
|
|
||||||
new-rts)
|
|
||||||
(let ((current-rcs (length (rule-trans-set-rule-candidates
|
|
||||||
new-rts))))
|
|
||||||
(if (or (= current-rcs last-rcs) (= current-rcs 0))
|
|
||||||
new-rts
|
|
||||||
(until-no-change current-rcs new-rts))))))))))
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
;;; TODO:
|
||||||
|
;;;
|
||||||
|
;;; (update-md-sum ...) is (due to history) not very lucky
|
||||||
|
;;;
|
||||||
|
(define digest-files (list "checksums.md5"
|
||||||
|
"fingerprints.md5"
|
||||||
|
"digests.md5"))
|
||||||
|
|
||||||
|
(define digest-extensions (list ".md5" ".fp" ".digest"))
|
||||||
|
|
||||||
|
(define (make-rule-build-func target prereqs thunk)
|
||||||
|
(lambda args
|
||||||
|
(cons (begin
|
||||||
|
(display ";;; rule : ")
|
||||||
|
(display target)
|
||||||
|
(newline)
|
||||||
|
(thunk))
|
||||||
|
(last args))))
|
||||||
|
|
||||||
|
(define (make-md5-build-func target prereqs thunk)
|
||||||
|
(lambda args
|
||||||
|
(cons (begin
|
||||||
|
(display ";;; md5 : ")
|
||||||
|
(display target)
|
||||||
|
(newline)
|
||||||
|
(thunk))
|
||||||
|
(last args))))
|
||||||
|
|
||||||
|
(define (make-always-build-func target prereqs thunk)
|
||||||
|
(lambda args
|
||||||
|
(cons (begin
|
||||||
|
(display ";;; always : ")
|
||||||
|
(display target)
|
||||||
|
(newline)
|
||||||
|
(thunk))
|
||||||
|
(last args))))
|
||||||
|
|
||||||
|
(define (make-once-build-func target prereqs thunk)
|
||||||
|
(lambda args
|
||||||
|
(cons (begin
|
||||||
|
(display ";;; once : ")
|
||||||
|
(display target)
|
||||||
|
(newline)
|
||||||
|
(thunk))
|
||||||
|
(last args))))
|
||||||
|
|
||||||
|
(define (make-is-out-of-date! target . prereqs)
|
||||||
|
;; init-state is the last arg
|
||||||
|
;; pass it untouched to the result
|
||||||
|
(lambda args (cons #t (last args))))
|
||||||
|
|
||||||
|
(define (make-once target . prereqs)
|
||||||
|
;; init-state is the last arg
|
||||||
|
;; pass it untouched to the result
|
||||||
|
(lambda args (cons (file-not-exists? target) (last args))))
|
||||||
|
|
||||||
|
(define (make-is-out-of-date? target . prereqs)
|
||||||
|
(lambda args
|
||||||
|
(let ((init-state (last args)))
|
||||||
|
(cons (or (file-not-exists? target)
|
||||||
|
(and (not (null? prereqs))
|
||||||
|
(let for-each-prereq ((prereq (car prereqs))
|
||||||
|
(todo (cdr prereqs)))
|
||||||
|
(and (file-exists? prereq)
|
||||||
|
(> (file-last-mod prereq)
|
||||||
|
(file-last-mod target))
|
||||||
|
(or (null? todo)
|
||||||
|
(for-each-prereq (car todo) (cdr todo)))))))
|
||||||
|
init-state))))
|
||||||
|
|
||||||
|
(define (make-md5-sum-changed? target . prereqs)
|
||||||
|
(lambda args
|
||||||
|
(let ((init-state (last args))
|
||||||
|
(tfname (expand-file-name target (cwd))))
|
||||||
|
(cons (or (file-not-exists? tfname)
|
||||||
|
(or (null? prereqs)
|
||||||
|
(let for-each-prereq ((prereq (car prereqs))
|
||||||
|
(todo (cdr prereqs)))
|
||||||
|
(let ((pname (expand-file-name prereq (cwd))))
|
||||||
|
(or (and (file-exists? pname)
|
||||||
|
(> (file-last-mod pname)
|
||||||
|
(file-last-mod tfname))
|
||||||
|
(checksum-changed? pname)
|
||||||
|
(or (md5-sum-update pname) #t))
|
||||||
|
(and (not (null? todo))
|
||||||
|
(for-each-prereq (car todo) (cdr todo))))))))
|
||||||
|
init-state))))
|
||||||
|
|
||||||
|
(define (check-files-target+extensions target checksum)
|
||||||
|
(map (lambda (digest-file)
|
||||||
|
(lambda ()
|
||||||
|
(let ((dfile (expand-file-name digest-file (cwd))))
|
||||||
|
(or (file-not-exists? dfile)
|
||||||
|
(let ((strls (port->string-list (open-input-file dfile))))
|
||||||
|
(= checksum
|
||||||
|
(string->number (if (null? strls) "" (car strls)))))))))
|
||||||
|
(map (lambda (ext)
|
||||||
|
(string-append target ext))
|
||||||
|
digest-extensions)))
|
||||||
|
|
||||||
|
(define (update-files-target+extensions target checksum)
|
||||||
|
(map (lambda (digest-file)
|
||||||
|
(lambda ()
|
||||||
|
(let ((dfile (expand-file-name digest-file (cwd))))
|
||||||
|
(and (file-exists? dfile)
|
||||||
|
(let ((outport (open-output-file dfile)))
|
||||||
|
(display ";;; update : ") (display target) (newline)
|
||||||
|
(with-current-output-port
|
||||||
|
outport
|
||||||
|
(lambda ()
|
||||||
|
(display (number->string checksum)) (newline)))
|
||||||
|
(close outport)
|
||||||
|
#t)))))
|
||||||
|
(map (lambda (ext)
|
||||||
|
(string-append target ext))
|
||||||
|
digest-extensions)))
|
||||||
|
|
||||||
|
(define (digest-file->string-list digest-fname)
|
||||||
|
(let* ((inport (open-input-file (expand-file-name digest-fname (cwd))))
|
||||||
|
(strls (map (lambda (str)
|
||||||
|
(let ((ls (string-tokenize str)))
|
||||||
|
(if (not (null? ls))
|
||||||
|
(let ((fp (car ls))
|
||||||
|
(name (cadr ls)))
|
||||||
|
(cons name fp))
|
||||||
|
'())))
|
||||||
|
(port->string-list inport))))
|
||||||
|
(close inport)
|
||||||
|
strls))
|
||||||
|
|
||||||
|
(define (check-digest-files target checksum)
|
||||||
|
(map (lambda (digest-file)
|
||||||
|
(lambda ()
|
||||||
|
(let ((dfile (expand-file-name digest-file (cwd)))
|
||||||
|
(tname (file-name-nondirectory target)))
|
||||||
|
(or (file-not-exists? dfile)
|
||||||
|
(let* ((*fname-md5* (digest-file->string-list dfile))
|
||||||
|
(maybe-md5 (if (or (null? *fname-md5*)
|
||||||
|
(null? (car *fname-md5*)))
|
||||||
|
#f
|
||||||
|
(assoc tname *fname-md5*))))
|
||||||
|
(or (not maybe-md5)
|
||||||
|
(= checksum
|
||||||
|
(string->number (cdr maybe-md5)))))))))
|
||||||
|
digest-files))
|
||||||
|
|
||||||
|
(define (string-list->digest-file dfname strls)
|
||||||
|
(let ((outport (open-output-file (expand-file-name dfname (cwd))))
|
||||||
|
(names (if (or (null? strls) (null? (car strls))) '() (map car strls)))
|
||||||
|
(sums (if (or (null? strls) (null? (car strls))) '() (map cdr strls))))
|
||||||
|
(display ";;; update : ") (display dfname) (newline)
|
||||||
|
(for-each (lambda (name fp)
|
||||||
|
(with-current-output-port outport
|
||||||
|
(for-each display (list fp " " name))
|
||||||
|
(newline)))
|
||||||
|
names sums)
|
||||||
|
(close outport)
|
||||||
|
#t))
|
||||||
|
|
||||||
|
(define (update-digest-files target checksum)
|
||||||
|
(map (lambda (digest-file)
|
||||||
|
(lambda ()
|
||||||
|
(let ((dfile (expand-file-name digest-file (cwd)))
|
||||||
|
(tname (file-name-nondirectory target)))
|
||||||
|
(and (file-exists? dfile)
|
||||||
|
(let* ((*fname-md5* (digest-file->string-list dfile))
|
||||||
|
(cleaned-table (if (or (null? *fname-md5*)
|
||||||
|
(null? (car *fname-md5*)))
|
||||||
|
(list)
|
||||||
|
(alist-delete tname *fname-md5*))))
|
||||||
|
(string-list->digest-file
|
||||||
|
dfile
|
||||||
|
(alist-cons tname checksum cleaned-table)))))))
|
||||||
|
digest-files))
|
||||||
|
|
||||||
|
(define (checksum-changed? target)
|
||||||
|
(let* ((inport (open-input-file target))
|
||||||
|
(checksum (md5-digest->number (md5-digest-for-port inport)))
|
||||||
|
(result-funcs (append (check-files-target+extensions target checksum)
|
||||||
|
(check-digest-files target checksum))))
|
||||||
|
(close inport)
|
||||||
|
(not (let each-result-and ((current (car result-funcs))
|
||||||
|
(todo (cdr result-funcs)))
|
||||||
|
(let ((res (current)))
|
||||||
|
(and res
|
||||||
|
(or (null? todo)
|
||||||
|
(each-result-and (car todo) (cdr todo)))))))))
|
||||||
|
|
||||||
|
(define (md5-sum-update target)
|
||||||
|
(let* ((tname (expand-file-name target (cwd)))
|
||||||
|
(inport (open-input-file tname))
|
||||||
|
(checksum (md5-digest->number (md5-digest-for-port inport)))
|
||||||
|
(update-funcs (append (update-files-target+extensions target checksum)
|
||||||
|
(update-digest-files target checksum))))
|
||||||
|
(close inport)
|
||||||
|
(let ((update-ok? (lambda ()
|
||||||
|
(let each-update-and ((current (car update-funcs))
|
||||||
|
(todo (cdr update-funcs)))
|
||||||
|
(or (current)
|
||||||
|
(and (not (null? todo))
|
||||||
|
(each-update-and (car todo) (cdr todo))))))))
|
||||||
|
;; the default is to use the filename with .md5 extension
|
||||||
|
(if (not (update-ok?))
|
||||||
|
(let ((outport (open-output-file (string-append tname ".md5"))))
|
||||||
|
(with-current-output-port outport
|
||||||
|
(begin
|
||||||
|
(display checksum)
|
||||||
|
(newline)))
|
||||||
|
(close outport))))))
|
135
to-rule-set.scm
135
to-rule-set.scm
|
@ -1,45 +1,122 @@
|
||||||
(define (rcs->dag rcs)
|
(define (rcs->dag rcs)
|
||||||
(map (lambda (rc)
|
(map (lambda (rc)
|
||||||
(make-dfs (car rc) (cadr rc) (caddr rc) (cadddr rc)))
|
(let ((target (list-ref rc 0))
|
||||||
|
(prereqs (list-ref rc 1))
|
||||||
|
(wants-build? (list-ref rc 2))
|
||||||
|
(build-func (list-ref rc 3)))
|
||||||
|
(make-dfs target prereqs (list wants-build? build-func))))
|
||||||
rcs))
|
rcs))
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; if dfs inserted leafs they have the ignored-data set to #f
|
||||||
|
;;; the build-func will then be set to produce an error
|
||||||
|
;;; in case of the file doesn't exist
|
||||||
|
;;;
|
||||||
(define (dag->rcs dag)
|
(define (dag->rcs dag)
|
||||||
(map (lambda (node)
|
(map (lambda (node)
|
||||||
(let* ((ls (dfs->list node))
|
(let* ((ls (dfs->list node))
|
||||||
(target (car ls))
|
(target (list-ref ls 0))
|
||||||
(prereqs (cadr ls))
|
(prereqs (list-ref ls 1))
|
||||||
(wants-build? (caddr ls))
|
(ignored (list-ref ls 2)))
|
||||||
(build-func (cdddr ls)))
|
(if ignored
|
||||||
(list target prereqs wants-build? build-func)))
|
(let ((wants-build? (car ignored))
|
||||||
|
(build-func (cadr ignored)))
|
||||||
|
(list target prereqs wants-build? build-func))
|
||||||
|
(let* ((tfname (expand-file-name target (cwd)))
|
||||||
|
(wants-build? (lambda args
|
||||||
|
(cons (file-not-exists? tfname)
|
||||||
|
(last args))))
|
||||||
|
(build-func (lambda args
|
||||||
|
(error "file (assumed leaf) does not exist:"
|
||||||
|
tfname))))
|
||||||
|
(list target prereqs wants-build? build-func)))))
|
||||||
dag))
|
dag))
|
||||||
|
|
||||||
(define (lookup-rc rcs rc)
|
(define (lookup-rc rc rcs)
|
||||||
(let ((maybe-rc (find (lambda (current)
|
(let ((maybe-rc (find (lambda (current)
|
||||||
(eq? (car rc) (car current)))
|
(eq? (car rc) (car current)))
|
||||||
rcs)))
|
rcs)))
|
||||||
(if maybe-rc maybe-rc (error "lookup-rc: rc not found."))))
|
(if maybe-rc maybe-rc (error "lookup-rc: rc not found."))))
|
||||||
|
|
||||||
(define (rcs->rules rcs)
|
(define (lookup-fname fname rcs)
|
||||||
(let ((sorted-rcs (dag->rcs (dfs (rcs->dag rcs)))))
|
(let ((maybe-fname (find (lambda (current)
|
||||||
(map (lambda (rc)
|
(eq? fname (car current)))
|
||||||
(let* ((target (car rc))
|
rcs)))
|
||||||
(prereqs (cadr rc))
|
(if maybe-fname maybe-fname (error "lookup-fname: fname not found."))))
|
||||||
(wants-build? (caddr rc))
|
|
||||||
(build-func (cdddr rc))
|
|
||||||
(prereq-rcs (map (lambda (p)
|
|
||||||
(lookup-rc sorted-rcs p))
|
|
||||||
prereqs))
|
|
||||||
(rule (make-rule prereq-rcs wants-build? build-func)))
|
|
||||||
(cons target rule)))
|
|
||||||
rcs)))
|
|
||||||
|
|
||||||
(define (rules->rule-set rules)
|
(define (lookup-rule fname rules)
|
||||||
(let for-each-rule ((current-rule (if (null? rules) '() (car rules)))
|
(let ((maybe-rule (assoc fname rules)))
|
||||||
(rules-to-do (if (null? rules) '() (cdr rules)))
|
(if maybe-rule
|
||||||
(rule-set (make-empty-rule-set)))
|
(cdr maybe-rule)
|
||||||
(if (not (null? rules-to-do))
|
(error "lookup-rule: fname not found in rules."))))
|
||||||
(for-each-rule (car rules-to-do)
|
|
||||||
(cdr rules-to-do)
|
|
||||||
(rule-set-add current-rule rule-set)))
|
|
||||||
rule-set))
|
|
||||||
|
|
||||||
|
(define (rcs->rules rule-candidates)
|
||||||
|
(let* ((sorted-dag (dfs (rcs->dag rule-candidates)))
|
||||||
|
(sorted-rcs (dag->rcs sorted-dag)))
|
||||||
|
;; (dfs-dag-show sorted-dag (car sorted-dag))
|
||||||
|
;; (rcs-show sorted-rcs)
|
||||||
|
(if (not (null? sorted-rcs))
|
||||||
|
(let for-all-rcs ((rc (car sorted-rcs))
|
||||||
|
(todo (cdr sorted-rcs))
|
||||||
|
(last-done '()))
|
||||||
|
(let* ((target (list-ref rc 0))
|
||||||
|
(prereqs (list-ref rc 1))
|
||||||
|
(wants-build? (list-ref rc 2))
|
||||||
|
(build-func (list-ref rc 3))
|
||||||
|
(done (cons (cons target
|
||||||
|
(make-rule (map (lambda (p)
|
||||||
|
(lookup-rule p last-done))
|
||||||
|
prereqs)
|
||||||
|
wants-build?
|
||||||
|
build-func))
|
||||||
|
last-done)))
|
||||||
|
(if (not (null? todo))
|
||||||
|
(for-all-rcs (car todo) (cdr todo) done)
|
||||||
|
done))))))
|
||||||
|
|
||||||
|
(define (rules->rule-set rule-alist)
|
||||||
|
(if (not (null? rule-alist))
|
||||||
|
(let ((rules (map cdr rule-alist)))
|
||||||
|
(let for-each-rule ((current-rule (car rules))
|
||||||
|
(rules-to-do (cdr rules))
|
||||||
|
(rule-set (make-empty-rule-set)))
|
||||||
|
(let ((next-rule-set (rule-set-add current-rule rule-set)))
|
||||||
|
(if (not (null? rules-to-do))
|
||||||
|
(for-each-rule (car rules-to-do)
|
||||||
|
(cdr rules-to-do)
|
||||||
|
next-rule-set)
|
||||||
|
next-rule-set))))))
|
||||||
|
|
||||||
|
(define (rcs-show rcs)
|
||||||
|
(newline) (newline) (newline) (newline)
|
||||||
|
(display ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||||
|
(display ";;; rcs-show ;;;\n")
|
||||||
|
(display ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||||
|
(let ((rc-show (lambda (rc)
|
||||||
|
(let ((target (list-ref rc 0))
|
||||||
|
(prereqs (list-ref rc 1))
|
||||||
|
(wants-build? (list-ref rc 2))
|
||||||
|
(build-func (list-ref rc 3)))
|
||||||
|
(newline)
|
||||||
|
(display "; target: ")
|
||||||
|
(display target)
|
||||||
|
(newline)
|
||||||
|
(display "; prereqs: ")
|
||||||
|
(display prereqs)
|
||||||
|
(newline)
|
||||||
|
(display "; wants-build?: ")
|
||||||
|
(display wants-build?)
|
||||||
|
(newline)
|
||||||
|
(display "; build-func: ")
|
||||||
|
(display build-func)
|
||||||
|
(newline)))))
|
||||||
|
(if (not (null? rcs))
|
||||||
|
(let visit-each-rc ((current-rc (car rcs))
|
||||||
|
(todo-rcs (cdr rcs)))
|
||||||
|
(rc-show current-rc)
|
||||||
|
(if (not (null? todo-rcs))
|
||||||
|
(visit-each-rc (car todo-rcs) (cdr todo-rcs))
|
||||||
|
(begin
|
||||||
|
(display ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||||
|
(display ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n")
|
||||||
|
(newline) (newline) (newline) (newline)))))))
|
||||||
|
|
Loading…
Reference in New Issue