diff options
-rw-r--r-- | guix/build-system/cargo.scm | 139 | ||||
-rw-r--r-- | guix/build/cargo-build-system.scm | 66 |
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") |