579 lines
29 KiB
Scheme
579 lines
29 KiB
Scheme
;;; GNU Guix --- Functional package management for GNU
|
||
;;;
|
||
;;; Copyright © 2023 Stefan <stefan-guix@vodafonemail.de>
|
||
;;;
|
||
;;; This file is not part of GNU Guix.
|
||
;;;
|
||
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||
;;; under the terms of the GNU General Public License as published by
|
||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||
;;; your option) any later version.
|
||
;;;
|
||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
;;; GNU General Public License for more details.
|
||
;;;
|
||
;;; You should have received a copy of the GNU General Public License
|
||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
(define-module (embedded)
|
||
#:use-module (guix build-system)
|
||
#:use-module (guix build-system gnu)
|
||
#:use-module (guix build-system trivial)
|
||
#:use-module (guix build gnu-build-system)
|
||
#:use-module ((guix build utils) #:select (alist-replace
|
||
modify-phases))
|
||
#:use-module (guix download)
|
||
#:use-module (guix gexp)
|
||
#:use-module ((guix licenses) #:prefix license:)
|
||
#:use-module (guix packages)
|
||
#:use-module (guix utils)
|
||
#:use-module (gnu packages)
|
||
#:use-module (gnu packages autotools)
|
||
#:use-module (gnu packages base)
|
||
#:use-module ((gnu packages bootstrap) #:select (glibc-dynamic-linker))
|
||
#:use-module (gnu packages commencement)
|
||
#:use-module (gnu packages compression)
|
||
#:use-module (gnu packages cross-base)
|
||
#:use-module (gnu packages flex)
|
||
#:use-module (gnu packages gcc)
|
||
#:use-module (gnu packages gdb)
|
||
#:use-module (gnu packages multiprecision)
|
||
#:use-module (gnu packages pkg-config)
|
||
#:use-module (gnu packages texinfo)
|
||
#:use-module (ice-9 optargs)
|
||
#:use-module (srfi srfi-1))
|
||
|
||
(define-public (gcc-phase-fix-environment)
|
||
"Give a build-phase for the GCC compilation to fix environment variables."
|
||
#~(lambda* (#:key inputs #:allow-other-keys)
|
||
(use-modules (srfi srfi-1))
|
||
(setenv
|
||
"LD_LIBRARY_PATH"
|
||
;; The built gcc will have a workaround to ensure that glibc will always
|
||
;; find libgcc_s.so. Unfortunately during the configuration of libatomic
|
||
;; and other libraries, the libgcc_s.so is not yet available in its final
|
||
;; installation directory and this workaround causes trouble to the
|
||
;; configure script during "checking whether we are cross compiling". As
|
||
;; a mitigation we set LD_LIBRARY_PATH to the location of the not yet
|
||
;; installed libgcc_s.so. This would not be necessary, if glibc had a
|
||
;; reference to the gcc used to build it.
|
||
(string-append (getcwd) "/build/gcc"))
|
||
(format #t "environment variable `LD_LIBRARY_PATH' set to `~a'~%"
|
||
(getenv "LD_LIBRARY_PATH"))
|
||
(when (getenv "CPLUS_INCLUDE_PATH")
|
||
(let* ((libc (assoc-ref inputs "libc"))
|
||
(gcc (assoc-ref inputs "gcc")) ; This is different to #$gcc!
|
||
(paths-to-delete
|
||
(map (lambda (package) (string-append package "/include"))
|
||
(filter-map identity (list libc gcc)))))
|
||
(setenv
|
||
"CPLUS_INCLUDE_PATH"
|
||
;; The gcc package used by the gnu-build-system to build this gcc
|
||
;; puts the include paths to the C++ headers and to the libc headers
|
||
;; into CPLUS_INCLUDE_PATH. This causes trouble in the gcc build
|
||
;; process when -nostdinc++ is used. As a mitigation we remove them.
|
||
;; This would not be necessary, when using this built gcc instead.
|
||
(string-join
|
||
(remove (lambda (path) (member path paths-to-delete))
|
||
(string-split (getenv "CPLUS_INCLUDE_PATH") #\:))
|
||
":"))
|
||
(format #t "environment variable `CPLUS_INCLUDE_PATH' set to `~a'~%"
|
||
(getenv "CPLUS_INCLUDE_PATH"))))))
|
||
|
||
(define*-public (gcc-phase-pre-configure
|
||
#:key
|
||
(libc glibc)
|
||
(dynamic-linker (glibc-dynamic-linker))
|
||
(startfile-dir "/lib/"))
|
||
"Give a build-phase for the GCC compilation to modify the source-code. Use
|
||
the LIBC package for embedded search-paths. The path DYNAMIC-LINKER is appended
|
||
to LIBC to form the absolute path to the dynamic-linker. The STRTFILE-DIR is a
|
||
suffix for LIBC to form the path to startfiles like crt0.o from newlib. All
|
||
default values match for glibc. For newlib omit DYNAMIC-LINKER and set
|
||
STARTFILE-DIR to (string-append \"/\" target \"/lib/\")."
|
||
#~(lambda _
|
||
(substitute* "Makefile.in"
|
||
;; Don't store configure arguments, to avoid retaining references to
|
||
;; build-time dependencies like "--with-…=/gnu/store/…".
|
||
(("@TOPLEVEL_CONFIGURE_ARGUMENTS@") ""))
|
||
(substitute* (find-files "gcc/config")
|
||
;; Enforce any /lib64 directory to just be /lib.
|
||
(("/lib64") "/lib"))
|
||
(when #$dynamic-linker
|
||
(substitute* (find-files "gcc/config" "^.+\\.h$" #:directories? #t)
|
||
;; Enforce anything looking like some /lib/ld.so.2 to be the linker.
|
||
(("[^ :;\"{]+/ld.*[_.]so(\\.[0-9]+)?")
|
||
(string-append #$libc #$dynamic-linker))))
|
||
(substitute* "gcc/configure"
|
||
;; Prevent auto-host.h in output:lib to create a cyclic dependency
|
||
;; referencing output:out.
|
||
(("PREFIX_INCLUDE_DIR \"\\$prefix/include\"")
|
||
"PREFIX_INCLUDE_DIR \"$libdir/include\""))
|
||
(substitute* "gcc/genmultilib"
|
||
;; Enforce proper invokations of sh.
|
||
(("#!/bin/sh") (string-append "#!" (which "sh"))))
|
||
(substitute* "gcc/gcc.cc"
|
||
;; The STARTFILE_PREFIX_SPEC defines where to find crt1.o and other
|
||
;; start files of libc. Replace it with a proper path to the libc.
|
||
;; Note: This path is relative to the sysroot which therefore must be /.
|
||
(("startfile_prefix_spec = STARTFILE_PREFIX_SPEC;")
|
||
(string-append "startfile_prefix_spec = \""
|
||
#$libc #$startfile-dir "\";")))
|
||
(substitute* "libstdc++-v3/python/Makefile.in"
|
||
;; Change pythondir from #$output:out to #$output:lib to prevent
|
||
;; #$output:lib/lib/libstdc++.so.*-gdb.py to create a cyclic dependency
|
||
;; to #$output:out/share/…/python. This moves all python files to
|
||
;; #$output:lib. The option --with-python-dir is still usable.
|
||
(("pythondir = \\$\\(datadir\\)") "pythondir = $(libdir)/share")
|
||
(("pythondir = \\$\\(prefix\\)") "pythondir = $(libdir)"))
|
||
#!(substitute* "libsanitizer/asan/asan_linux.cpp"
|
||
;; Ensure PATH_MAX is defined by including the proper header file.
|
||
;; https://gcc.gnu.org/bugzilla//show_bug.cgi?id=99476
|
||
;; https://gcc.gnu.org/bugzilla//show_bug.cgi?id=106998
|
||
;; The gcc package used by the gnu-build-system is to blame here. This
|
||
;; patch is unnecessary when not using --disable-bootstrap.
|
||
(("#include <limits\\.h>")
|
||
#$(string-join (list "#include <limits.h>"
|
||
"#if SANITIZER_LINUX"
|
||
"#include <linux/limits.h>"
|
||
"#endif")
|
||
"\n")))!#))
|
||
|
||
(define*-public (gcc-configure-flags
|
||
#:key
|
||
(libc glibc)
|
||
(kernel-headers
|
||
(car (assoc-ref (package-propagated-inputs glibc)
|
||
"kernel-headers"))))
|
||
"Give the configure-flags for the GCC compilation referring to the LIBC and
|
||
KERNEL-HEADERS packages. The defaults refer to glibc and the kernel-headers
|
||
used to build glibc."
|
||
#~(list
|
||
;; The first set of include paths consinsts of #$gcc/include-c++/… and
|
||
;; #$gcc:lib/…/include. Second is usually /usr/local, which we replace
|
||
;; with the empty #$output:lib/include path.
|
||
(string-append "--with-local-prefix=" #$output:lib)
|
||
;; Third is #$gcc:lib/…/include-fixed, which expects #$libc/include and
|
||
;; #$kernel-headers/include to follow in this order.
|
||
;; Fourth and usually the last include path is /usr/include containing all
|
||
;; system headers. It is only possible to specify one path for this. Set
|
||
;; the #$libc/include path and prevent the use of /usr/include.
|
||
(string-append "--with-native-system-header-dir=" #$libc "/include")
|
||
;; The final include path has to be #$kernel-headers/include, which has to
|
||
;; be after #$libc/include. There is only -idirafter left to achieve
|
||
;; this. Add #$output:lib/lib as a built-in link-time search path.
|
||
;; Add #$libc/lib and #$libc/static as built-in link-time search paths.
|
||
;; Add a runtime search path to #$libc/lib, if not linked statically.
|
||
;; This search path to #$libc/lib may not be technically necessary because
|
||
;; of the dynamic linker in there, but better use a complete list.
|
||
;; Actually libc needs a DT_RUNPATH entry to the libgcc_s.so of the GCC
|
||
;; used to build it. This is missing and may requires a fix. As a
|
||
;; workaround one can force any program built by this GCC and not linked
|
||
;; statically to load libgcc_s.so by embedding the -lgcc_s option and
|
||
;; adding a runtime search path to libgcc_s.so as well.
|
||
(string-append
|
||
"--with-specs="
|
||
;; Embed the path to the kernel-headers.
|
||
"-idirafter " #$kernel-headers "/include "
|
||
;; Embed the link-time search path to libgcc_s.so, libstdc++.so, etc.
|
||
"%x{-L" #$output:lib "/lib} "
|
||
;; Embed the link-time search paths to #$libc/lib and #$libc:static/lib.
|
||
"%x{-L" #$libc "/lib} %x{-L" #$libc:static "/lib} "
|
||
;; Embed the runtime search path to #$libc/lib, if not staticlally
|
||
;; linked.
|
||
"%{nolibc|nostdlib|static:; :%x{-rpath=" #$libc "/lib}} "
|
||
;; This is a workaround to ensure a pre-loaded libgcc_s.so for libc if
|
||
;; not statically linking. The libstdc++.so and other shared libraries
|
||
;; are statically linked but use the option -lgcc_s. Unfortunately it
|
||
;; seems to be impossible to check for the presence of -lgcc_s. Adding
|
||
;; the -rpath option conditionally, if not linking statically, has the
|
||
;; risk to not add it although needed. Adding it unconditionally may add
|
||
;; it needlessly, which prevents building the dynamic linker of libc,
|
||
;; but makes the make-flags #~(list "LDFLAGS=-Wl,-rpath=$(libdir)/lib")
|
||
;; obsolete. As a GCC referencing the dynamic linker cannot be used to
|
||
;; build it, the -rpath is added unconditionally here.
|
||
"%{nodefaultlibs|nostdlib|static|static-libgcc|static-pie:; "
|
||
":%x{-lgcc_s}} %x{-rpath=" #$output:lib "/lib}")
|
||
;; Prevent the C++ headers in #$output:lib, put them in #$output:out
|
||
;; instead. Use an unconventional path to prevent it from being added to
|
||
;; the environment variables C_INCLUDE_PATH and CPLUS_INCLUDE_PATH.
|
||
"--with-gxx-include-dir=$(prefix)/include-c++"
|
||
;; As libc is limited, gcc will not be usable for 32 and 64 bit builds.
|
||
"--disable-multilib"
|
||
;; Disable all language frontends except for C and C++.
|
||
"--enable-languages=c,c++"
|
||
;; Save space by disabling pre-compiled libstdc++ headers.
|
||
"--disable-libstdcxx-pch"
|
||
;; Use the zlib package instead of the zlib bundled with gcc.
|
||
"--with-system-zlib"
|
||
;; Avoid parallel linking to not crash on systems with limited memory.
|
||
"--enable-link-serialization"
|
||
;; Prevent the built gcc to build itself again to save time.
|
||
#!"--disable-bootstrap"!#))
|
||
|
||
(define-public (make-gcc12 phase-pre-configure configure-flags)
|
||
"Make a GCC package using the PHASE-PRE-CONFIGURE and the CONFIGURE-FLAGS in
|
||
the build-process."
|
||
(package
|
||
(name "gcc12")
|
||
(version "12.2.0")
|
||
(source (origin
|
||
(method url-fetch)
|
||
(uri (string-append "mirror://gnu/gcc/gcc-"
|
||
version "/gcc-" version ".tar.xz"))
|
||
(sha256
|
||
(base32 "1zrhca90c7hqnjz3jgr1vl675q3h5lrd92b5ggi00jjryffcyjg5"))
|
||
(patches
|
||
(search-patches "gcc-12-strmov-store-file-names.patch"))))
|
||
(build-system gnu-build-system)
|
||
(outputs '("out" "lib" "debug"))
|
||
(inputs (list gmp mpfr mpc isl zstd zlib))
|
||
(arguments
|
||
(list #:tests? #f
|
||
#:out-of-source? #t
|
||
#:configure-flags configure-flags
|
||
#:phases
|
||
#~(modify-phases %standard-phases
|
||
(add-after 'set-paths 'fix-environment
|
||
#$(gcc-phase-fix-environment))
|
||
(add-before 'configure 'pre-configure
|
||
#$phase-pre-configure))))
|
||
(native-search-paths
|
||
(list (search-path-specification (variable "CPLUS_INCLUDE_PATH")
|
||
(files (list "include")))
|
||
(search-path-specification (variable "C_INCLUDE_PATH")
|
||
(files (list "include")))
|
||
(search-path-specification (variable "LIBRARY_PATH")
|
||
(files (list "lib")))))
|
||
(synopsis "GNU Compiler Collection")
|
||
(description
|
||
"GCC is the GNU Compiler Collection. It provides compiler front-ends for
|
||
several languages, including C, C++, Objective-C, Fortran, Java, Ada, and
|
||
Go. It also includes runtime support libraries for these languages.")
|
||
(home-page "https://gcc.gnu.org/")
|
||
(license license:gpl3+)))
|
||
|
||
(define-public gcc12
|
||
(make-gcc12 (gcc-phase-pre-configure) (gcc-configure-flags)))
|
||
|
||
(define-public guix-locpath
|
||
(package
|
||
(name "guix-locpath")
|
||
(version "1.0")
|
||
(source #f)
|
||
(build-system trivial-build-system)
|
||
(arguments (list #:builder #~(mkdir #$output)))
|
||
(native-search-paths
|
||
(list (search-path-specification (variable "GUIX_LOCPATH")
|
||
(files '("lib/locale")))))
|
||
(home-page #f)
|
||
(synopsis "Access for glibc to locales")
|
||
(description "The guix-locpath package sets the environment variable
|
||
GUIX_LOCPATH to make all locale related functions of glibc usable without
|
||
propagating glibc itself. This is usefull to prevent glibc include paths to be
|
||
exposed via C_INCLUDE_PATH and similar environment variables, to keep a defined
|
||
include order with embedded paths in GCC to glibc.")
|
||
(license (package-license glibc-utf8-locales))))
|
||
|
||
(define*-public (make-c-toolchain gcc binutils #:optional ld-wrapper)
|
||
"Make a C-toolchain consisting of GCC, BINUTILS, guix-locpath and
|
||
optionally LD-WRAPPER packages. The result can be used by the transformation
|
||
function 'package-with-c-toolchain' and to build a GCC-toolchain package with
|
||
'make-gcc-toolchain-package'.
|
||
|
||
The guix-locpath package is used instead of the glibc package to prevent glibc
|
||
and the kernel-headers from appearing in the C_INCLUDE_PATH, CPLUS_INCLUDE_PATH,
|
||
and similar environment variables. The GCC package is expected to have the
|
||
necessary paths build-in to preserve a necessary include-order."
|
||
(let ((build-inputs (list (list "guix-locpath" guix-locpath)
|
||
(list "gcc" gcc)
|
||
(list "binutils" binutils))))
|
||
(if ld-wrapper
|
||
;; The ld-wrapper has to be in front of binutils.
|
||
(cons (list "ld-wrapper" ld-wrapper) build-inputs)
|
||
build-inputs)))
|
||
|
||
(define*-public (make-gcc-toolchain-package c-toolchain)
|
||
"Make a GCC-toolchain package from C-TOOLCHAIN. The C-TOOLCHAIN argument must
|
||
be a list of inputs (label/package tuples) providing equivalent functionality as
|
||
the 'gcc-toolchain' package as passed to 'package-with-c-toolchain'."
|
||
(let ((gcc (car (assoc-ref c-toolchain "gcc"))))
|
||
(package
|
||
(name (string-append (package-name gcc) "-toolchain"))
|
||
(version (package-version gcc))
|
||
(source #f)
|
||
(build-system trivial-build-system)
|
||
(arguments
|
||
(list
|
||
#:modules '((guix build union))
|
||
#:builder
|
||
#~(begin
|
||
(use-modules ((guix build union)))
|
||
(union-build #$output (quote #$(map second c-toolchain))))))
|
||
(synopsis "Complete GCC toolchain for C/C++ development")
|
||
(description "This package provides a complete GCC toolchain for C/C++
|
||
development to be installed in user profiles. This includes GCC and Binutils.
|
||
GCC is the GNU Compiler Collection.")
|
||
(home-page "https://gcc.gnu.org/")
|
||
(license license:gpl3+))))
|
||
|
||
(define-public gcc12-c-toolchain
|
||
(make-c-toolchain gcc12 binutils ld-wrapper))
|
||
|
||
(define-public gcc12-toolchain
|
||
(make-gcc-toolchain-package gcc12-c-toolchain))
|
||
|
||
(define*-public (make-newlib-4.3 target
|
||
#:key
|
||
(configure-flags
|
||
'("--disable-newlib-supplied-syscalls"
|
||
"--enable-newlib-io-long-long"
|
||
"--enable-newlib-io-c99-formats"
|
||
"--enable-newlib-mb"
|
||
"--enable-newlib-reent-check-verify"
|
||
"--enable-newlib-register-fini"
|
||
"--enable-newlib-retargetable-locking"
|
||
"--disable-dependency-tracking"))
|
||
(cross-gcc (cross-gcc target))
|
||
(cross-binutils (cross-binutils target)))
|
||
"Make a newlib package for TARGET with the given CONFIGURE-FLAGS, CROSS-GCC
|
||
and CROSS-BINUTLIS packages for building."
|
||
(package
|
||
(name (string-append "newlib-" target))
|
||
(version "4.3.0")
|
||
(source
|
||
(origin
|
||
(method url-fetch)
|
||
(uri "ftp://sourceware.org/pub/newlib/newlib-4.3.0.20230120.tar.gz")
|
||
(sha256
|
||
(base32 "0l2iycz12m9r8czc08isykzh1mr4xs9d13n5n2wqxqsrmycjm9l3"))))
|
||
(build-system gnu-build-system)
|
||
(arguments
|
||
(list #:out-of-source? #t
|
||
;; The configure-flags are taken from newlib_configure found in:
|
||
;; https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.2.mpacbti-bet1/manifest/arm-gnu-toolchain-arm-none-eabi-abe-manifest.txt
|
||
;; Got that link in section "Linaro ABE example manifest files for
|
||
;; Linux hosted cross toolchains" form:
|
||
;; https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
|
||
#:configure-flags
|
||
#~(quote #$(cons (string-append "--target=" target)
|
||
configure-flags))
|
||
#:phases
|
||
#~(modify-phases %standard-phases
|
||
;; TODO: Remove nano related files after installation.
|
||
(add-after 'unpack 'fix-references-to-/bin/sh
|
||
(lambda _
|
||
(substitute* (find-files "libgloss" "^Makefile\\.in$")
|
||
;; There are plenty Makefile.in below libgloss which
|
||
;; reference /bin/sh. These must be fixed.
|
||
(("/bin/sh") (which "sh"))))))))
|
||
(native-inputs (list cross-gcc cross-binutils texinfo))
|
||
(home-page "https://www.sourceware.org/newlib/")
|
||
(synopsis "C library for use on embedded systems")
|
||
(description "Newlib is a C library intended for use on embedded
|
||
systems. It is a conglomeration of several library parts that are easily
|
||
usable on embedded products.")
|
||
(license (license:non-copyleft
|
||
"https://www.sourceware.org/newlib/COPYING.NEWLIB"))))
|
||
|
||
(define*-public (make-newlib-nano-4.3 target
|
||
#:key
|
||
(cross-gcc (cross-gcc target))
|
||
(cross-binutils (cross-binutils target)))
|
||
"Make a newlib-nano package for TARGET with the given CROSS-GCC and
|
||
CROSS-BINUTLIS packages for building."
|
||
(package
|
||
(inherit (make-newlib-4.3 target
|
||
#:configure-flags
|
||
'("--disable-newlib-fseek-optimization"
|
||
"--disable-newlib-fvwrite-in-streamio"
|
||
"--disable-newlib-supplied-syscalls"
|
||
"--disable-newlib-unbuf-stream-opt"
|
||
"--disable-newlib-wide-orient"
|
||
"--enable-lite-exit"
|
||
"--enable-newlib-global-atexit"
|
||
"--enable-newlib-nano-formatted-io"
|
||
"--enable-newlib-nano-malloc"
|
||
"--enable-newlib-reent-check-verify"
|
||
"--enable-newlib-reent-small"
|
||
"--enable-newlib-retargetable-locking"
|
||
"--disable-dependency-tracking")
|
||
#:cross-gcc cross-gcc
|
||
#:cross-binutils cross-binutils))
|
||
(name (string-append "newlib-nano-" target))
|
||
;; TODO: Add nano suffix to installed files, keep nano related files.
|
||
(synopsis "C library for use on embedded systems with limited memory")))
|
||
|
||
(define-public newlib-arm-none-eabi-4.3
|
||
(make-newlib-4.3 "arm-none-eabi"))
|
||
|
||
(define-public newlib-nano-arm-none-eabi-4.3
|
||
(make-newlib-nano-4.3 "arm-none-eabi"))
|
||
|
||
(define-public (gcc-cross-newlib-arm-configure-flags target libc)
|
||
"Modify configure-flags to build a GCC cross-compiler for the Arm target
|
||
TARGET using newlib as LIBC."
|
||
#~(list
|
||
(string-append "--target=" #$target)
|
||
;; All paths to --with-… options are relative to the sysroot. As store
|
||
;; pathes are absolute, the sysroot needs to be set to /.
|
||
"--with-sysroot=/"
|
||
;; The first set of include paths consinsts of #$gcc/include-c++/… and
|
||
;; #$gcc:lib/…/include. Second is usually /usr/local, which we replace
|
||
;; with the empty #$output:lib/include path.
|
||
(string-append "--with-local-prefix=" #$output:lib)
|
||
;; Third is #$gcc:lib/…/include-fixed, which expects #$libc/include and
|
||
;; #$kernel-headers/include to follow in this order.
|
||
;; Fourth and usually the last include path is /usr/include containing all
|
||
;; system headers. It is only possible to specify one path for this. Set
|
||
;; the #$libc/include path and prevent the use of /usr/include.
|
||
;; Using newlib as libc for bare-metal does not require kernel-headers.
|
||
(string-append
|
||
"--with-native-system-header-dir=" #$libc "/" #$target "/include")
|
||
;; Add #$output/#$target/lib and #$libc/#$target/lib as a built-in
|
||
;; link-time search path.
|
||
(string-append
|
||
"--with-specs="
|
||
;; Embed the link-time search path to libgcc, libstdc++, etc.
|
||
"%x{-L" #$output "/" #$target "/lib} "
|
||
;; Embed the link-time search paths to libc.
|
||
"%x{-L" #$libc "/" #$target "/lib}")
|
||
;; Prevent the C++ headers in #$output:lib, put them in #$output:out
|
||
;; instead. Use an unconventional path to prevent it from being added to
|
||
;; the environment variables C_INCLUDE_PATH and CPLUS_INCLUDE_PATH.
|
||
"--with-gxx-include-dir=$(prefix)/include-c++"
|
||
;; Ensure GCC is build for newlib.
|
||
"--with-newlib"
|
||
;; As newlib has multiple target libraries, enable their support.
|
||
"--enable-multilib"
|
||
"--with-multilib-list=aprofile,rmprofile"
|
||
;; As newlib does not have a dynamik-linker, disable shared builds.
|
||
"--disable-shared"
|
||
;; Disable all language frontends except for C and C++.
|
||
"--enable-languages=c,c++"
|
||
;; Save space by disabling pre-compiled libstdc++ headers.
|
||
"--disable-libstdcxx-pch"
|
||
;; Use the zlib package instead of the zlib bundled with gcc.
|
||
"--with-system-zlib"
|
||
;; Avoid parallel linking to not crash on systems with limited memory.
|
||
"--enable-link-serialization"))
|
||
|
||
(define*-public (make-cross-gcc gcc cross-libc cross-binutils)
|
||
"Make a GCC cross-compiler package based on a still native but modified GCC
|
||
package using the CROSS-LIBC and CROSS-BINUTILS packages."
|
||
(package
|
||
(inherit gcc)
|
||
(name (string-append (package-name gcc)
|
||
"-cross-"
|
||
(package-name cross-libc)))
|
||
(inputs '())
|
||
(native-inputs (append (list (list "cross-binutils" cross-binutils))
|
||
(package-inputs gcc)))))
|
||
|
||
(define*-public (make-cross-c-toolchain target cross-gcc cross-binutils
|
||
#:optional cross-ld-wrapper)
|
||
"Make a cross-C-toolchain targeting TARGET of the CROSS-GCC, CROSS-BINUTILS,
|
||
guix-locpath and optionally CROSS-LD-WRAPPER packages. The result can be used
|
||
by the transformation function 'package-with-c-toolchain' and to build a
|
||
GCC-toolchain package with 'make-gcc-toolchain-package'.
|
||
|
||
The guix-locpath package is used instead of the glibc package to prevent glibc
|
||
and the kernel-headers from appearing in the C_INCLUDE_PATH, CPLUS_INCLUDE_PATH,
|
||
and similar environment variables. The GCC package is expected to have the
|
||
necessary paths build-in to preserve a necessary include-order."
|
||
(append (make-c-toolchain cross-gcc cross-binutils cross-ld-wrapper)
|
||
;; GCC looks for as and other tools from cross-binutils in PATH.
|
||
;; However, the cross-binutils package contains only executables
|
||
;; pefixed with the target name in its bin directory. The ones
|
||
;; not prefixed reside in its target/bin directory. We create a
|
||
;; new package, which links that #$target/bin directory as bin.
|
||
;; Note: The linker is invoked by collect2, which has different lookup
|
||
;; rules as GCC and finds a prefixed target-ld.
|
||
(list
|
||
(list "binutils-for-toolchain"
|
||
(package
|
||
(inherit cross-binutils)
|
||
(name (string-append (package-name cross-binutils)
|
||
"-for-toolchain"))
|
||
(version (package-version cross-binutils))
|
||
(source #f)
|
||
(build-system trivial-build-system)
|
||
(arguments
|
||
(list
|
||
#:builder
|
||
#~(begin
|
||
(mkdir #$output)
|
||
(symlink
|
||
#$(file-append cross-binutils "/" target "/bin")
|
||
(string-append #$output "/bin"))))))))))
|
||
|
||
(define*-public (make-cross-arm-none-eabi-c-toolchain
|
||
gcc
|
||
make-gcc
|
||
make-cross-newlib)
|
||
"Make a C-toolchain targeting arm-none-eabi consisting of a cross-compiler,
|
||
cross-compiled Binutils, and a newlib C-library. The cross-compiler will be
|
||
build with another toolchain using the given host GCC and Binutils. The
|
||
function MAKE-GCC is used to create a GCC cross-compiler package using the
|
||
newlib C-library package created with MAKE-CROSS-NEWLIB. The result can be used
|
||
by the transformation function 'package-with-c-toolchain' and to build a
|
||
GCC-toolchain package with 'make-gcc-toolchain-package'."
|
||
(let* ((target "arm-none-eabi")
|
||
(c-toolchain (make-c-toolchain gcc binutils ld-wrapper))
|
||
(cross-binutils (cross-binutils target))
|
||
(cross-newlib (make-cross-newlib target))
|
||
(cross-gcc
|
||
(package-with-c-toolchain
|
||
(make-cross-gcc
|
||
(make-gcc (gcc-phase-pre-configure
|
||
#:libc cross-newlib
|
||
#:startfile-dir (string-append "/" target "/lib/"))
|
||
(gcc-cross-newlib-arm-configure-flags target
|
||
cross-newlib))
|
||
cross-newlib
|
||
cross-binutils)
|
||
c-toolchain)))
|
||
(make-cross-c-toolchain target cross-gcc cross-binutils)))
|
||
|
||
(define-public gcc12-cross-newlib-arm-none-eabi-c-toolchain
|
||
(make-cross-arm-none-eabi-c-toolchain gcc12 make-gcc12 make-newlib-4.3))
|
||
|
||
(define-public gcc12-cross-newlib-nano-arm-none-eabi-c-toolchain
|
||
(make-cross-arm-none-eabi-c-toolchain gcc12 make-gcc12 make-newlib-nano-4.3))
|
||
|
||
(define-public gcc12-cross-newlib-arm-none-eabi-toolchain
|
||
(package
|
||
(inherit (make-gcc-toolchain-package
|
||
gcc12-cross-newlib-arm-none-eabi-c-toolchain))
|
||
(synopsis
|
||
"Complete GCC toolchain for C/C++ cross development on ARM Cortex-A and
|
||
Cortex-M micro-controllers with newlib")
|
||
(description "This package provides a complete GCC toolchain for C/C++ cross
|
||
development on ARM Cortex-A and Cortex-M micro-controllers to be installed in
|
||
user profiles. This includes GCC, newlib and Binutils. GCC is the GNU
|
||
Compiler Collection.")))
|
||
|
||
(define-public gcc12-cross-newlib-nano-arm-none-eabi-toolchain
|
||
(package
|
||
(inherit (make-gcc-toolchain-package
|
||
gcc12-cross-newlib-nano-arm-none-eabi-c-toolchain))
|
||
(synopsis
|
||
"Complete GCC toolchain for C/C++ cross development on ARM Cortex-A and
|
||
Cortex-M micro-controllers with newlib-nano")
|
||
(description "This package provides a complete GCC toolchain for C/C++ cross
|
||
development on ARM Cortex-A and Cortex-M micro-controllers to be installed in
|
||
user profiles. This includes GCC, newlib-nano and Binutils. GCC is the GNU
|
||
Compiler Collection.")))
|
||
|
||
(define-public gcc12-cross-newlib-arm-none-eabi
|
||
(car (assoc-ref gcc12-cross-newlib-arm-none-eabi-c-toolchain "gcc")))
|
||
|
||
(define-public gcc12-cross-newlib-nano-arm-none-eabi
|
||
(car (assoc-ref gcc12-cross-newlib-nano-arm-none-eabi-c-toolchain "gcc")))
|
||
|
||
(define-public binutils-cross-arm-none-eabi
|
||
(car (assoc-ref gcc12-cross-newlib-nano-arm-none-eabi-c-toolchain "binutils")))
|
||
|