raco pkg: support platform-specific package dependencies
A platform-specific dependency is useful for triggering installation of a platform-specific library only on the platform where its needed.
This commit is contained in:
parent
37aa091e1c
commit
b47c1857b5
|
@ -172,7 +172,28 @@
|
||||||
(and (list? dep)
|
(and (list? dep)
|
||||||
(= 2 (length dep))
|
(= 2 (length dep))
|
||||||
(package-source? (car dep))
|
(package-source? (car dep))
|
||||||
(version? (cadr dep))))))
|
(version? (cadr dep)))
|
||||||
|
(and (list? dep)
|
||||||
|
((length dep) . >= . 1)
|
||||||
|
(odd? (length dep))
|
||||||
|
(package-source? (car dep))
|
||||||
|
(let loop ([saw (hash)] [dep (cdr dep)])
|
||||||
|
(cond
|
||||||
|
[(null? dep) #t]
|
||||||
|
[(hash-ref saw (car dep) #f) #f]
|
||||||
|
[else
|
||||||
|
(define kw (car dep))
|
||||||
|
(define val (cadr dep))
|
||||||
|
(and
|
||||||
|
(cond
|
||||||
|
[(eq? kw '#:version) (version? val)]
|
||||||
|
[(eq? kw '#:platform)
|
||||||
|
(or (string? val)
|
||||||
|
(regexp? val)
|
||||||
|
(memq val '(unix windows macosx)))]
|
||||||
|
[else #f])
|
||||||
|
(loop (hash-set saw (car dep) #t)
|
||||||
|
(cddr dep)))]))))))
|
||||||
(pkg-error (~a "invalid `deps' specification\n"
|
(pkg-error (~a "invalid `deps' specification\n"
|
||||||
" specification: ~e")
|
" specification: ~e")
|
||||||
deps)))
|
deps)))
|
||||||
|
@ -187,9 +208,30 @@
|
||||||
(car dep)))
|
(car dep)))
|
||||||
|
|
||||||
(define (dependency->version dep)
|
(define (dependency->version dep)
|
||||||
(if (string? dep)
|
(cond
|
||||||
#f
|
[(string? dep) #f]
|
||||||
(cadr dep)))
|
[(keyword? (cadr dep))
|
||||||
|
(dependency-lookup '#:version dep)]
|
||||||
|
[else (cadr dep)]))
|
||||||
|
|
||||||
|
(define (dependency-lookup kw dep)
|
||||||
|
(cond
|
||||||
|
[(string? dep) #f]
|
||||||
|
[(keyword? (cadr dep))
|
||||||
|
(define p (member kw (cdr dep)))
|
||||||
|
(and p (cadr p))]
|
||||||
|
[else #f]))
|
||||||
|
|
||||||
|
(define (dependency-this-platform? dep)
|
||||||
|
(define p (dependency-lookup '#:platform dep))
|
||||||
|
(if p
|
||||||
|
(if (symbol? p)
|
||||||
|
(eq? p (system-type))
|
||||||
|
(let ([s (path->string (system-library-subpath #f))])
|
||||||
|
(if (regexp? p)
|
||||||
|
(regexp-match? p s)
|
||||||
|
(equal? p s))))
|
||||||
|
#t))
|
||||||
|
|
||||||
(define (with-package-lock* read-only? t)
|
(define (with-package-lock* read-only? t)
|
||||||
(define d (pkg-dir))
|
(define d (pkg-dir))
|
||||||
|
@ -892,6 +934,7 @@
|
||||||
(filter-not (λ (dep)
|
(filter-not (λ (dep)
|
||||||
(define name (dependency->name dep))
|
(define name (dependency->name dep))
|
||||||
(or (equal? name "racket")
|
(or (equal? name "racket")
|
||||||
|
(not (dependency-this-platform? dep))
|
||||||
(hash-ref simultaneous-installs name #f)
|
(hash-ref simultaneous-installs name #f)
|
||||||
(hash-has-key? db name)))
|
(hash-has-key? db name)))
|
||||||
deps)))
|
deps)))
|
||||||
|
@ -948,8 +991,11 @@
|
||||||
(filter-map (λ (dep)
|
(filter-map (λ (dep)
|
||||||
(define name (dependency->name dep))
|
(define name (dependency->name dep))
|
||||||
(define req-vers (dependency->version dep))
|
(define req-vers (dependency->version dep))
|
||||||
|
(define this-platform? (dependency-this-platform? dep))
|
||||||
(define-values (inst-vers* can-try-update?)
|
(define-values (inst-vers* can-try-update?)
|
||||||
(cond
|
(cond
|
||||||
|
[(not this-platform?)
|
||||||
|
(values #f #f)]
|
||||||
[(not req-vers)
|
[(not req-vers)
|
||||||
(values #f #f)]
|
(values #f #f)]
|
||||||
[(equal? name "racket")
|
[(equal? name "racket")
|
||||||
|
@ -964,7 +1010,8 @@
|
||||||
(values (get-metadata metadata-ns (package-directory name)
|
(values (get-metadata metadata-ns (package-directory name)
|
||||||
'version (lambda () "0.0"))
|
'version (lambda () "0.0"))
|
||||||
#t)]))
|
#t)]))
|
||||||
(define inst-vers (if (and req-vers
|
(define inst-vers (if (and this-platform?
|
||||||
|
req-vers
|
||||||
(not (and (string? inst-vers*)
|
(not (and (string? inst-vers*)
|
||||||
(valid-version? inst-vers*))))
|
(valid-version? inst-vers*))))
|
||||||
(begin
|
(begin
|
||||||
|
@ -974,7 +1021,8 @@
|
||||||
inst-vers*)
|
inst-vers*)
|
||||||
"0.0")
|
"0.0")
|
||||||
inst-vers*))
|
inst-vers*))
|
||||||
(and req-vers
|
(and this-platform?
|
||||||
|
req-vers
|
||||||
((version->integer req-vers)
|
((version->integer req-vers)
|
||||||
. > .
|
. > .
|
||||||
(version->integer inst-vers))
|
(version->integer inst-vers))
|
||||||
|
|
|
@ -632,7 +632,15 @@ Package metadata, including dependencies on other packages, is reported
|
||||||
by an @filepath{info.rkt} module within the package. This module must be
|
by an @filepath{info.rkt} module within the package. This module must be
|
||||||
implemented in the @racketmodname[setup/infotab] language.
|
implemented in the @racketmodname[setup/infotab] language.
|
||||||
|
|
||||||
The following fields are used by the package manager:
|
For example, a basic @filepath{info.rkt} file might be
|
||||||
|
|
||||||
|
@codeblock{
|
||||||
|
#lang setup/infotab
|
||||||
|
(define version "1.0")
|
||||||
|
(define deps (list _package-source-string ...))
|
||||||
|
}
|
||||||
|
|
||||||
|
The following @filepath{info.rkt} fields are used by the package manager:
|
||||||
|
|
||||||
@itemlist[
|
@itemlist[
|
||||||
|
|
||||||
|
@ -640,9 +648,42 @@ The following fields are used by the package manager:
|
||||||
@tech{version} of a package is @racket["0.0"].}
|
@tech{version} of a package is @racket["0.0"].}
|
||||||
|
|
||||||
@item{@racketidfont{deps} --- a list of dependencies, where each
|
@item{@racketidfont{deps} --- a list of dependencies, where each
|
||||||
dependency is either a @tech{package source} strings or a list
|
dependency has one of the following forms:
|
||||||
containing a @tech{package source} string and a
|
|
||||||
@tech{version} string.
|
@itemlist[
|
||||||
|
|
||||||
|
@item{A string for a @tech{package source}.}
|
||||||
|
|
||||||
|
@item{A list of the form
|
||||||
|
@racketblock[(list _package-source-string
|
||||||
|
_keyword-and-spec ...)]
|
||||||
|
where each @racket[_keyword-and-spec] has a
|
||||||
|
distinct keyword in the form
|
||||||
|
@racketgrammar*[#:literals (quote)
|
||||||
|
[keyword-and-spec
|
||||||
|
(code:line '#:version version-string)
|
||||||
|
(code:line '#:platform platform-spec)]
|
||||||
|
[platform-spec string symbol regexp]]
|
||||||
|
|
||||||
|
A @racket[_version-string] specifies a lower bound
|
||||||
|
on an acceptable @tech{version} of the needed package.
|
||||||
|
|
||||||
|
A @racket[_platform-spec] indicates that the dependency
|
||||||
|
applies only for platforms with a matching result from
|
||||||
|
@racket[(system-type)] when @racket[_platforms-spec] is
|
||||||
|
a symbol or @racket[(path->string
|
||||||
|
(system-library-subpath #f))] when
|
||||||
|
@racket[_platform-spec] is a regular expression. For
|
||||||
|
example, platform-specific binaries can be placed into
|
||||||
|
their own packages, with one separate package and one
|
||||||
|
dependency for each supported platform.}
|
||||||
|
|
||||||
|
@item{A list of the form
|
||||||
|
@racketblock[(list _package-source-string _version-string)]
|
||||||
|
which is deprecated and equivalent to
|
||||||
|
@racketblock[(list _package-source-string '#:version _version-string)]}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
Each elements of the @racketidfont{deps} list determines a
|
Each elements of the @racketidfont{deps} list determines a
|
||||||
dependency on the @tech{package} whose name is inferred from
|
dependency on the @tech{package} whose name is inferred from
|
||||||
|
@ -651,9 +692,6 @@ The following fields are used by the package manager:
|
||||||
indicates where to get the package if needed to satisfy the
|
indicates where to get the package if needed to satisfy the
|
||||||
dependency.
|
dependency.
|
||||||
|
|
||||||
When provided, a @tech{version} string specifies a lower bound
|
|
||||||
on an acceptable @tech{version} of the package.
|
|
||||||
|
|
||||||
Use the package name @racket["racket"] to specify a dependency
|
Use the package name @racket["racket"] to specify a dependency
|
||||||
on the version of the Racket installation.}
|
on the version of the Racket installation.}
|
||||||
|
|
||||||
|
@ -667,14 +705,6 @@ The following fields are used by the package manager:
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
For example, a basic @filepath{info.rkt} file might be
|
|
||||||
|
|
||||||
@codeblock{
|
|
||||||
#lang setup/infotab
|
|
||||||
(define version "1.0")
|
|
||||||
(define deps (list _package-source-string ...))
|
|
||||||
}
|
|
||||||
|
|
||||||
@; ----------------------------------------
|
@; ----------------------------------------
|
||||||
|
|
||||||
@section{@|Planet1| Compatibility}
|
@section{@|Planet1| Compatibility}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#lang setup/infotab
|
#lang setup/infotab
|
||||||
|
|
||||||
(define deps '(("pkg-v" "2.0")
|
(define deps '(("pkg-v" #:version "2.0")
|
||||||
("racket" "5.3.1.10")))
|
("racket" "5.3.1.10")))
|
||||||
|
|
|
@ -52,5 +52,6 @@
|
||||||
"update-deps"
|
"update-deps"
|
||||||
"update-auto"
|
"update-auto"
|
||||||
"versions"
|
"versions"
|
||||||
|
"platform"
|
||||||
"raco"
|
"raco"
|
||||||
"indexes")
|
"indexes")
|
||||||
|
|
71
collects/tests/pkg/tests-platform.rkt
Normal file
71
collects/tests/pkg/tests-platform.rkt
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#lang racket/base
|
||||||
|
(require rackunit
|
||||||
|
racket/file
|
||||||
|
racket/format
|
||||||
|
pkg/util
|
||||||
|
(prefix-in db: pkg/pnr-db)
|
||||||
|
"shelly.rkt"
|
||||||
|
"util.rkt")
|
||||||
|
|
||||||
|
(pkg-tests
|
||||||
|
(shelly-begin
|
||||||
|
(define pkgs-dir (make-temporary-file "~a-pkgs" 'directory))
|
||||||
|
(define db (build-path pkgs-dir "pnr.sqlite"))
|
||||||
|
(define pkg-x-dir (build-path pkgs-dir "pkg-x"))
|
||||||
|
|
||||||
|
(make-directory* pkg-x-dir)
|
||||||
|
(call-with-output-file*
|
||||||
|
(build-path pkg-x-dir "info.rkt")
|
||||||
|
(lambda (o)
|
||||||
|
(displayln "#lang setup/infotab" o)
|
||||||
|
(write `(define deps '(("pkg-x-windows" #:platform windows)
|
||||||
|
("pkg-x-unix" #:platform unix)
|
||||||
|
("pkg-x-macosx" #:platform macosx)
|
||||||
|
("pkg-x-platform1"
|
||||||
|
#:platform
|
||||||
|
,(path->string (system-library-subpath #f)))
|
||||||
|
("pkg-x-platform2" #:platform #rx".")
|
||||||
|
("pkg-x-platform-no" #:platform #rx"no such platform")))
|
||||||
|
o)))
|
||||||
|
|
||||||
|
(parameterize ([db:current-pkg-index-file db])
|
||||||
|
(db:set-indexes! '("local"))
|
||||||
|
(db:set-pkgs! "local"
|
||||||
|
'("pkg-x" "pkg-x-windows" "pkg-x-unix" "pkg-x-macosx"
|
||||||
|
"pkg-x-platform1" "pkg-x-platform2")))
|
||||||
|
|
||||||
|
(define (create-package name)
|
||||||
|
(define pkg-name name)
|
||||||
|
(define dir (build-path pkgs-dir pkg-name))
|
||||||
|
(make-directory* dir)
|
||||||
|
(define coll-dir (build-path dir name))
|
||||||
|
(make-directory* coll-dir)
|
||||||
|
(call-with-output-file*
|
||||||
|
(build-path coll-dir "main.rkt")
|
||||||
|
(lambda (o)
|
||||||
|
(displayln "#lang racket/base" o)))
|
||||||
|
(parameterize ([db:current-pkg-index-file db])
|
||||||
|
(db:set-pkg! pkg-name "local" "author@place" (path->string dir) "123456" "")))
|
||||||
|
|
||||||
|
(create-package "pkg-x")
|
||||||
|
(create-package "pkg-x-unix")
|
||||||
|
(create-package "pkg-x-windows")
|
||||||
|
(create-package "pkg-x-macosx")
|
||||||
|
(create-package "pkg-x-platform1")
|
||||||
|
(create-package "pkg-x-platform2")
|
||||||
|
|
||||||
|
(with-fake-root
|
||||||
|
(shelly-begin
|
||||||
|
$ (~a "raco pkg config --set indexes file://" (path->string db))
|
||||||
|
$ "racket -e '(require pkg-x)'" =exit> 1
|
||||||
|
$ "raco pkg install --deps search-auto pkg-x" =exit> 0
|
||||||
|
$ "racket -e '(require pkg-x)'" =exit> 0
|
||||||
|
$ (~a "racket -e '(require pkg-x-" (system-type) ")'") =exit> 0
|
||||||
|
$ "racket -e '(require pkg-x-platform1)'" =exit> 0
|
||||||
|
$ "racket -e '(require pkg-x-platform2)'" =exit> 0
|
||||||
|
$ "racket -e '(require pkg-x-platform-no)'" =exit> 1
|
||||||
|
$ "raco pkg remove pkg-x"))
|
||||||
|
|
||||||
|
(delete-directory/files pkgs-dir)))
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,7 @@
|
||||||
(file->string "test-pkgs/pkg-test2.zip.CHECKSUM")
|
(file->string "test-pkgs/pkg-test2.zip.CHECKSUM")
|
||||||
'source
|
'source
|
||||||
"http://localhost:9999/pkg-test2.zip"))
|
"http://localhost:9999/pkg-test2.zip"))
|
||||||
|
|
||||||
(hash-set! *index-ht-2* "pkg-test2-snd"
|
(hash-set! *index-ht-2* "pkg-test2-snd"
|
||||||
(hasheq 'checksum
|
(hasheq 'checksum
|
||||||
(file->string "test-pkgs/pkg-test2.zip.CHECKSUM")
|
(file->string "test-pkgs/pkg-test2.zip.CHECKSUM")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user