building-toolchains-with-guix.html 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <!DOCTYPE html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /><meta name="keywords" content="GNU, Emacs, Libre Software, Hurd, Guile, Guix" /><meta name="description" content="GNUcode.me is a website focusing on libre software projects, especially the GNU project." /><link type="application/atom+xml" rel="alternate" title="GNUcode.me -- Feed" href="/feed.xml" /><a rel="me" href="https://fosstodon.org/@thegnuguy"></a><link type="text/css" href="css/footer.min.css" rel="stylesheet"></link><link type="text/css" href="css/header.min.css" rel="stylesheet"></link><link type="text/css" href="css/main.min.css" rel="stylesheet"></link><title>Building Toolchains with Guix — GNUcode.me</title></head><body><header><nav><ul><li><a href="index.html">GNUcode.me</a></li><li><a href="services.html">Services</a></li><li><a href="about.html">About</a></li><li><a href="business-ideas.html">Business-ideas</a></li></ul></nav></header><h1>Building Toolchains with Guix</h1><main><section class="basic-section-padding"><article><h3>by Mitchell Schmeisser &lt;mitchellschmeisser@librem.one&gt; — February 23, 2023</h3><div><p>Today's post is a guest post from my new internet friend Mitchell. We met on the
  2. #guix irc channel, and I offered to post a few of his blog posts on this blog. Without further ado,
  3. here is Michell's first blog post (it's pretty fantastic)!</p><h1>Overview</h1><p>In order to deploy embedded software using Guix we first need to teach Guix
  4. how to build it. Since Guix bootstraps everything this means we must teach Guix
  5. how to build our toolchain.</p><p>The <a href="https://zephyrproject.org">Zephyr Project</a> uses its own fork of GCC with custom configs for
  6. the architectures supported by the project.</p><h1>Anatomy of a toolchain</h1><p>Toolchains are responsible for taking high level descriptions of programs and
  7. lowering them down to a series of equivalent machine instructions. This process
  8. involves more than just a compiler. The compiler uses the <code>binutils</code> to
  9. manipulate it’s internal representation down to a given architecture. It
  10. also needs the C standard library as well as a few other libraries needed for
  11. some compiler optimizations.</p><p>The C library provides the interface to the underlying kernel. System calls like <code>write</code>
  12. and <code>read</code> are provided by <code>Glibc</code> on most Linux distributions.</p><p>In embedded systems smaller implementations like <code>newlib</code> and <code>newlib-nano</code> are used.</p><h1>Bootstrapping a Toolchain</h1><p>In order to compile GCC we need a C library that’s been compiled for
  13. our target architecture. How can we cross compile our C library if we
  14. need our C library to build a cross compiler? The solution is to build
  15. a simpler compiler that doesn’t require the C library to function.
  16. It will not be capable of as many optimizations and it will be very slow,
  17. however it will be able to build the C libraries as well as the complete version
  18. of GCC.</p><p>In order to build the simpler compiler we need to compile the <code>binutils</code> to
  19. work with our target architecture.
  20. The <code>binutils</code> can be bootstrapped with our host GCC and have no target dependencies.</p><p><a href="https://crosstool-ng.github.io/docs/toolchain-construction/">For more information read this.</a></p><p>Doesn’t sound so bad right? It isn’t… in theory.
  21. However internet forums since time immemorial have been
  22. littered with the laments of those who came before.
  23. From incorrect versions of <code>ISL</code> to the wrong C library being linked
  24. or the host linker being used, etc.
  25. The one commonality between all of these issues is the environment.
  26. Building GCC is difficult because isolating build environments is hard.</p><p>In fact as of <code>v0.14.2</code> the zephyr SDK repository took down the build
  27. instructions and posted a sign that read “Building this is too
  28. complicated, don’t worry about it.” (I’m paraphrasing, but
  29. <a href="https://github.com/zephyrproject-rtos/sdk-ng/tree/v0.14.2#build-process">not by
  30. much</a>.)</p><p>We will neatly side step all of these problems and not
  31. risk destroying or polluting our host system with garbage
  32. by using Guix to manage our environments for us.</p><p>Our toolchain only requires the first pass compiler because
  33. newlib(-nano) is statically linked and introduced to the toolchain
  34. by normal package composition.</p><h1>Defining the Packages</h1><p>All of the base packages are defined in <code>zephyr/packages/zephyr.scm</code>.
  35. Zephyr modules are defined in <code>zephyr/packages/zephyr-xyz.scm</code>, following
  36. the pattern of other module systems implemented by Guix.</p><h2>Binutils</h2><p>First thing we need to build is the <code>arm-zephyr-eabi</code> binutils.
  37. This is very easy in Guix.</p><pre><code>(define-module (zephyr packages zephyr)
  38. #:use-module (guix packages)
  39. (define-public arm-zephyr-eabi-binutils
  40. (let ((xbinutils (cross-binutils &quot;arm-zephyr-eabi&quot;)))
  41. (package
  42. (inherit xbinutils)
  43. (name &quot;arm-zephyr-eabi-binutils&quot;)
  44. (version &quot;2.38&quot;)
  45. (source
  46. (origin (method git-fetch)
  47. (uri (git-reference
  48. (url &quot;https://github.com/zephyrproject-rtos/binutils-gdb&quot;)
  49. (commit &quot;6a1be1a6a571957fea8b130e4ca2dcc65e753469&quot;)))
  50. (file-name (git-file-name name version))
  51. (sha256 (base32 &quot;0ylnl48jj5jk3jrmvfx5zf8byvwg7g7my7jwwyqw3a95qcyh0isr&quot;))))
  52. (arguments
  53. `(#:tests? #f
  54. ,@(substitute-keyword-arguments (package-arguments xbinutils)
  55. ((#:configure-flags flags)
  56. `(cons &quot;--program-prefix=arm-zephyr-eabi-&quot; ,flags)))))
  57. (native-inputs
  58. (append
  59. (list texinfo
  60. bison
  61. flex
  62. gmp
  63. dejagnu)
  64. (package-native-inputs xbinutils)))
  65. (home-page &quot;https://zephyrproject.org&quot;)
  66. (synopsis &quot;binutils for zephyr RTOS&quot;))))</code></pre><p>The function <code>cross-binutils</code> returns a package which has been
  67. configured for the given gnu triplet. We simply inherit that package
  68. and replace the source.
  69. The zephyr build system expects the binutils to be prefixed with
  70. <code>arm-zephyr-eabi-</code> which is accomplished by adding another flag to the
  71. <code>#:configure-flags</code> argument.</p><p>We can test our package definition using the <code>-L</code> flag with <code>guix build</code>
  72. to add our packages.</p><pre><code>guix build -L guix-zephyr zephyr-binutils
  73. /gnu/store/a947nb4rb2vymz2gaqnafgm1bsq4ipqp-zephyr-binutils-2.38</code></pre><p>This directory contains the results of <code>make install</code>.</p><h2>GCC sans libc</h2><p>This one is a bit more involved. Don’t be afraid!
  74. This version of GCC wants ISL version 0.15. It’s easy enough
  75. to make that happen. Inherit the current version of ISL and swap
  76. out the source and update the version. For most packages the build process doesn’t
  77. change that much between versions.</p><pre><code>(define-public isl-0.15
  78. (package
  79. (inherit isl)
  80. (version &quot;0.15&quot;)
  81. (source (origin
  82. (method url-fetch)
  83. (uri (list (string-append &quot;mirror://sourceforge/libisl/isl-&quot;
  84. version &quot;.tar.gz&quot;)))
  85. (sha256
  86. (base32
  87. &quot;11vrpznpdh7w8jp4wm4i8zqhzq2h7nix71xfdddp8xnzhz26gyq2&quot;))))))</code></pre><p>Like the binutils, there is a function for creating cross-gcc packages. This one
  88. accepts keywords specifying which binutils and libc to use. If libc isn’t
  89. given (like here), gcc is configured with many options disabled to facilitate
  90. being built without libc. Therefore we need to add the extra options we want (I
  91. got them from the SDK configuration scripts on the <a href="https://github.com/zephyrproject-rtos/sdk-ng">sdk
  92. github</a> as well as the commits to
  93. use for each of the tools. ).</p><pre><code>(define-public gcc-arm-zephyr-eabi-12
  94. (let ((xgcc (cross-gcc &quot;arm-zephyr-eabi&quot;
  95. #:xbinutils zephyr-binutils)))
  96. (package
  97. (inherit xgcc)
  98. (version &quot;12.1.0&quot;)
  99. (source (origin (method git-fetch)
  100. (uri (git-reference
  101. (url &quot;https://github.com/zephyrproject-rtos/gcc&quot;)
  102. (commit &quot;0218469df050c33479a1d5be3e5239ac0eb351bf&quot;)))
  103. (file-name (git-file-name (package-name xgcc) version))
  104. (sha256
  105. (base32 &quot;1s409qmidlvzaw1ns6jaanigh3azcxisjplzwn7j2n3s33b76zjk&quot;))
  106. (patches
  107. (search-patches &quot;gcc-12-cross-environment-variables.patch&quot;
  108. &quot;gcc-cross-gxx-include-dir.patch&quot;))))
  109. (native-inputs
  110. (modify-inputs (package-native-inputs xgcc)
  111. ;; Get rid of stock ISL
  112. (delete &quot;isl&quot;)
  113. ;; Add additional dependencies that xgcc doesn't have
  114. ;; including our special ISL
  115. (prepend flex
  116. perl
  117. python-3
  118. gmp
  119. isl-0.15
  120. texinfo
  121. python
  122. mpc
  123. mpfr
  124. zlib)))
  125. (arguments
  126. (substitute-keyword-arguments (package-arguments xgcc)
  127. ((#:phases phases)
  128. `(modify-phases ,phases
  129. (add-after 'unpack 'fix-genmultilib
  130. (lambda _
  131. (substitute* &quot;gcc/genmultilib&quot;
  132. ((&quot;#!/bin/sh&quot;) (string-append &quot;#!&quot; (which &quot;sh&quot;))))
  133. #t))
  134. (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
  135. (lambda* (#:key inputs #:allow-other-keys)
  136. (let ((gcc (assoc-ref inputs &quot;gcc&quot;)))
  137. ;; Remove the default compiler from CPLUS_INCLUDE_PATH to
  138. ;; prevent header conflict with the GCC from native-inputs.
  139. (setenv &quot;CPLUS_INCLUDE_PATH&quot;
  140. (string-join
  141. (delete (string-append gcc &quot;/include/c++&quot;)
  142. (string-split (getenv &quot;CPLUS_INCLUDE_PATH&quot;)
  143. #\:))
  144. &quot;:&quot;))
  145. (format #t
  146. &quot;environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%&quot;
  147. (getenv &quot;CPLUS_INCLUDE_PATH&quot;))
  148. #t)))))
  149. ((#:configure-flags flags)
  150. ;; The configure flags are largely identical to the flags used by the
  151. ;; &quot;GCC ARM embedded&quot; project.
  152. `(append (list &quot;--enable-multilib&quot;
  153. &quot;--with-newlib&quot;
  154. &quot;--with-multilib-list=rmprofile&quot;
  155. &quot;--with-host-libstdcxx=-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm&quot;
  156. &quot;--enable-plugins&quot;
  157. &quot;--disable-decimal-float&quot;
  158. &quot;--disable-libffi&quot;
  159. &quot;--disable-libgomp&quot;
  160. &quot;--disable-libmudflap&quot;
  161. &quot;--disable-libquadmath&quot;
  162. &quot;--disable-libssp&quot;
  163. &quot;--disable-libstdcxx-pch&quot;
  164. &quot;--disable-nls&quot;
  165. &quot;--disable-shared&quot;
  166. &quot;--disable-threads&quot;
  167. &quot;--disable-tls&quot;
  168. &quot;--with-gnu-ld&quot;
  169. &quot;--with-gnu-as&quot;
  170. &quot;--enable-initfini-array&quot;)
  171. (delete &quot;--disable-multilib&quot; ,flags)))))
  172. (native-search-paths
  173. (list (search-path-specification
  174. (variable &quot;CROSS_C_INCLUDE_PATH&quot;)
  175. (files '(&quot;arm-zephyr-eabi/include&quot;)))
  176. (search-path-specification
  177. (variable &quot;CROSS_CPLUS_INCLUDE_PATH&quot;)
  178. (files '(&quot;arm-zephyr-eabi/include&quot;
  179. &quot;arm-zephyr-eabi/c++&quot;
  180. &quot;arm-zephyr-eabi/c++/arm-zephyr-eabi&quot;)))
  181. (search-path-specification
  182. (variable &quot;CROSS_LIBRARY_PATH&quot;)
  183. (files '(&quot;arm-zephyr-eabi/lib&quot;)))))
  184. (home-page &quot;https://zephyrproject.org&quot;)
  185. (synopsis &quot;GCC for zephyr RTOS&quot;))))</code></pre><p>This GCC can be built like so.</p><pre><code>guix build -L guix-zephyr gcc-cross-sans-libc-arm-zephyr-eabi
  186. /gnu/store/qmp8bzmwwimw0r6fh165hgfhkxkxilpj-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0-lib
  187. /gnu/store/38rli0rbn7ksmym3wq99cr4p2cjdz4a7-gcc-cross-sans-libc-arm-zephyr-eabi-12.1.0</code></pre><p>Great! We now have our stage-1 compiler.</p><h2>Newlib(-nano)</h2><p>The newlib package is quite straight forward (relatively).
  188. It is mostly adding in the relevent configuration flags and patching
  189. the files the <code>patch-shebangs</code> phase missed.</p><pre><code> (define-public zephyr-newlib
  190. (package
  191. (name &quot;zephyr-newlib&quot;)
  192. (version &quot;3.3&quot;)
  193. (source (origin
  194. (method git-fetch)
  195. (uri (git-reference
  196. (url &quot;https://github.com/zephyrproject-rtos/newlib-cygwin&quot;)
  197. (commit &quot;4e150303bcc1e44f4d90f3489a4417433980d5ff&quot;)))
  198. (sha256
  199. (base32 &quot;08qwjpj5jhpc3p7a5mbl7n6z7rav5yqlydqanm6nny42qpa8kxij&quot;))))
  200. (build-system gnu-build-system)
  201. (arguments
  202. `(#:out-of-source? #t
  203. #:configure-flags '(&quot;--target=arm-zephyr-eabi&quot;
  204. &quot;--enable-newlib-io-long-long&quot;
  205. &quot;--enable-newlib-io-float&quot;
  206. &quot;--enable-newlib-io-c99-formats&quot;
  207. &quot;--enable-newlib-retargetable-locking&quot;
  208. &quot;--enable-newlib-lite-exit&quot;
  209. &quot;--enable-newlib-multithread&quot;
  210. &quot;--enable-newlib-register-fini&quot;
  211. &quot;--enable-newlib-extra-sections&quot;
  212. &quot;--disable-newlib-wide-orient&quot;
  213. &quot;--disable-newlib-fseek-optimization&quot;
  214. &quot;--disable-newlib-supplied-syscalls&quot;
  215. &quot;--disable-newlib-target-optspace&quot;
  216. &quot;--disable-nls&quot;)
  217. #:phases
  218. (modify-phases %standard-phases
  219. (add-after 'unpack 'fix-references-to-/bin/sh
  220. (lambda _
  221. (substitute* '(&quot;libgloss/arm/cpu-init/Makefile.in&quot;
  222. &quot;libgloss/arm/Makefile.in&quot;
  223. &quot;libgloss/libnosys/Makefile.in&quot;
  224. &quot;libgloss/Makefile.in&quot;)
  225. ((&quot;/bin/sh&quot;) (which &quot;sh&quot;)))
  226. #t)))))
  227. (native-inputs
  228. `((&quot;xbinutils&quot; ,zephyr-binutils)
  229. (&quot;xgcc&quot; ,gcc-arm-zephyr-eabi-12)
  230. (&quot;texinfo&quot; ,texinfo)))
  231. (home-page &quot;https://www.sourceware.org/newlib/&quot;)
  232. (synopsis &quot;C library for use on embedded systems&quot;)
  233. (description &quot;Newlib is a C library intended for use on embedded
  234. systems. It is a conglomeration of several library parts that are easily
  235. usable on embedded products.&quot;)
  236. (license (license:non-copyleft
  237. &quot;https://www.sourceware.org/newlib/COPYING.NEWLIB&quot;))))</code></pre><p>And the build.</p><pre><code>guix build -L guix-zephyr zephyr-newlib
  238. /gnu/store/4lx37gga1jv3ckykrxsfgwy9slaamln4-zephyr-newlib-3.3</code></pre><h2>Complete toolchain</h2><p>Note that the toolchain is <em>Mostly</em> complete. libstdc++ does not build because
  239. `arm-zephyr-eabi` is not `arm-none-eabi` so a dynamic link check is
  240. performed/failed. I cannot figure out how crosstool-ng handles this.</p><p>Anyway, now that we’ve got the individual tools it’s time to create
  241. our complete toolchain. For this we need to do some package transformations.
  242. Because these transformations are must be done for every combination of
  243. binutils/gcc/newlib, it is best to create a function which we can reuse for
  244. every version of the SDK.</p><pre><code>(define (arm-zephyr-eabi-toolchain xgcc newlib version)
  245. &quot;Produce a cross-compiler zephyr toolchain package with the compiler XGCC and the C
  246. library variant NEWLIB.&quot;
  247. (let ((newlib-with-xgcc (package (inherit newlib)
  248. (native-inputs
  249. (alist-replace &quot;xgcc&quot; (list xgcc)
  250. (package-native-inputs newlib))))))
  251. (package
  252. (name (string-append &quot;arm-zephyr-eabi&quot;
  253. (if (string=? (package-name newlib-with-xgcc)
  254. &quot;newlib-nano&quot;)
  255. &quot;-nano&quot; &quot;&quot;)
  256. &quot;-toolchain&quot;))
  257. (version version)
  258. (source #f)
  259. (build-system trivial-build-system)
  260. (arguments
  261. '(#:modules ((guix build union)
  262. (guix build utils))
  263. #:builder
  264. (begin
  265. (use-modules (ice-9 match)
  266. (guix build union)
  267. (guix build utils))
  268. (let ((out (assoc-ref %outputs &quot;out&quot;)))
  269. (mkdir-p out)
  270. (match %build-inputs
  271. (((names . directories) ...)
  272. (union-build (string-append out &quot;/arm-zephyr-eabi&quot;)
  273. directories)
  274. #t))))))
  275. (inputs
  276. `((&quot;binutils&quot; ,zephyr-binutils)
  277. (&quot;gcc&quot; ,xgcc)
  278. (&quot;newlib&quot; ,newlib-with-xgcc)))
  279. (synopsis &quot;Complete GCC tool chain for ARM zephyrRTOS development&quot;)
  280. (description &quot;This package provides a complete GCC tool chain for ARM
  281. bare metal development with zephyr rtos. This includes the GCC arm-zephyr-eabi cross compiler
  282. and newlib (or newlib-nano) as the C library. The supported programming
  283. language is C.&quot;)
  284. (home-page (package-home-page xgcc))
  285. (license (package-license xgcc)))))</code></pre><p>This function creates a special package which consists of the toolchain in a special directory hierarchy, i.e <code>arm-zephyr-eabi/</code>.
  286. Our complete toolchain definition looks like this.</p><pre><code>(define-public arm-zephyr-eabi-toolchain-0.15.0
  287. (arm-zephyr-eabi-toolchain
  288. gcc-arm-zephyr-eabi-12
  289. zephyr-newlib
  290. &quot;0.15.0&quot;))</code></pre><p>To build:</p><pre><code>guix build -L guix-zephyr arm-zephyr-eabi-toolchain
  291. /gnu/store/9jnanr27v6na5qq3dlgljraysn8r1sad-arm-zephyr-eabi-toolchain-0.15.0</code></pre><h1>Integrating with Zephyr Build System</h1><p>Zephyr uses CMake as it’s build system. It contains numerous CMake files in both the so-called <code>ZEPHYR_BASE</code>,
  292. the zephyr source code repository, as well as a handful in the SDK which help select the correct toolchain
  293. for a given board.</p><p>There are standard locations the build system will look for the SDK. We are not
  294. using any of them. Our SDK lives in the store, immutable forever. According to
  295. <a href="https://docs.zephyrproject.org/latest/develop/west/without-west.html">this
  296. webpage</a>,
  297. the variable <code>ZEPHYR_SDK_INSTALL_DIR</code> needs to point to our custom spot.</p><p>We also need to grab the cmake files from the <a href="https://github.com/zephyrproject-rtos/sdk-ng">repository</a> and create a file <code>sdk_version</code> which
  298. contains the version string <code>ZEPHYR_BASE</code> uses to find a compatible SDK.</p><p>Along with the SDK proper we need to include a number of python packages required by the build system.</p><pre><code> (define-public zephyr-sdk
  299. (package
  300. (name &quot;zephyr-sdk&quot;)
  301. (version &quot;0.15.0&quot;)
  302. (home-page &quot;https://zephyrproject.org&quot;)
  303. (source (origin (method git-fetch)
  304. (uri (git-reference
  305. (url &quot;https://github.com/zephyrproject-rtos/sdk-ng&quot;)
  306. (commit &quot;v0.15.0&quot;)))
  307. (file-name (git-file-name name version))
  308. (sha256 (base32 &quot;04gsvh20y820dkv5lrwppbj7w3wdqvd8hcanm8hl4wi907lwlmwi&quot;))))
  309. (build-system trivial-build-system)
  310. (arguments
  311. `(#:modules ((guix build union)
  312. (guix build utils))
  313. #:builder
  314. (begin
  315. (use-modules (guix build union)
  316. (ice-9 match)
  317. (guix build utils))
  318. (let* ((out (assoc-ref %outputs &quot;out&quot;))
  319. (cmake-scripts (string-append (assoc-ref %build-inputs &quot;source&quot;)
  320. &quot;/cmake&quot;))
  321. (sdk-out (string-append out &quot;/zephyr-sdk-0.15.0&quot;)))
  322. (mkdir-p out)
  323. (match (assoc-remove! %build-inputs &quot;source&quot;)
  324. (((names . directories) ...)
  325. (union-build sdk-out directories)))
  326. (copy-recursively cmake-scripts
  327. (string-append sdk-out &quot;/cmake&quot;))
  328. (with-directory-excursion sdk-out
  329. (call-with-output-file &quot;sdk_version&quot;
  330. (lambda (p)
  331. (format p &quot;0.15.0&quot;)))
  332. #t)))))
  333. (propagated-inputs
  334. (list
  335. arm-zephyr-eabi-toolchain-0.15.0
  336. zephyr-binutils
  337. dtc))
  338. (native-search-paths
  339. (list (search-path-specification
  340. (variable &quot;ZEPHYR_SDK_INSTALL_DIR&quot;)
  341. (files '(&quot;&quot;)))))
  342. (synopsis &quot;SDK for zephyrRTOS&quot;)
  343. (description &quot;zephyr-sdk contains bundles a complete gcc toolchain as well
  344. as host tools like dtc, openocd, qemu, and required python packages.&quot;)
  345. (license license:apsl2)))</code></pre><h2>Testing</h2><p>In order to test we will need an environment with the SDK installed.
  346. We can take advantage of <code>guix shell</code> to avoid installing test packages into
  347. our home environment. This way, if it causes problems, we can just exit the shell
  348. and try again.</p><pre><code>guix shell -L guix-zephyr zephyr-sdk cmake ninja git</code></pre><p><code>ZEPHYR_BASE</code> can be cloned into a temporary workspace to test our toolchain
  349. functionality (For now. Eventually we will need to create a package for
  350. <code>zephyr-base</code> that our guix zephyr-build-system can use).</p><pre><code>mkdir /tmp/zephyr-project
  351. cd /tmp/zephyr-project
  352. git clone https://github.com/zephyrproject-rtos/zephyr
  353. export ZEPHYR_BASE=/tmp/zephyr-project/zephyr</code></pre><p>In order to build for the test board (k64f in this case) we need to get a hold
  354. of the vendor Hardware Abstraction Layers and CMSIS (These will also need to
  355. become guix packages to allow the build system to compose modules).</p><pre><code>git clone https://github.com/zephyrproject-rtos/hal_nxp &amp;&amp;
  356. git clone https://github.com/zephyrproject-rtos/cmsis</code></pre><p>To inform the build system about this module we pass it in with <code>-DZEPHYR_MODULES=</code> which is
  357. a semicolon separated list of paths containing a module.yml file.</p><p>To build the hello world sample we use the following incantation.</p><pre><code>cmake -Bbuild $ZEPHYR_BASE/samples/hello_world \
  358. -GNinja \
  359. -DBOARD=frdm_k64f \
  360. -DBUILD_VERSION=3.1.0 \
  361. -DZEPHYR_MODULES=&quot;/tmp/zephyr-project/hal_nxp;/tmp/zephyr-project/cmsis&quot; \
  362. &amp;&amp; ninja -Cbuild</code></pre><p>If everything is set up correctly we will end up with a <code>./build</code>
  363. directory with all our build artifacts. The SDK is installed correctly!</p></div></article></section></main><footer><p>© 2020 Joshua Branson. The text on this site is free culture under the Creative Commons Attribution Share-Alike 4.0 International license.</p><p>This website is build with Haunt, a static site generator written in Guile Scheme. Source code is <a href="https://notabug.org/jbranso/gnucode.me">available.</a></p><p>The color theme of this website is based off of the famous <a href="#3f3f3f" target="_blank">zenburn</a> theme.</p></footer></body>