summaryrefslogtreecommitdiff
path: root/guix
diff options
context:
space:
mode:
Diffstat (limited to 'guix')
-rw-r--r--guix/build-system/cargo.scm139
-rw-r--r--guix/build/cargo-build-system.scm66
2 files changed, 172 insertions, 33 deletions
diff --git a/guix/build-system/cargo.scm b/guix/build-system/cargo.scm
index 912400a191..c029cc1dda 100644
--- a/guix/build-system/cargo.scm
+++ b/guix/build-system/cargo.scm
@@ -55,12 +55,18 @@
to NAME and VERSION."
(string-append crate-url name "/" version "/download"))
-(define (default-rust)
+(define (default-rust target)
"Return the default Rust package."
;; Lazily resolve the binding to avoid a circular dependency.
(let ((rust (resolve-interface '(gnu packages rust))))
(module-ref rust 'rust)))
+(define (default-rust-sysroot target)
+ "Return the default Rust sysroot for <target>."
+ ;; Lazily resolve the binding to avoid a circular dependency.
+ (let ((module (resolve-interface '(gnu packages rust))))
+ (module-ref module 'make-rust-sysroot)))
+
(define %cargo-utils-modules
;; Build-side modules imported by default.
`((guix build cargo-utils)
@@ -126,6 +132,69 @@ to NAME and VERSION."
#:graft? #f
#:guile-for-build guile))
+(define* (cargo-cross-build name
+ #:key
+ source target
+ build-inputs target-inputs host-inputs
+ (tests? #f)
+ (test-target #f)
+ (vendor-dir "guix-vendor")
+ (cargo-build-flags ''("--release"))
+ (cargo-test-flags ''("--release"))
+ (cargo-package-flags ''("--no-metadata" "--no-verify"))
+ (features ''())
+ (skip-build? #f)
+ (install-source? (not (target-mingw? target)))
+ (phases '%standard-phases)
+ (outputs '("out"))
+ (search-paths '())
+ (native-search-paths '())
+ (system (%current-system))
+ (guile #f)
+ (imported-modules %cargo-build-system-modules)
+ (modules '((guix build cargo-build-system)
+ (guix build utils))))
+ "Cross-build SOURCE using CARGO, and with INPUTS."
+
+ (define builder
+ (with-imported-modules imported-modules
+ #~(begin
+ (use-modules #$@(sexp->gexp modules))
+
+ (cargo-build #:name #$name
+ #:source #+source
+ #:target #+target
+ #:system #$system
+ #:test-target #$test-target
+ #:vendor-dir #$vendor-dir
+ #:cargo-build-flags #$(sexp->gexp cargo-build-flags)
+ #:cargo-test-flags #$(sexp->gexp cargo-test-flags)
+ #:cargo-package-flags #$(sexp->gexp cargo-package-flags)
+ #:features #$(sexp->gexp features)
+ #:skip-build? #$skip-build?
+ #:install-source? #$install-source?
+ #:tests? #$(and tests? (not skip-build?))
+ #:phases #$(if (pair? phases)
+ (sexp->gexp phases)
+ phases)
+ #:outputs #$(outputs->gexp outputs)
+ #:inputs (append #$(input-tuples->gexp host-inputs)
+ #+(input-tuples->gexp target-inputs))
+ #:native-inputs #+(input-tuples->gexp build-inputs)
+ #:make-dynamic-linker-cache? #f ;cross-compiling
+ #:search-paths '#$(sexp->gexp
+ (map search-path-specification->sexp
+ search-paths))
+ #:native-search-paths '#$(sexp->gexp
+ (map search-path-specification->sexp
+ native-search-paths))))))
+
+ (gexp->derivation name builder
+ #:system system
+ #:target target
+ #:graft? #f
+ #:guile-for-build guile))
+
(define (package-cargo-inputs p)
(apply
(lambda* (#:key (cargo-inputs '()) #:allow-other-keys)
@@ -235,7 +304,8 @@ any dependent crates. This can be a benefits:
(define* (lower name
#:key source inputs native-inputs outputs system target
- (rust (default-rust))
+ (rust (default-rust target))
+ (rust-sysroot (default-rust-sysroot target))
(cargo-inputs '())
(cargo-development-inputs '())
#:allow-other-keys
@@ -243,28 +313,49 @@ any dependent crates. This can be a benefits:
"Return a bag for NAME."
(define private-keywords
- '(#:target #:rust #:inputs #:native-inputs #:outputs
- #:cargo-inputs #:cargo-development-inputs))
-
- (and (not target) ;; TODO: support cross-compilation
- (bag
- (name name)
- (system system)
- (target target)
- (host-inputs `(,@(if source
- `(("source" ,source))
- '())
- ,@inputs
-
- ;; Keep the standard inputs of 'gnu-build-system'
- ,@(standard-packages)))
- (build-inputs `(("cargo" ,rust "cargo")
- ("rustc" ,rust)
- ,@(expand-crate-sources cargo-inputs cargo-development-inputs)
- ,@native-inputs))
- (outputs outputs)
- (build cargo-build)
- (arguments (strip-keyword-arguments private-keywords arguments)))))
+ `(#:rust #:inputs #:native-inputs #:outputs
+ #:cargo-inputs #:cargo-development-inputs
+ #:rust-sysroot
+ ,@(if target '() '(#:target))))
+
+ (bag
+ (name name)
+ (system system)
+ (target target)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+
+ ;,@(if target '() inputs)
+ ,@(if target inputs '())
+
+ ,@(expand-crate-sources cargo-inputs cargo-development-inputs)))
+ (build-inputs `(("cargo" ,rust "cargo")
+ ("rustc" ,rust)
+
+ ,@native-inputs
+ ;,@(if target inputs '())
+ ,@(if target '() inputs)
+ ;,@inputs
+
+ ,@(if target
+ ;; Use the standard cross inputs of
+ ;; 'gnu-build-system'.
+ (standard-cross-packages target 'host)
+ '())
+ ;; Keep the standard inputs of 'gnu-build-system'
+ ,@(standard-packages)))
+ (target-inputs `(,@(if target
+ (standard-cross-packages target 'target)
+ '())
+
+ ;; This provides a separate sysroot for the regular rustc
+ ,@(if target
+ `(("rust-sysroot" ,(rust-sysroot target)))
+ '())))
+ (outputs outputs)
+ (build (if target cargo-cross-build cargo-build))
+ (arguments (strip-keyword-arguments private-keywords arguments))))
(define cargo-build-system
(build-system
diff --git a/guix/build/cargo-build-system.scm b/guix/build/cargo-build-system.scm
index 1694ab973c..2e6aeb78be 100644
--- a/guix/build/cargo-build-system.scm
+++ b/guix/build/cargo-build-system.scm
@@ -119,6 +119,7 @@ libraries or executables."
(error "Possible pre-generated files found:" pregenerated-files))))
(define* (configure #:key inputs
+ target
(vendor-dir "guix-vendor")
#:allow-other-keys)
"Vendor Cargo.toml dependencies as guix inputs."
@@ -146,27 +147,74 @@ libraries or executables."
(invoke "tar" "xf" path "-C" crate-dir "--strip-components" "1")))))
inputs)
- ;; Configure cargo to actually use this new directory.
+ ;; For cross-building
+ (when target
+ (setenv "CARGO_BUILD_TARGET"
+ ;; Can this be replaced with platform-rust-architecture?
+ ;; Keep this synchronized with (guix platforms *)
+ (match target
+ ("aarch64-linux-gnu" "aarch64-unknown-linux-gnu")
+ ("arm-linux-gnueabihf" "armv7-unknown-linux-gnueabihf")
+ ("i686-linux-gnu" "i686-unknown-linux-gnu")
+ ("mips64el-linux-gnu" "mips64el-unknown-linux-gnuabi64")
+ ("powerpc-linux-gnu" "powerpc-unknown-linux-gnu")
+ ("powerpc64-linux-gnu" "powerpc64-unknown-linux-gnu")
+ ("powerpc64le-linux-gnu" "powerpc64le-unknown-linux-gnu")
+ ("riscv64-linux-gnu" "riscv64gc-unknown-linux-gnu")
+ ("x86_64-linux-gnu" "x86_64-unknown-linux-gnu")
+ ("i586-pc-gnu" "i686-unknown-hurd-gnu")
+ ("i686-w64-mingw32" "i686-pc-windows-gnu")
+ ("x86_64-w64-mingw32" "x86_64-pc-windows-gnu")
+ (else #f)))
+ (setenv "RUSTFLAGS" (string-append
+ (or (getenv "RUSTFLAGS") "")
+ " --sysroot " (assoc-ref inputs "rust-sysroot")))
+
+ (setenv "PKG_CONFIG" (string-append target "-pkg-config"))
+
+ ;; We've removed all the bundled libraries, don't look for them.
+ (setenv "WINAPI_NO_BUNDLED_LIBRARIES" "1")
+
+ ;; Prevent targeting the build machine.
+ (setenv "CRATE_CC_NO_DEFAULTS" "1"))
+
+ ;; Configure cargo to actually use this new directory with all the crates.
(setenv "CARGO_HOME" (string-append (getcwd) "/.cargo"))
(mkdir-p ".cargo")
- (let ((port (open-file ".cargo/config" "w" #:encoding "utf-8")))
- (display "
+ (let ((port (open-file ".cargo/config.toml" "w" #:encoding "utf-8")))
+ ;; Placed here so it doesn't cause random rebuilds. Neither of these work.
+ ;; sysroot = '" (assoc-ref inputs "rust-sysroot") "'
+ ;; rustflags = ['--sysroot', '" (assoc-ref inputs "rust-sysroot") "']
+ (when target
+ (display (string-append "
+[target." (getenv "CARGO_BUILD_TARGET") "]
+linker = '" target "-gcc'
+
+[build]
+target = ['" (getenv "CARGO_BUILD_TARGET") "']") port))
+ (display (string-append "
[source.crates-io]
replace-with = 'vendored-sources'
[source.vendored-sources]
-directory = '" port)
- (display (string-append (getcwd) "/" vendor-dir) port)
- (display "'
-" port)
+directory = '" vendor-dir "'") port)
(close-port port))
;; Lift restriction on any lints: a crate author may have decided to opt
;; into stricter lints (e.g. #![deny(warnings)]) during their own builds
;; but we don't want any build failures that could be caused later by
;; upgrading the compiler for example.
- (setenv "RUSTFLAGS" "--cap-lints allow")
- (setenv "CC" (string-append (assoc-ref inputs "gcc") "/bin/gcc"))
+ (setenv "RUSTFLAGS" (string-append (or (getenv "RUSTFLAGS") "")
+ " --cap-lints allow"))
+
+ (if (assoc-ref inputs "cross-gcc")
+ (begin
+ (setenv "HOST_CC" "gcc")
+ (setenv "TARGET_CC" (string-append target "-gcc"))
+ (setenv "TARGET_AR" (string-append target "-ar"))
+ (setenv "TARGET_PKG_CONFIG" (string-append target "-pkg-config")))
+ (setenv "CC" (string-append (assoc-ref inputs "gcc") "/bin/gcc")))
+
(setenv "LIBGIT2_SYS_USE_PKG_CONFIG" "1")
(setenv "LIBSSH2_SYS_USE_PKG_CONFIG" "1")
(when (assoc-ref inputs "openssl")