compiler/cm-accomplice: add `register-external-module'
The new function allows declaration of a module dependency, as opposed to a mere file dependency. Misuse of this function opens the door to cyclic compilation dependencies, so we have to check for that in `compiler/cm'.
This commit is contained in:
parent
50af874a7a
commit
06ffb74d66
|
@ -1,10 +1,17 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide register-external-file)
|
(provide register-external-file
|
||||||
|
register-external-module)
|
||||||
|
|
||||||
(define (register-external-file f)
|
(define (register-external-file f)
|
||||||
|
(register-external 'register-external-file f #f))
|
||||||
|
(define (register-external-module f)
|
||||||
|
(register-external 'register-external-module f #t))
|
||||||
|
|
||||||
|
(define (register-external who f module?)
|
||||||
(unless (and (path? f) (complete-path? f))
|
(unless (and (path? f) (complete-path? f))
|
||||||
(raise-type-error 'register-external-file "complete path" f))
|
(raise-type-error who "complete path" f))
|
||||||
(log-message (current-logger)
|
(log-message (current-logger)
|
||||||
'info
|
'info
|
||||||
(format "file dependency: ~s" f)
|
(format "file dependency: ~s" f)
|
||||||
`#s(file-dependency ,f)))
|
`#s(file-dependency ,f ,module?)))
|
||||||
|
|
|
@ -266,7 +266,7 @@
|
||||||
(get-source-sha1 (path-replace-suffix p #".ss"))))])
|
(get-source-sha1 (path-replace-suffix p #".ss"))))])
|
||||||
(call-with-input-file* p sha1)))
|
(call-with-input-file* p sha1)))
|
||||||
|
|
||||||
(define (get-dep-sha1s deps up-to-date read-src-syntax mode roots must-exist?)
|
(define (get-dep-sha1s deps up-to-date read-src-syntax mode roots must-exist? seen)
|
||||||
(let ([l (for/fold ([l null]) ([dep (in-list deps)])
|
(let ([l (for/fold ([l null]) ([dep (in-list deps)])
|
||||||
(and l
|
(and l
|
||||||
;; (cons 'ext rel-path) => a non-module file, check source
|
;; (cons 'ext rel-path) => a non-module file, check source
|
||||||
|
@ -280,8 +280,8 @@
|
||||||
[must-exist? (error 'cm "cannot find external-dependency file: ~v" p)]
|
[must-exist? (error 'cm "cannot find external-dependency file: ~v" p)]
|
||||||
[else #f]))]
|
[else #f]))]
|
||||||
[(or (hash-ref up-to-date (simple-form-path p) #f)
|
[(or (hash-ref up-to-date (simple-form-path p) #f)
|
||||||
;; Use `compiler-root' with `sha1-only?' as #t:
|
;; Use `compile-root' with `sha1-only?' as #t:
|
||||||
(compile-root mode roots p up-to-date read-src-syntax #t))
|
(compile-root mode roots p up-to-date read-src-syntax #t seen))
|
||||||
=> (lambda (sh)
|
=> (lambda (sh)
|
||||||
(cons (cons (cdr sh) dep) l))]
|
(cons (cons (cdr sh) dep) l))]
|
||||||
[must-exist?
|
[must-exist?
|
||||||
|
@ -303,9 +303,12 @@
|
||||||
;; compute one hash from all hashes
|
;; compute one hash from all hashes
|
||||||
(sha1 (open-input-bytes (get-output-bytes p)))))))
|
(sha1 (open-input-bytes (get-output-bytes p)))))))
|
||||||
|
|
||||||
(define (write-deps code mode roots path src-sha1 external-deps reader-deps up-to-date read-src-syntax)
|
(define (write-deps code mode roots path src-sha1
|
||||||
|
external-deps external-module-deps reader-deps
|
||||||
|
up-to-date read-src-syntax)
|
||||||
(let ([dep-path (path-add-suffix (get-compilation-path mode roots path) #".dep")]
|
(let ([dep-path (path-add-suffix (get-compilation-path mode roots path) #".dep")]
|
||||||
[deps (remove-duplicates (append (get-deps code path)
|
[deps (remove-duplicates (append (get-deps code path)
|
||||||
|
external-module-deps ; can create cycles if misused!
|
||||||
reader-deps))]
|
reader-deps))]
|
||||||
[external-deps (remove-duplicates external-deps)])
|
[external-deps (remove-duplicates external-deps)])
|
||||||
(with-compile-output dep-path
|
(with-compile-output dep-path
|
||||||
|
@ -317,7 +320,7 @@
|
||||||
external-deps))])
|
external-deps))])
|
||||||
(write (list* (version)
|
(write (list* (version)
|
||||||
(cons (or src-sha1 (get-source-sha1 path))
|
(cons (or src-sha1 (get-source-sha1 path))
|
||||||
(get-dep-sha1s deps up-to-date read-src-syntax mode roots #t))
|
(get-dep-sha1s deps up-to-date read-src-syntax mode roots #t #hash()))
|
||||||
deps)
|
deps)
|
||||||
op)
|
op)
|
||||||
(newline op))))))
|
(newline op))))))
|
||||||
|
@ -345,7 +348,7 @@
|
||||||
|
|
||||||
(define-struct ext-reader-guard (proc top)
|
(define-struct ext-reader-guard (proc top)
|
||||||
#:property prop:procedure (struct-field-index proc))
|
#:property prop:procedure (struct-field-index proc))
|
||||||
(define-struct file-dependency (path) #:prefab)
|
(define-struct file-dependency (path module?) #:prefab)
|
||||||
|
|
||||||
(define (compile-zo* mode roots path src-sha1 read-src-syntax zo-name up-to-date)
|
(define (compile-zo* mode roots path src-sha1 read-src-syntax zo-name up-to-date)
|
||||||
;; The `path' argument has been converted to .rkt or .ss form,
|
;; The `path' argument has been converted to .rkt or .ss form,
|
||||||
|
@ -353,14 +356,17 @@
|
||||||
;; External dependencies registered through reader guard and
|
;; External dependencies registered through reader guard and
|
||||||
;; accomplice-logged events:
|
;; accomplice-logged events:
|
||||||
(define external-deps null)
|
(define external-deps null)
|
||||||
|
(define external-module-deps null)
|
||||||
(define reader-deps null)
|
(define reader-deps null)
|
||||||
(define deps-sema (make-semaphore 1))
|
(define deps-sema (make-semaphore 1))
|
||||||
(define done-key (gensym))
|
(define done-key (gensym))
|
||||||
(define (external-dep! p)
|
(define (external-dep! p module?)
|
||||||
(call-with-semaphore
|
(call-with-semaphore
|
||||||
deps-sema
|
deps-sema
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(set! external-deps (cons (path->bytes p) external-deps)))))
|
(if module?
|
||||||
|
(set! external-module-deps (cons (path->bytes p) external-module-deps))
|
||||||
|
(set! external-deps (cons (path->bytes p) external-deps))))))
|
||||||
(define (reader-dep! p)
|
(define (reader-dep! p)
|
||||||
(call-with-semaphore
|
(call-with-semaphore
|
||||||
deps-sema
|
deps-sema
|
||||||
|
@ -379,7 +385,8 @@
|
||||||
(if (and (eq? (vector-ref l 0) 'info)
|
(if (and (eq? (vector-ref l 0) 'info)
|
||||||
(file-dependency? (vector-ref l 2))
|
(file-dependency? (vector-ref l 2))
|
||||||
(path? (file-dependency-path (vector-ref l 2))))
|
(path? (file-dependency-path (vector-ref l 2))))
|
||||||
(external-dep! (file-dependency-path (vector-ref l 2)))
|
(external-dep! (file-dependency-path (vector-ref l 2))
|
||||||
|
(file-dependency-module? (vector-ref l 2)))
|
||||||
(log-message orig-log (vector-ref l 0) (vector-ref l 1)
|
(log-message orig-log (vector-ref l 0) (vector-ref l 1)
|
||||||
(vector-ref l 2)))
|
(vector-ref l 2)))
|
||||||
(loop))))))))
|
(loop))))))))
|
||||||
|
@ -465,7 +472,9 @@
|
||||||
;; Note that we check time and write .deps before returning from
|
;; Note that we check time and write .deps before returning from
|
||||||
;; with-compile-output...
|
;; with-compile-output...
|
||||||
(verify-times path tmp-name)
|
(verify-times path tmp-name)
|
||||||
(write-deps code mode dest-roots path src-sha1 external-deps reader-deps up-to-date read-src-syntax)))))
|
(write-deps code mode dest-roots path src-sha1
|
||||||
|
external-deps external-module-deps reader-deps
|
||||||
|
up-to-date read-src-syntax)))))
|
||||||
|
|
||||||
(define (install-module-hashes! s start len)
|
(define (install-module-hashes! s start len)
|
||||||
(define vlen (bytes-ref s (+ start 2)))
|
(define vlen (bytes-ref s (+ start 2)))
|
||||||
|
@ -506,7 +515,7 @@
|
||||||
alt-path
|
alt-path
|
||||||
path))))
|
path))))
|
||||||
|
|
||||||
(define (maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date)
|
(define (maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date seen)
|
||||||
(let ([actual-path (actual-source-path orig-path)])
|
(let ([actual-path (actual-source-path orig-path)])
|
||||||
(unless sha1-only?
|
(unless sha1-only?
|
||||||
((manager-compile-notify-handler) actual-path)
|
((manager-compile-notify-handler) actual-path)
|
||||||
|
@ -531,7 +540,7 @@
|
||||||
(if (and zo-exists?
|
(if (and zo-exists?
|
||||||
src-sha1
|
src-sha1
|
||||||
(equal? src-sha1 (caadr deps))
|
(equal? src-sha1 (caadr deps))
|
||||||
(equal? (get-dep-sha1s (cddr deps) up-to-date read-src-syntax mode roots #f)
|
(equal? (get-dep-sha1s (cddr deps) up-to-date read-src-syntax mode roots #f seen)
|
||||||
(cdadr deps)))
|
(cdadr deps)))
|
||||||
(begin
|
(begin
|
||||||
(log-info (format "cm: ~ahash-equivalent ~a"
|
(log-info (format "cm: ~ahash-equivalent ~a"
|
||||||
|
@ -610,7 +619,7 @@
|
||||||
(path-replace-suffix p #".ss")
|
(path-replace-suffix p #".ss")
|
||||||
p)))
|
p)))
|
||||||
|
|
||||||
(define (compile-root mode roots path0 up-to-date read-src-syntax sha1-only?)
|
(define (compile-root mode roots path0 up-to-date read-src-syntax sha1-only? seen)
|
||||||
(define orig-path (simple-form-path path0))
|
(define orig-path (simple-form-path path0))
|
||||||
(define (read-deps path)
|
(define (read-deps path)
|
||||||
(with-handlers ([exn:fail:filesystem? (lambda (ex) (list (version) '#f))])
|
(with-handlers ([exn:fail:filesystem? (lambda (ex) (list (version) '#f))])
|
||||||
|
@ -630,6 +639,11 @@
|
||||||
[path-time (or main-path-time alt-path-time)]
|
[path-time (or main-path-time alt-path-time)]
|
||||||
[path-zo-time (get-compiled-time mode roots path)])
|
[path-zo-time (get-compiled-time mode roots path)])
|
||||||
(cond
|
(cond
|
||||||
|
[(hash-ref seen path #f)
|
||||||
|
(error 'compile-zo
|
||||||
|
"dependency cycle\n involves module: ~a"
|
||||||
|
path)
|
||||||
|
#f]
|
||||||
[(not path-time)
|
[(not path-time)
|
||||||
(trace-printf "~a does not exist" orig-path)
|
(trace-printf "~a does not exist" orig-path)
|
||||||
(or (hash-ref up-to-date orig-path #f)
|
(or (hash-ref up-to-date orig-path #f)
|
||||||
|
@ -640,17 +654,18 @@
|
||||||
(hash-set! up-to-date alt-path stamp))
|
(hash-set! up-to-date alt-path stamp))
|
||||||
stamp))]
|
stamp))]
|
||||||
[else
|
[else
|
||||||
(let ([deps (read-deps path)])
|
(let ([deps (read-deps path)]
|
||||||
|
[new-seen (hash-set seen path #t)])
|
||||||
(define build
|
(define build
|
||||||
(cond
|
(cond
|
||||||
[(not (and (pair? deps) (equal? (version) (car deps))))
|
[(not (and (pair? deps) (equal? (version) (car deps))))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(trace-printf "newer version...")
|
(trace-printf "newer version...")
|
||||||
(maybe-compile-zo #f #f mode roots path orig-path read-src-syntax up-to-date))]
|
(maybe-compile-zo #f #f mode roots path orig-path read-src-syntax up-to-date new-seen))]
|
||||||
[(> path-time path-zo-time)
|
[(> path-time path-zo-time)
|
||||||
(trace-printf "newer src...")
|
(trace-printf "newer src...")
|
||||||
;; If `sha1-only?', then `maybe-compile-zo' returns a #f or thunk:
|
;; If `sha1-only?', then `maybe-compile-zo' returns a #f or thunk:
|
||||||
(maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date)]
|
(maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date new-seen)]
|
||||||
[(ormap
|
[(ormap
|
||||||
(lambda (p)
|
(lambda (p)
|
||||||
;; (cons 'ext rel-path) => a non-module file (check date)
|
;; (cons 'ext rel-path) => a non-module file (check date)
|
||||||
|
@ -660,15 +675,16 @@
|
||||||
(define t
|
(define t
|
||||||
(if ext?
|
(if ext?
|
||||||
(cons (try-file-time d) #f)
|
(cons (try-file-time d) #f)
|
||||||
(compile-root mode roots d up-to-date read-src-syntax #f)))
|
(compile-root mode roots d up-to-date read-src-syntax #f new-seen)))
|
||||||
(and (car t)
|
(and t
|
||||||
|
(car t)
|
||||||
(> (car t) path-zo-time)
|
(> (car t) path-zo-time)
|
||||||
(begin (trace-printf "newer: ~a (~a > ~a)..."
|
(begin (trace-printf "newer: ~a (~a > ~a)..."
|
||||||
d (car t) path-zo-time)
|
d (car t) path-zo-time)
|
||||||
#t)))
|
#t)))
|
||||||
(cddr deps))
|
(cddr deps))
|
||||||
;; If `sha1-only?', then `maybe-compile-zo' returns a #f or thunk:
|
;; If `sha1-only?', then `maybe-compile-zo' returns a #f or thunk:
|
||||||
(maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date)]
|
(maybe-compile-zo sha1-only? deps mode roots path orig-path read-src-syntax up-to-date new-seen)]
|
||||||
[else #f]))
|
[else #f]))
|
||||||
(cond
|
(cond
|
||||||
[(and build sha1-only?) #f]
|
[(and build sha1-only?) #f]
|
||||||
|
@ -704,7 +720,8 @@
|
||||||
(path->complete-path src)
|
(path->complete-path src)
|
||||||
cache
|
cache
|
||||||
read-src-syntax
|
read-src-syntax
|
||||||
#f)
|
#f
|
||||||
|
#hash())
|
||||||
(void)))))
|
(void)))))
|
||||||
|
|
||||||
(define (make-compilation-manager-load/use-compiled-handler [delete-zos-when-rkt-file-does-not-exist? #f]
|
(define (make-compilation-manager-load/use-compiled-handler [delete-zos-when-rkt-file-does-not-exist? #f]
|
||||||
|
@ -768,7 +785,7 @@
|
||||||
[else
|
[else
|
||||||
(trace-printf "processing: ~a" path)
|
(trace-printf "processing: ~a" path)
|
||||||
(parameterize ([compiler-security-guard security-guard])
|
(parameterize ([compiler-security-guard security-guard])
|
||||||
(compile-root (car modes) roots path cache read-syntax #f))
|
(compile-root (car modes) roots path cache read-syntax #f #hash()))
|
||||||
(trace-printf "done: ~a" path)])
|
(trace-printf "done: ~a" path)])
|
||||||
(default-handler path mod-name))
|
(default-handler path mod-name))
|
||||||
(when (null? modes)
|
(when (null? modes)
|
||||||
|
|
|
@ -528,7 +528,8 @@ directory.
|
||||||
|
|
||||||
Logs a message (see @racket[log-message]) at level @racket['info]. The
|
Logs a message (see @racket[log-message]) at level @racket['info]. The
|
||||||
message data is a @racketidfont{file-dependency} prefab structure type
|
message data is a @racketidfont{file-dependency} prefab structure type
|
||||||
with one field whose value is @racket[file].
|
with two fields; the first field's value is @racket[file] and the second
|
||||||
|
field's value is @racket[#f] (to indicate a non-module dependency).
|
||||||
|
|
||||||
A compilation manager implemented by @racketmodname[compiler/cm] looks
|
A compilation manager implemented by @racketmodname[compiler/cm] looks
|
||||||
for such messages to register an external dependency. The compilation
|
for such messages to register an external dependency. The compilation
|
||||||
|
@ -540,6 +541,17 @@ compilation manager will know to recompile the module.
|
||||||
The @racket[include] macro, for example, calls this procedure with the
|
The @racket[include] macro, for example, calls this procedure with the
|
||||||
path of an included file as it expands an @racket[include] form.}
|
path of an included file as it expands an @racket[include] form.}
|
||||||
|
|
||||||
|
@defproc[(register-external-module [file (and path? complete-path?)]) void?]{
|
||||||
|
|
||||||
|
Like @racket[register-external-file], but logs a message with a
|
||||||
|
@racketidfont{file-dependency} prefab structure type whose second
|
||||||
|
field is @racket[#t].
|
||||||
|
|
||||||
|
A compilation manager implemented by @racketmodname[compiler/cm]
|
||||||
|
recognizes the message to register a dependency on a
|
||||||
|
module (which implies a dependency on all of that module's
|
||||||
|
dependencies, etc.).}
|
||||||
|
|
||||||
@; ----------------------------------------------------------------------
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
@section[#:tag "zo"]{Compiling to Raw Bytecode}
|
@section[#:tag "zo"]{Compiling to Raw Bytecode}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user