build-system/cmake: Add support for cross compilation.

Fixes <https://bugs.gnu.org/26897>.

* guix/build-system/gnu.scm: Export standard-cross-packages.
* guix/build-system/cmake.scm (cmake-cross-build): New procedure.
(lower): Add support for cross-builds.
* guix/build/cmake-build-system.scm (configure): Handle "target" argument.
master
Ricardo Wurmus 2017-05-25 22:59:00 +02:00
parent 8a9b08b503
commit d2ac5e2975
No known key found for this signature in database
GPG Key ID: 197A5888235FACAC
3 changed files with 151 additions and 17 deletions

View File

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Cyril Roelandt <tipecaml@gmail.com>
;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;
@ -56,24 +57,38 @@
#:rest arguments)
"Return a bag for NAME."
(define private-keywords
'(#:source #:target #:cmake #:inputs #:native-inputs))
`(#:source #:cmake #:inputs #:native-inputs #:outputs
,@(if target '() '(#:target))))
(and (not target) ;XXX: no cross-compilation
(bag
(name name)
(system system)
(host-inputs `(,@(if source
`(("source" ,source))
'())
,@inputs
(bag
(name name)
(system system)
(target target)
(build-inputs `(,@(if source
`(("source" ,source))
'())
,@`(("cmake" ,cmake))
,@native-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)))
(host-inputs inputs)
;; Keep the standard inputs of 'gnu-build-system'.
,@(standard-packages)))
(build-inputs `(("cmake" ,cmake)
,@native-inputs))
(outputs outputs)
(build cmake-build)
(arguments (strip-keyword-arguments private-keywords arguments)))))
;; The cross-libc is really a target package, but for bootstrapping
;; reasons, we can't put it in 'host-inputs'. Namely, 'cross-gcc' is a
;; native package, so it would end up using a "native" variant of
;; 'cross-libc' (built with 'gnu-build'), whereas all the other packages
;; would use a target variant (built with 'gnu-cross-build'.)
(target-inputs (if target
(standard-cross-packages target 'target)
'()))
(outputs outputs)
(build (if target cmake-cross-build cmake-build))
(arguments (strip-keyword-arguments private-keywords arguments))))
(define* (cmake-build store name inputs
#:key (guile #f)
@ -145,6 +160,115 @@ provides a 'CMakeLists.txt' file as its build system."
#:outputs outputs
#:guile-for-build guile-for-build))
;;;
;;; Cross-compilation.
;;;
(define* (cmake-cross-build store name
#:key
target native-drvs target-drvs
(guile #f)
(outputs '("out"))
(configure-flags ''())
(search-paths '())
(native-search-paths '())
(make-flags ''())
(out-of-source? #t)
(build-type "RelWithDebInfo")
(tests? #f) ; nothing can be done
(test-target "test")
(parallel-build? #t) (parallel-tests? #f)
(validate-runpath? #t)
(patch-shebangs? #t)
(strip-binaries? #t)
(strip-flags ''("--strip-debug"
"--enable-deterministic-archives"))
(strip-directories ''("lib" "lib64" "libexec"
"bin" "sbin"))
(phases '(@ (guix build cmake-build-system)
%standard-phases))
(system (%current-system))
(build (nix-system->gnu-triplet system))
(imported-modules %cmake-build-system-modules)
(modules '((guix build cmake-build-system)
(guix build utils))))
"Cross-build NAME using CMAKE for TARGET, where TARGET is a GNU triplet and
with INPUTS. This assumes that SOURCE provides a 'CMakeLists.txt' file as its
build system."
(define builder
`(begin
(use-modules ,@modules)
(let ()
(define %build-host-inputs
',(map (match-lambda
((name (? derivation? drv) sub ...)
`(,name . ,(apply derivation->output-path drv sub)))
((name path)
`(,name . ,path)))
native-drvs))
(define %build-target-inputs
',(map (match-lambda
((name (? derivation? drv) sub ...)
`(,name . ,(apply derivation->output-path drv sub)))
((name (? package? pkg) sub ...)
(let ((drv (package-cross-derivation store pkg
target system)))
`(,name . ,(apply derivation->output-path drv sub))))
((name path)
`(,name . ,path)))
target-drvs))
(cmake-build #:source ,(match (assoc-ref native-drvs "source")
(((? derivation? source))
(derivation->output-path source))
((source)
source)
(source
source))
#:system ,system
#:build ,build
#:target ,target
#:outputs %outputs
#:inputs %build-target-inputs
#:native-inputs %build-host-inputs
#:search-paths ',(map search-path-specification->sexp
search-paths)
#:native-search-paths ',(map
search-path-specification->sexp
native-search-paths)
#:phases ,phases
#:configure-flags ,configure-flags
#:make-flags ,make-flags
#:out-of-source? ,out-of-source?
#:build-type ,build-type
#:tests? ,tests?
#:test-target ,test-target
#:parallel-build? ,parallel-build?
#:parallel-tests? ,parallel-tests?
#:validate-runpath? ,validate-runpath?
#:patch-shebangs? ,patch-shebangs?
#:strip-binaries? ,strip-binaries?
#:strip-flags ,strip-flags
#:strip-directories ,strip-directories))))
(define guile-for-build
(match guile
((? package?)
(package-derivation store guile system #:graft? #f))
(#f ; the default
(let* ((distro (resolve-interface '(gnu packages commencement)))
(guile (module-ref distro 'guile-final)))
(package-derivation store guile system #:graft? #f)))))
(build-expression->derivation store name builder
#:system system
#:inputs (append native-drvs target-drvs)
#:outputs outputs
#:modules imported-modules
#:guile-for-build guile-for-build))
(define cmake-build-system
(build-system
(name 'cmake)

View File

@ -30,6 +30,7 @@
gnu-build
gnu-build-system
standard-packages
standard-cross-packages
package-with-explicit-inputs
package-with-extra-configure-variable
static-libgcc-package

View File

@ -32,7 +32,7 @@
;; Code:
(define* (configure #:key outputs (configure-flags '()) (out-of-source? #t)
build-type
build-type target
#:allow-other-keys)
"Configure the given package."
(let* ((out (assoc-ref outputs "out"))
@ -59,6 +59,15 @@
,(string-append "-DCMAKE_INSTALL_RPATH=" out "/lib")
;; enable verbose output from builds
"-DCMAKE_VERBOSE_MAKEFILE=ON"
;; Cross-build
,@(if target
(list (string-append "-DCMAKE_C_COMPILER="
target "-gcc")
(if (string-contains target "mingw")
"-DCMAKE_SYSTEM_NAME=Windows"
"-DCMAKE_SYSTEM_NAME=Linux"))
'())
,@configure-flags)))
(format #t "running 'cmake' with arguments ~s~%" args)
(zero? (apply system* "cmake" args)))))