From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id AMSnOW0W+WMmEgAAbAwnHQ (envelope-from ) for ; Fri, 24 Feb 2023 20:56:30 +0100 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id yHHSOW0W+WNh+AAAauVa8A (envelope-from ) for ; Fri, 24 Feb 2023 20:56:29 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 7A35ABAFA for ; Fri, 24 Feb 2023 20:56:29 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pVeAf-0007jA-Eu; Fri, 24 Feb 2023 14:55:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pVdBn-0007Ml-A4 for guix-patches@gnu.org; Fri, 24 Feb 2023 13:53:03 -0500 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pVdBn-0007vU-1i for guix-patches@gnu.org; Fri, 24 Feb 2023 13:53:03 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pVdBm-0006r2-G2 for guix-patches@gnu.org; Fri, 24 Feb 2023 13:53:02 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#61765] custom toolchain blog post Resent-From: Mitchell Schmeisser Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 24 Feb 2023 18:53:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 61765 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: To: 61765@debbugs.gnu.org X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.167726473026287 (code B ref -1); Fri, 24 Feb 2023 18:53:02 +0000 Received: (at submit) by debbugs.gnu.org; 24 Feb 2023 18:52:10 +0000 Received: from localhost ([127.0.0.1]:38235 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pVdAu-0006pu-ND for submit@debbugs.gnu.org; Fri, 24 Feb 2023 13:52:09 -0500 Received: from lists.gnu.org ([209.51.188.17]:39508) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pVdAs-0006pl-HO for submit@debbugs.gnu.org; Fri, 24 Feb 2023 13:52:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pVdAs-0007ID-AW for guix-patches@gnu.org; Fri, 24 Feb 2023 13:52:06 -0500 Received: from mx1.librem.one ([138.201.176.93]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pVdAp-00077U-1u for guix-patches@gnu.org; Fri, 24 Feb 2023 13:52:06 -0500 Received: from smtp.librem.one (unknown [192.241.214.14]) by mx1.librem.one (Postfix) with ESMTPS id EB4D381E97 for ; Fri, 24 Feb 2023 10:51:59 -0800 (PST) Date: Fri, 24 Feb 2023 13:51:56 -0500 Message-ID: <87sfeuucab.fsf@librem.one> Content-Type: text/plain Received-SPF: pass client-ip=138.201.176.93; envelope-from=mitchellschmeisser@librem.one; helo=mx1.librem.one X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Mailman-Approved-At: Fri, 24 Feb 2023 14:55:48 -0500 X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Mitchell Schmeisser X-ACL-Warn: , Mitchell Schmeisser via Guix-patches From: Mitchell Schmeisser via Guix-patches via Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN ARC-Seal: i=1; s=key1; d=yhetil.org; t=1677268589; a=rsa-sha256; cv=none; b=GXPsZoDbJSrP+JjukjglNybrZ2F7kLnamKnzhioqDjDcpYYaaWlzuDs13P7b2scZXpwV80 O5Qik4mdzkrYKrinPFMuiXqC/Y3VYs6/lgmM9KIGQzXRg2Og9yUgnq7Oow+UpdXpQGCxv0 f8zTzeKEzLdSenXTPt6VLuDhEdarF0BKwYE+Vo1Ye7cwGpjxuWonDMR7LqZMUFkgXlxZJ9 Cm5xW5k/UKY+j/MFN/2LeVUYTTNXwE8Qhe2ZfaWlacAR/vbQxahn5yeqSkB4ICQZPLfK+S iNVxLyUtdLiOa4bRYPoN2Uv/S6QgJB+9ABpP7QvEPw726dPF07BEdbZ6R8vIzw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1677268589; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:content-type:content-type:resent-cc: resent-from:resent-sender:resent-message-id:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=yB3eOJM8asPXAjo4f5AphK22BZ/x2g4QDobJmt2/ER4=; b=N7ssKSksGU0u6KFDqCdWmArO82wlTw6SGljrfFZKN+6W7XzrXMDc6/h+3v7p1uXYYiMd1S hBxs1kOKAnymquT/WTdeB375W/JbaWfXPjsj+8um2c7QKtyCtZgsuR0i3uNVdVEs41dlMd c0Q6abb3Nhnxt+2aPyKEYvgEpGF6a5iFSK7XWkgflov/QByYUy9dPo2XFgEHuKWxU0Vmbb WPwq1rIzcJZLvv8VKEEC0ctfVOytSvPPzw31PQDJim0PpacNh2oO/14tfVVXKohW6GPwac cqfji2OADtNxERfw2WGpSrEoS2yYMOw6RaOskhFQvBqPCQgXQKVErHek+IkBVQ== X-Migadu-Scanner: scn1.migadu.com X-Migadu-Spam-Score: -0.08 X-Spam-Score: -0.08 X-Migadu-Queue-Id: 7A35ABAFA Authentication-Results: aspmx1.migadu.com; dkim=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org X-TUID: kqrryM95kSpn Here is a rough draft of my toolchain post. I hope it can make an interesting contribution to the Guix literature. - Mitchell >From 4f6c43091ffd67cdbc5f041e496f61bc8a06070e Mon Sep 17 00:00:00 2001 From: Mitchell Schmeisser Date: Fri, 24 Feb 2023 13:02:05 -0500 Subject: [PATCH] website: Add custom toolchain blog post * website/posts/custom-toolchains-with-guix.md: New file. --- website/posts/custom-toolchains-with-guix.md | 557 +++++++++++++++++++ 1 file changed, 557 insertions(+) create mode 100644 website/posts/custom-toolchains-with-guix.md diff --git a/website/posts/custom-toolchains-with-guix.md b/website/posts/custom-toolchains-with-guix.md new file mode 100644 index 0000000..f73f1ab --- /dev/null +++ b/website/posts/custom-toolchains-with-guix.md @@ -0,0 +1,557 @@ +# Table of Contents + +1. [Overview](#org2633a51) +2. [Anatomy of a toolchain](#orgc440e9e) +3. [Bootstrapping a Toolchain](#orgd42b6c3) +4. [Defining the Packages](#org55042c5) + 1. [Binutils](#org67da1ec) + 2. [GCC sans libc](#org82d6f83) + 3. [Newlib(-nano)](#orgf6bafbc) + 4. [Complete toolchain](#org052f2a2) +5. [Integrating with Zephyr Build System](#orgc3f87f4) + 1. [Testing](#org9f3c314) + +All code is available at [guix-zephyr](https://github.com/paperclip4465/guix-zephyr) channel. + + + + +# Overview + +In order to deploy embedded software using Guix we first need to teach Guix +how to build it. Since Guix bootstraps everything this means we must teach Guix +how to build our toolchain. + +The [Zephyr Project](https://zephyrproject.org) uses its own fork of GCC with custom configs for +the architectures supported by the project. + + + + +# Anatomy of a toolchain + +Toolchains are responsible for taking high level descriptions of programs +and lowering them down to a series of equivalent machine instructions. +This process involves more than just a compiler. The compiler uses the `binutils` +to manipulate it's internal representation down to a given architecture. +It also needs the use of the C standard library as well as a few other libraries +needed for some compiler optimizations. + +The C library provides the interface to the underlying kernel. System calls like `write` +and `read` are provided by `Glibc` on most Linux distributions. + +In embedded systems smaller implementations like `newlib` and `newlib-nano` are used. + + + + +# Bootstrapping a Toolchain + +In order to compile GCC we need a C library that's been compiled for +our target architecture. How can we cross compile our C library if we +need our C library to build a cross compiler? The solution is to build +a simpler compiler that doesn't require the C library to function. +It will not be capable of as many optimizations and it will be very slow, +however it will be able to build the C libraries as well as the complete version +of GCC. + +In order to build the simpler compiler we need to compile the `binutils` to +work with our target architecture. +The `binutils` can be bootstrapped with our host GCC and have no target dependencies. + +[For more information read this.](https://crosstool-ng.github.io/docs/toolchain-construction/) + +Doesn't sound so bad right? It isn't… in theory. +However internet forums since time immemorial have been +littered with the laments of those who came before. +From incorrect versions of `ISL` to the wrong C library being linked +or the host linker being used, etc. +The one commonality between all of these issues is the environment. +Building a cross toolchain is difficult because isolating build +environments is difficult. + +In fact as of `v0.14.2` the zephyr SDK repository took down the build +instructions and posted a sign that read +"Building this is too complicated, don't worry about it."1 + +We will neatly side step all of these problems and not +risk destroying or polluting our host system with garbage +by using Guix to manage our environments for us. + +Our toolchain only requires the first pass compiler because +newlib(-nano) is statically linked and introduced to the toolchain +by normal package composition. + + + + +# Defining the Packages + +All of the base packages are defined in `zephyr/packages/zephyr.scm`. +Zephyr modules are defined in `zephyr/packages/zephyr-xyz.scm`, following +the pattern of other module systems implemented by Guix. + + + + +## Binutils + +First thing we need to build is the `arm-zephyr-eabi` binutils. +This is very easy in Guix. + + (define-module (zephyr packages zephyr) + #:use-module (guix packages)) + + (define-public arm-zephyr-eabi-binutils + (let ((xbinutils (cross-binutils "arm-zephyr-eabi"))) + (package + (inherit xbinutils) + (name "arm-zephyr-eabi-binutils") + (version "2.38") + (source + (origin (method git-fetch) + (uri (git-reference + (url "https://github.com/zephyrproject-rtos/binutils-gdb") + (commit "6a1be1a6a571957fea8b130e4ca2dcc65e753469"))) + (file-name (git-file-name name version)) + (sha256 (base32 "0ylnl48jj5jk3jrmvfx5zf8byvwg7g7my7jwwyqw3a95qcyh0isr")))) + (arguments + `(#:tests? #f + ,@(substitute-keyword-arguments (package-arguments xbinutils) + ((#:configure-flags flags) + `(cons "--program-prefix=arm-zephyr-eabi-" ,flags))))) + (native-inputs + (append + (list texinfo + bison + flex + gmp + dejagnu) + (package-native-inputs xbinutils))) + (home-page "https://zephyrproject.org") + (synopsis "binutils for zephyr RTOS")))) + +The function `cross-binutils` returns a package which has been +configured for the given gnu triplet. We simply inherit that package +and replace the source. +The zephyr build system expects the binutils to be prefixed with +`arm-zephyr-eabi-` which is accomplished by adding another flag to the +`#:configure-flags` argument. + +We can test our package definition using the `-L` flag with `guix build` +to add our packages. + + guix build -L guix-zephyr zephyr-binutils + + /gnu/store/...-zephyr-binutils-2.38 + +This directory contains the results of `make install`. + + + + +## GCC sans libc + +This one is a bit more involved. Don't be afraid! +This version of GCC wants ISL version 0.15. It's easy enough +to make that happen. Inherit the current version of ISL and swap +out the source and update the version. For most packages the build process doesn't +change that much between versions. + + (define-public isl-0.15 + (package + (inherit isl) + (version "0.15") + (source (origin + (method url-fetch) + (uri (list (string-append "mirror://sourceforge/libisl/isl-" + version ".tar.gz"))) + (sha256 + (base32 + "11vrpznpdh7w8jp4wm4i8zqhzq2h7nix71xfdddp8xnzhz26gyq2")))))) + +Like the binutils, there is a function for creating cross-gcc packages. +This one accepts keywords specifying which binutils and libc to use. +If libc isn't given (like here), gcc is configured with many options disabled +to facilitate being built without libc. Therefore we need to add the extra options +we want 2 + + (define-public gcc-arm-zephyr-eabi-12 + (let ((xgcc (cross-gcc "arm-zephyr-eabi" + #:xbinutils zephyr-binutils))) + (package + (inherit xgcc) + (version "12.1.0") + (source (origin (method git-fetch) + (uri (git-reference + (url "https://github.com/zephyrproject-rtos/gcc") + (commit "0218469df050c33479a1d5be3e5239ac0eb351bf"))) + (file-name (git-file-name (package-name xgcc) version)) + (sha256 + (base32 "1s409qmidlvzaw1ns6jaanigh3azcxisjplzwn7j2n3s33b76zjk")) + (patches + (search-patches "gcc-12-cross-environment-variables.patch" + "gcc-cross-gxx-include-dir.patch")))) + (native-inputs + (modify-inputs (package-native-inputs xgcc) + ;; Get rid of stock ISL + (delete "isl") + ;; Add additional dependencies that xgcc doesn't have + ;; including our special ISL + (prepend flex + perl + python-3 + gmp + isl-0.15 + texinfo + python + mpc + mpfr + zlib))) + (arguments + (substitute-keyword-arguments (package-arguments xgcc) + ((#:phases phases) + `(modify-phases ,phases + (add-after 'unpack 'fix-genmultilib + (lambda _ + (substitute* "gcc/genmultilib" + (("#!/bin/sh") (string-append "#!" (which "sh")))) + #t)) + + (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH + (lambda* (#:key inputs #:allow-other-keys) + (let ((gcc (assoc-ref inputs "gcc"))) + ;; Remove the default compiler from CPLUS_INCLUDE_PATH to + ;; prevent header conflict with the GCC from native-inputs. + (setenv "CPLUS_INCLUDE_PATH" + (string-join + (delete (string-append gcc "/include/c++") + (string-split (getenv "CPLUS_INCLUDE_PATH") + #\:)) + ":")) + (format #t + "environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%" + (getenv "CPLUS_INCLUDE_PATH")) + #t))))) + + ((#:configure-flags flags) + ;; The configure flags are largely identical to the flags used by the + ;; "GCC ARM embedded" project. + `(append (list "--enable-multilib" + "--with-newlib" + "--with-multilib-list=rmprofile" + "--with-host-libstdcxx=-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm" + "--enable-plugins" + "--disable-decimal-float" + "--disable-libffi" + "--disable-libgomp" + "--disable-libmudflap" + "--disable-libquadmath" + "--disable-libssp" + "--disable-libstdcxx-pch" + "--disable-nls" + "--disable-shared" + "--disable-threads" + "--disable-tls" + "--with-gnu-ld" + "--with-gnu-as" + "--enable-initfini-array") + (delete "--disable-multilib" ,flags))))) + (native-search-paths + (list (search-path-specification + (variable "CROSS_C_INCLUDE_PATH") + (files '("arm-zephyr-eabi/include"))) + (search-path-specification + (variable "CROSS_CPLUS_INCLUDE_PATH") + (files '("arm-zephyr-eabi/include" + "arm-zephyr-eabi/c++" + "arm-zephyr-eabi/c++/arm-zephyr-eabi"))) + (search-path-specification + (variable "CROSS_LIBRARY_PATH") + (files '("arm-zephyr-eabi/lib"))))) + (home-page "https://zephyrproject.org") + (synopsis "GCC for zephyr RTOS")))) + +This GCC can be built like so. + + guix build -L guix-zephyr gcc-cross-sans-libc-arm-zephyr-eabi + + /gnu/store/...-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0-lib + /gnu/store/...-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0 + +Great! We now have our stage-1 compiler. + + + + +## Newlib(-nano) + +The newlib package package is quite straight forward (relatively). +It is mostly adding in the relevent configuration flags and patching +the files the `patch-shebangs` phase missed. + + (define-public zephyr-newlib + (package + (name "zephyr-newlib") + (version "3.3") + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://github.com/zephyrproject-rtos/newlib-cygwin") + (commit "4e150303bcc1e44f4d90f3489a4417433980d5ff"))) + (sha256 + (base32 "08qwjpj5jhpc3p7a5mbl7n6z7rav5yqlydqanm6nny42qpa8kxij")))) + (build-system gnu-build-system) + (arguments + `(#:out-of-source? #t + #:configure-flags '("--target=arm-zephyr-eabi" + "--enable-newlib-io-long-long" + "--enable-newlib-io-float" + "--enable-newlib-io-c99-formats" + "--enable-newlib-retargetable-locking" + "--enable-newlib-lite-exit" + "--enable-newlib-multithread" + "--enable-newlib-register-fini" + "--enable-newlib-extra-sections" + "--disable-newlib-wide-orient" + "--disable-newlib-fseek-optimization" + "--disable-newlib-supplied-syscalls" + "--disable-newlib-target-optspace" + "--disable-nls") + #:phases + (modify-phases %standard-phases + (add-after 'unpack 'fix-references-to-/bin/sh + (lambda _ + (substitute* '("libgloss/arm/cpu-init/Makefile.in" + "libgloss/arm/Makefile.in" + "libgloss/libnosys/Makefile.in" + "libgloss/Makefile.in") + (("/bin/sh") (which "sh"))) + #t))))) + (native-inputs + `(("xbinutils" ,zephyr-binutils) + ("xgcc" ,gcc-arm-zephyr-eabi-12) + ("texinfo" ,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")))) + +And the build. + + guix build -L guix-zephyr zephyr-newlib + + /gnu/store/...-zephyr-newlib-3.3 + + + + +## Complete toolchain3 + +Now that we've got the individual tools it's time to create our complete toolchain. +For this we need to do some package transformations. +Because these transformations are going to have to be done for every combination of +gcc/newlib it is best to create a function which we can reuse for every version +of the SDK. + + (define (arm-zephyr-eabi-toolchain xgcc newlib version) + "Produce a cross-compiler zephyr toolchain package with the compiler XGCC and the C + library variant NEWLIB." + (let ((newlib-with-xgcc (package (inherit newlib) + (native-inputs + (alist-replace "xgcc" (list xgcc) + (package-native-inputs newlib)))))) + (package + (name (string-append "arm-zephyr-eabi" + (if (string=? (package-name newlib-with-xgcc) + "newlib-nano") + "-nano" "") + "-toolchain")) + (version version) + (source #f) + (build-system trivial-build-system) + (arguments + '(#:modules ((guix build union) + (guix build utils)) + #:builder + (begin + (use-modules (ice-9 match) + (guix build union) + (guix build utils)) + (let ((out (assoc-ref %outputs "out"))) + (mkdir-p out) + (match %build-inputs + (((names . directories) ...) + (union-build (string-append out "/arm-zephyr-eabi") + directories) + #t)))))) + (inputs + `(("binutils" ,zephyr-binutils) + ("gcc" ,xgcc) + ("newlib" ,newlib-with-xgcc))) + (synopsis "Complete GCC tool chain for ARM zephyrRTOS development") + (description "This package provides a complete GCC tool chain for ARM + bare metal development with zephyr rtos. This includes the GCC arm-zephyr-eabi cross compiler + and newlib (or newlib-nano) as the C library. The supported programming + language is C.") + (home-page (package-home-page xgcc)) + (license (package-license xgcc))))) + +This function creates a special package which consists of the toolchain in a special directory hierarchy, i.e `arm-zephyr-eabi/`. +Our complete toolchain definition looks like this. + + (define-public arm-zephyr-eabi-toolchain-0.15.0 + (arm-zephyr-eabi-toolchain + gcc-arm-zephyr-eabi-12 + zephyr-newlib + "0.15.0")) + +To build: + + guix build -L guix-zephyr arm-zephyr-eabi-toolchain + + /gnu/store/...-arm-zephyr-eabi-toolchain-0.15.0 + + + + +# Integrating with Zephyr Build System + +Zephyr uses CMake as it's build system. It contains numerous CMake +files in both the so-called `ZEPHYR_BASE`, the zephyr source code +repository, as well as a handful in the SDK +which help select the correct toolchain for a given board. + +There are standard locations the build system will look for the +SDK. We are not using any of them. Our SDK lives in the store, +immutable forever. According to [this](https://docs.zephyrproject.org/latest/develop/west/without-west.html) the variable +`ZEPHYR_SDK_INSTALL_DIR` needs to point to our custom spot. + +We also need to grab the cmake files from the [repository](https://github.com/zephyrproject-rtos/sdk-ng) and create a +file `sdk_version` which contains the version string `ZEPHYR_BASE` +uses to find a compatible SDK. + +Along with the SDK proper we need to include a number of python +packages required by the build system4. + + (define-public zephyr-sdk + (package + (name "zephyr-sdk") + (version "0.15.0") + (home-page "https://zephyrproject.org") + (source (origin (method git-fetch) + (uri (git-reference + (url "https://github.com/zephyrproject-rtos/sdk-ng") + (commit "v0.15.0"))) + (file-name (git-file-name name version)) + (sha256 (base32 "04gsvh20y820dkv5lrwppbj7w3wdqvd8hcanm8hl4wi907lwlmwi")))) + (build-system trivial-build-system) + (arguments + `(#:modules ((guix build union) + (guix build utils)) + #:builder + (begin + (use-modules (guix build union) + (ice-9 match) + (guix build utils)) + (let* ((out (assoc-ref %outputs "out")) + (cmake-scripts (string-append (assoc-ref %build-inputs "source") + "/cmake")) + (sdk-out (string-append out "/zephyr-sdk-0.15.0"))) + (mkdir-p out) + + (match (assoc-remove! %build-inputs "source") + (((names . directories) ...) + (union-build sdk-out directories))) + + (copy-recursively cmake-scripts + (string-append sdk-out "/cmake")) + + (with-directory-excursion sdk-out + (call-with-output-file "sdk_version" + (lambda (p) + (format p "0.15.0"))) + #t))))) + (propagated-inputs + (list + arm-zephyr-eabi-toolchain-0.15.0 + zephyr-binutils + python-3 + python-pyelftools + python-pykwalify + python-pyyaml + python-packaging + dtc)) + (native-search-paths + (list (search-path-specification + (variable "ZEPHYR_SDK_INSTALL_DIR") + (files '(""))))) + (synopsis "SDK for zephyrRTOS") + (description "zephyr-sdk contains bundles a complete gcc toolchain as well + as host tools like dtc, openocd, qemu, and required python packages.") + (license license:apsl2))) + + + + +## Testing + +In order to test we will need an environment with the SDK installed. +We can take advantage of `guix shell` to avoid installing test +packages into our home environment. This way if it causes problems we +can just exit the shell and try again. + + guix shell -L guix-zephyr zephyr-sdk cmake ninja git + +`ZEPHYR_BASE` can be cloned into a temporary workspace to test our +toolchain functionality.5 + + mkdir /tmp/zephyr-project + cd /tmp/zephyr-project + git clone https://github.com/zephyrproject-rtos/zephyr + export ZEPHYR_BASE=/tmp/zephyr-project/zephyr + +In order to build for the test board (k64f in this case) we need to +get a hold of the vendor Hardware Abstraction Layers and CMSIS.6 + + git clone https://github.com/zephyrproject-rtos/hal_nxp && + git clone https://github.com/zephyrproject-rtos/cmsis + +To inform the build system about this module we pass it in with +`-DZEPHYR_MODULES=` which is a semicolon separated list of paths +containing a module.yml file. + +To build the hello world sample we use the following incantation. + + cmake -Bbuild $ZEPHYR_BASE/samples/hello_world \ + -GNinja \ + -DBOARD=frdm_k64f \ + -DBUILD_VERSION=3.1.0 \ + -DZEPHYR_MODULES="/tmp/zephyr-project/hal_nxp;/tmp/zephyr-project/cmsis" \ + && ninja -Cbuild + +If everything is set up correctly we will end up with a `./build` +directory with all our build artifacts. The SDK is installed correctly! + + +# Footnotes + +1 I'm paraphrasing, but [not by much](https://github.com/zephyrproject-rtos/sdk-ng/tree/v0.14.2#build-process). + +2 I got them from the SDK configuration scripts on the [sdk github](https://github.com/zephyrproject-rtos/sdk-ng) as well as the +commits to use for each of the tools. + +3 *Mostly* complete. libstdc++ does not build because +\`arm-zephyr-eabi\` is not \`arm-none-eabi\` so a dynamic link check is +performed/failed. I cannot figure out how crosstool-ng handles this. + +4 This is no longer the case. Now python packages are provided by the zephyr package +which was not available when this was being developed. + +5 For now. Eventually we will need to create a package for `zephyr-base` that +our guix zephyr-build-system can use. + +6 These will also need to become guix packages to allow the build system to compose modules. -- 2.39.1