diff --git a/pkgs/racket-doc/scribblings/raco/make.scrbl b/pkgs/racket-doc/scribblings/raco/make.scrbl index c979104ca9..5c0c895b90 100644 --- a/pkgs/racket-doc/scribblings/raco/make.scrbl +++ b/pkgs/racket-doc/scribblings/raco/make.scrbl @@ -550,25 +550,36 @@ field is a @racket[compile-event] as document in @defmodule[compiler/cm-accomplice] -@defproc[(register-external-file [file (and path? complete-path?)]) void?]{ +@defproc[(register-external-file [file (and path? complete-path?)] + [#:indirect? indirect? any/c #f]) + void?]{ -Logs a message (see @racket[log-message]) at level @racket['info] to -a logger named @racket['cm-accomplice]. The -message data is a @racketidfont{file-dependency} prefab structure type -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). +Logs a message (see @racket[log-message]) at level @racket['info] to a +logger named @racket['cm-accomplice]. The message data is a +@racketidfont{file-dependency} prefab structure type 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). If the +@racket[indirect?] argument is true, the data is more specifically an +instance of a @racketidfont{file-dependency/indirect} prefab structure +type that is a subtype of @racketidfont{file-dependency} with no new +fields. A compilation manager implemented by @racketmodname[compiler/cm] looks -for such messages to register an external dependency. The compilation -manager records (in a @filepath{.dep} file) the path as contributing -to the implementation of the module currently being +for such messages to register an external dependency. In response, the +compilation manager records (in a @filepath{.dep} file) the path as +contributing to the implementation of the module currently being compiled. Afterward, if the registered file is modified, the -compilation manager will know to recompile the module. +compilation manager will know to recompile the module. An ``indirect'' +dependency has no effect on recompilation, but it can signal to other +tools, such as a package-dependency checker, that the dependency is +indirect (and should not imply a direct package dependency). The @racket[include] macro, for example, calls this procedure with the path of an included file as it expands an @racket[include] form.} -@defproc[(register-external-module [file (and path? complete-path?)]) void?]{ +@defproc[(register-external-module [file (and path? complete-path?)] + [#:indirect? indirect? any/c #f]) + void?]{ Like @racket[register-external-file], but logs a message with a @racketidfont{file-dependency} prefab structure type whose second diff --git a/pkgs/racket-doc/scribblings/reference/syntax.scrbl b/pkgs/racket-doc/scribblings/reference/syntax.scrbl index b008cdb8bb..1838aa3d70 100644 --- a/pkgs/racket-doc/scribblings/reference/syntax.scrbl +++ b/pkgs/racket-doc/scribblings/reference/syntax.scrbl @@ -3005,10 +3005,10 @@ submodule). Introduced submodules have the names @racket[lazy-require-]@racket[_n]@racketidfont{-}@racket[_m], where @racket[_n] is a phase-level number and @racket[_m] is a number. -When the use of a lazily-required function triggers module loading, -@racket[register-external-module] declares a potential compilation -dependency (in case the function is used in the process of compiling a -module). +When the use of a lazily-required function triggers module loading, it +also triggers a use of @racket[register-external-module] to declare an +indirect compilation dependency (in case the function is used in the +process of compiling a module). @examples[#:eval lazy-require-eval (lazy-require diff --git a/racket/collects/compiler/cm-accomplice.rkt b/racket/collects/compiler/cm-accomplice.rkt index f7a8eb03a9..4278472059 100644 --- a/racket/collects/compiler/cm-accomplice.rkt +++ b/racket/collects/compiler/cm-accomplice.rkt @@ -3,16 +3,18 @@ (provide register-external-file register-external-module) -(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-file f #:indirect? [indirect? #f]) + (register-external 'register-external-file f #f indirect?)) +(define (register-external-module f #:indirect? [indirect? #f]) + (register-external 'register-external-module f #t indirect?)) -(define (register-external who f module?) +(define (register-external who f module? indirect?) (unless (and (path? f) (complete-path? f)) (raise-type-error who "complete path" f)) (log-message (current-logger) 'info 'cm-accomplice (format "file dependency: ~s" f) - `#s(file-dependency ,f ,module?))) + (if indirect? + `#s((file-dependency/indirect file-dependency 2) ,f ,module?) + `#s(file-dependency ,f ,module?)))) diff --git a/racket/collects/compiler/cm.rkt b/racket/collects/compiler/cm.rkt index 7f8f9595be..3139bf52fb 100644 --- a/racket/collects/compiler/cm.rkt +++ b/racket/collects/compiler/cm.rkt @@ -231,9 +231,13 @@ (define (get-dep-sha1s deps up-to-date collection-cache read-src-syntax mode roots must-exist? seen) (let ([l (for/fold ([l null]) ([dep (in-list deps)]) (and l + ;; (cons 'indirect dep) => indirect dependency (for pkg-dep checking) ;; (cons 'ext rel-path) => a non-module file, check source ;; rel-path => a module file name, check cache - (let* ([ext? (and (pair? dep) (eq? 'ext (car dep)))] + (let* ([dep (if (and (pair? dep) (eq? 'indirect (car dep))) + (cdr dep) + dep)] + [ext? (and (pair? dep) (eq? 'ext (car dep)))] [p (collects-relative*->path (if ext? (cdr dep) dep) collection-cache)]) (cond [ext? (let ([v (get-source-sha1 p)]) @@ -273,19 +277,26 @@ external-module-deps ; can create cycles if misused! reader-deps))] [external-deps (remove-duplicates external-deps)]) + (define (path*->collects-relative/maybe-indirect dep) + (if (and (pair? dep) (eq? 'indirect (car dep))) + (cons 'indirect (path*->collects-relative (cdr dep))) + (path*->collects-relative dep))) (with-compile-output dep-path (lambda (op tmp-path) (let ([deps (append - (map path*->collects-relative deps) + (map path*->collects-relative/maybe-indirect deps) (map (lambda (x) - (cons 'ext (path*->collects-relative x))) + (define d (path*->collects-relative/maybe-indirect x)) + (if (and (pair? d) (eq? 'indirect d)) + (cons 'indirect (cons 'ext (cdr d))) + (cons 'ext d))) external-deps))]) - (write (list* (version) - (cons (or src-sha1 (get-source-sha1 path)) - (get-dep-sha1s deps up-to-date collection-cache read-src-syntax mode roots #t #hash())) - deps) - op) - (newline op)))))) + (write (list* (version) + (cons (or src-sha1 (get-source-sha1 path)) + (get-dep-sha1s deps up-to-date collection-cache read-src-syntax mode roots #t #hash())) + deps) + op) + (newline op)))))) (define (format-time sec) (let ([d (seconds->date sec)]) @@ -311,6 +322,7 @@ (define-struct ext-reader-guard (proc top) #:property prop:procedure (struct-field-index proc)) (define-struct file-dependency (path module?) #:prefab) +(define-struct (file-dependency/indirect file-dependency) () #:prefab) (define (compile-zo* mode roots path src-sha1 read-src-syntax zo-name up-to-date collection-cache) ;; The `path' argument has been converted to .rkt or .ss form, @@ -322,10 +334,14 @@ (define reader-deps null) (define deps-sema (make-semaphore 1)) (define done-key (gensym)) - (define (external-dep! p module?) + (define (external-dep! p module? indirect?) + (define bstr (path->bytes p)) + (define dep (if indirect? + (cons 'indirect bstr) + bstr)) (if module? - (set! external-module-deps (cons (path->bytes p) external-module-deps)) - (set! external-deps (cons (path->bytes p) external-deps)))) + (set! external-module-deps (cons dep external-module-deps)) + (set! external-deps (cons dep external-deps)))) (define (reader-dep! p) (call-with-semaphore deps-sema @@ -386,7 +402,8 @@ (file-dependency? (vector-ref l 2)) (path? (file-dependency-path (vector-ref l 2)))) (external-dep! (file-dependency-path (vector-ref l 2)) - (file-dependency-module? (vector-ref l 2)))) + (file-dependency-module? (vector-ref l 2)) + (file-dependency/indirect? (vector-ref l 2)))) (loop)))) ;; Write the code and dependencies: @@ -627,9 +644,13 @@ ;; 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 collection-cache new-seen)] [(ormap - (lambda (p) + (lambda (raw-p) + ;; (cons 'indirect dep) => indirect dependency (for pkg-dep checking) ;; (cons 'ext rel-path) => a non-module file (check date) ;; rel-path => a module file name (check transitive dates) + (define p (if (and (pair? raw-p) (eq? 'indirect (car raw-p))) + (cdr raw-p) + raw-p)) (define ext? (and (pair? p) (eq? 'ext (car p)))) (define d (collects-relative*->path (if ext? (cdr p) p) collection-cache)) (define t diff --git a/racket/collects/racket/lazy-require.rkt b/racket/collects/racket/lazy-require.rkt index 5530d0c170..7b86cfd64d 100644 --- a/racket/collects/racket/lazy-require.rkt +++ b/racket/collects/racket/lazy-require.rkt @@ -110,4 +110,4 @@ modpath (variable-reference->resolved-module-path vr))))]) (when (path? path) - (register-external-module path)))) + (register-external-module path #:indirect? #t)))) diff --git a/racket/collects/setup/private/pkg-deps.rkt b/racket/collects/setup/private/pkg-deps.rkt index d22000b699..5455ded1bf 100644 --- a/racket/collects/setup/private/pkg-deps.rkt +++ b/racket/collects/setup/private/pkg-deps.rkt @@ -489,6 +489,7 @@ ;; Treat everything in ".dep" as 'build mode... (define deps (cddr (call-with-input-file* (build-path dir f) read))) (for ([dep (in-list deps)]) + ;; Note: indirect dependencies (which start with 'indirect) are ignored (when (and (pair? dep) (eq? 'collects (car dep))) (define path-strs (map bytes->string/utf-8 (cdr dep)))