guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

01/01: website: Add Guixdays ARM hacking post.


From: Efraim Flashner
Subject: 01/01: website: Add Guixdays ARM hacking post.
Date: Wed, 6 Feb 2019 12:48:30 -0500 (EST)

efraim pushed a commit to branch master
in repository guix-artwork.

commit 46aa06e444fef8944f523452e0cc88c51e231c93
Author: Efraim Flashner <address@hidden>
Date:   Wed Feb 6 19:43:06 2019 +0200

    website: Add Guixdays ARM hacking post.
    
    * website/posts/guixdays-arm-hacking.md: New file.
---
 website/posts/guixdays-arm-hacking.md | 310 ++++++++++++++++++++++++++++++++++
 1 file changed, 310 insertions(+)

diff --git a/website/posts/guixdays-arm-hacking.md 
b/website/posts/guixdays-arm-hacking.md
new file mode 100644
index 0000000..5304482
--- /dev/null
+++ b/website/posts/guixdays-arm-hacking.md
@@ -0,0 +1,310 @@
+title: QA on non-Intel at Guix Days
+date: 2019-02-06 19:30
+author: Efraim Flashner
+tags: ARM, Guix Hackathon, FOSDEM
+---
+
+During the second day of Guix Days (a FOSDEM [fringe
+event](https://fosdem.org/2019/fringe)) we split up into smaller working groups
+based on our areas of interest. I led a group which aimed to address some of
+the package issues which exist on non-Intel architectures. Of course not
+everyone has access to an ARM board, but with the
+[`qemu-binfmt-service`](http://guix.info/manual/en/Virtualization-Services.html#Virtualization-Services)
+service it is possible to use QEMU and the `binfmt_misc` functionality of the
+Linux kernel to emulate these systems. Many have reported that this system
+emulation is comparable in speed to many of the available ARM boards on the
+market. Yet another possibility would be to do the hacking on an x86_64 system
+and, when we had a working prototype, to test it with QEMU or on actual ARM
+hardware.
+
+Our group decided to tackle Go, which was lacking support in Guix on armhf and
+aarch64. Upon checking the build logs from Cuirass and the source code for Go 
we
+determined that Go did indeed require the `gold` linker from `binutils`. We
+didn't want to modify the copy of `binutils` in Guix since it is part of our
+bootstrap story, so we quickly put together a new package definition which 
added
+the configure flag to enable `gold`.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     (substitute-keyword-arguments (package-arguments binutils)
+       ((#:configure-flags flags)
+        `(cons "--enable-gold=default" ,flags))))))
+```
+
+This was an obvious first step, and one which we knew would fail. Had it been
+this easy `gold` would have been enabled back in 2012 when it was first added.
+Our error came in the form of one of the binaries not being able to link 
against
+libstdc++.so, which is in the `gcc:lib` output. This was quickly added and we
+were off and building again.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     (substitute-keyword-arguments (package-arguments binutils)
+       ((#:configure-flags flags)
+        `(cons "--enable-gold=default" ,flags))))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+Once again this failed. What were we missing? The correct paths were included,
+the file was indeed in the `gcc:lib` output. We inspected the original
+`binutils` package again noticed that it was built against a static libgcc, so
+of course it wouldn't find the shared library. In order to work quickly we
+copied the configure flags rather than inheriting them from `binutils` and
+tried our build again.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     (substitute-keyword-arguments (package-arguments binutils)
+       ((#:configure-flags flags)
+        `(cons* "--enable-gold=default"
+                "--enable-new-dtags"
+                "--with-lib-path=/no-ld-lib-path"
+                "--enable-install-libbfd"
+                "--enable-deterministic-archives"))))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+This time we made it through the full build phase and we knew we were almost
+there. Our enthusiasm was quickly dampened when we got the error during the
+tests "unable to find the 'dc' program". What is this `dc` program? This isn't
+any package any of us had heard of before. It definitely wasn't packaged in
+Guix. A quick `apt-cache search dc` search in Ubuntu showed they didn't have
+package either. A second search of Ubuntu, `apt-file search dc | grep 
'/bin/dc'`
+quickly showed us it was in the `bc` package, and soon we were building
+`binutils-gold` again.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     (substitute-keyword-arguments (package-arguments binutils)
+       ((#:configure-flags flags)
+        `(cons* "--enable-gold=default"
+                "--enable-new-dtags"
+                "--with-lib-path=/no-ld-lib-path"
+                "--enable-install-libbfd"
+                "--enable-deterministic-archives"))))
+    (native-inputs
+     `(("bc" ,bc)))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+Approaching the end of the check phase we soon ran into another error, there
+was an unpatched `/bin/sh` somewhere in the source code which was generated
+during the check phase. Based on the build logs we were able to track down
+approximately where the code should be, so we downloaded the source `tar xf
+$(guix build --source binutils)` and started looking. There were many obvious
+`/bin/sh` calls which we cross-referenced with the build logs and the
+'patch-source-shebangs phase, and this left us with some code in
+`gold/Makefile.in`, which by default is not included in the
+'patch-source-shebangs and would need to be fixed manually.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'patch-source-shebangs 'patch-more-shebangs
+           (lambda _
+             (substitute* "gold/Makefile.in"
+               (("/bin/sh") (which "sh")))
+             #t)))
+       ,@(substitute-keyword-arguments (package-arguments binutils)
+         ((#:configure-flags flags)
+          `(cons* "--enable-gold=default"
+                  "--enable-new-dtags"
+                  "--with-lib-path=/no-ld-lib-path"
+                  "--enable-install-libbfd"
+                  "--enable-deterministic-archives")))))
+    (native-inputs
+     `(("bc" ,bc)))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+One more build cycle later and we did it! `/gnu/store/...-binutils-gold-2.31.1`
+existed! We now did two things, we copied our patch over to an aarch64 build
+machine and we started cleaning up our package definition on our x86_64 build
+machine, where we knew we had a working package definition.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'patch-source-shebangs 'patch-more-shebangs
+           (lambda _
+             (substitute* "gold/Makefile.in"
+               (("/bin/sh") (which "sh")))
+             #t)))
+       ,@(substitute-keyword-arguments (package-arguments binutils)
+         ((#:configure-flags flags)
+          `(cons* "--enable-gold=default"
+                  (delete "LDFLAGS=-static-libgcc" ,flags))))))
+    (native-inputs
+     `(("bc" ,bc)))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+Fortunately for us the changes in the code worked on x86_64 and we still got a
+working binutils-gold output. On our aarch64 side the build was progressing
+nicely and everything seemed fine... until we suddenly were presented with big
+red errors about unrelocatable code. How could it? Everything was working so
+well! Undeterred, we built the source again, this time targeting armhf and were
+unfortunately presented with similar errors. Deciding to address the test
+failures later (It's ARM! It's not as well tested as other architectures!
+Right?) we disabled the tests and unsurprisingly `binutils-gold` built on both
+aarch64-and armhf.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'patch-source-shebangs 'patch-more-shebangs
+           (lambda _
+             (substitute* "gold/Makefile.in"
+               (("/bin/sh") (which "sh")))
+             #t)))
+       ,@(substitute-keyword-arguments (package-arguments binutils)
+         ((#:tests? _ #f) #f)
+         ((#:configure-flags flags)
+          `(cons* "--enable-gold=default"
+                  (delete "LDFLAGS=-static-libgcc" ,flags))))))
+    (native-inputs
+     `(("bc" ,bc)))
+    (inputs
+     `(("gcc:lib" ,gcc "lib")))))
+```
+
+Now for the real test. Due to bootstrapping issues with Go and aarch64, aarch64
+uses address@hidden built for armhf. address@hidden failed to build until now 
because it was
+missing the `gold` linker. Surely using the `gold` linker would be a good test
+if our package worked. Since Go for aarch64 is 'more complex' due to the
+bootstrapping using armhf's Go, we decided to test armhf first. `binutils-gold`
+was added and our build started.
+
+```diff
+    (native-inputs
+     `(("go" ,go-1.4)
++      ,@(match (%current-system)
++          ((or "armhf-linux" "aarch64-linux")
++           `(("gold" ,binutils-gold)))
++          (_ `()))
+       ,@(package-native-inputs go-1.4)))
+```
+
+First build, success! `/gnu/store/...-go-1.11.5` exists! OK, but does it
+actually work? `guix build syncthing --system=armhf-linux`.
+`/gnu/store/...-syncthing-1.0.0` exists too! A quick check of `guix refresh
+--list-dependent address@hidden showed that we had unlocked 176 new packages 
for armhf.
+Even better, since they had all failed by default due to address@hidden 
failing to
+build, for each package that did build meant one fewer package which failed to
+build which should take a big bite out of our build failures.
+
+Our next test was syncthing for aarch64. `/gnu/store/...-go-1.11.5` exists!
+`/gnu/store/..-syncthing-1.0.0` ... does not. "unknown architecture 'armv7-a'."
+It seems that Go is confused which architecture it is building for.
+Unfortunately we were reaching the end of our time for hacking, so that will
+have to wait for another day. All that was left now was the test failures on
+binutils-gold for the ARM systems. Some attempts at cargo-culting other code
+failed (per-architecture tests we had and overriding flags in
+substitute-keyword-arguments we had, but not together), but after some attempts
+we were able to create a working package definition we were happy with.
+
+```scheme
+(define-public binutils-gold
+  (package
+    (inherit binutils)
+    (name "binutils-gold")
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'patch-source-shebangs 'patch-more-shebangs
+           (lambda _
+             (substitute* "gold/Makefile.in"
+               (("/bin/sh") (which "sh")))
+             #t)))
+       ,@(substitute-keyword-arguments (package-arguments binutils)
+         ; Upstream is aware of unrelocatable test failures on arm*.
+         ((#:tests? _ #f)
+          (if (any (cute string-prefix? <> (or (%current-target-system)
+                                               (%current-system)))
+                   '("i686" "x86_64"))
+              '#t '#f))
+         ((#:configure-flags flags)
+          `(cons* "--enable-gold=default"
+                 (delete "LDFLAGS=-static-libgcc" ,flags))))))
+     (native-inputs
+      `(("bc" ,bc)))
+     (inputs
+      `(("gcc:lib" ,gcc "lib")))))
+```
+
+This patch was pushed to the master branch as
+[28317d499034b00cf1f08a9efd39bd2bc3425b19](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=28317d499034b00cf1f08a9efd39bd2bc3425b19),
+and the
+[commit](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=1009e6e7ecc00b72a51778e90b0212ccc33bfa7a)
+following uses it as a native-input for address@hidden and address@hidden 
address@hidden was added in
+[June
+2016](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=7a2941a83ee8ecac9ca7a3a076b1231805b39bbd)
+and address@hidden that
+[August](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=ec91bcb500a2540b91fca6fd2a93a0562c427712),
+with our first go packages being added in [October
+2017](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=56a37713c3fada3010666278eb37873980746572).
+That same
+[October](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=dda785f66081871501236722f68c8eaa31103186)
address@hidden had support limited to Intel and armhf and in October 2018, in 
an effort
+to work toward a resolution, a
+[patch](https://git.savannah.gnu.org/cgit/guix.git/commit/?id=2ab321ca37d1c00c1540d78d587226d3d487b2d4)
+was added to have aarch64 use address@hidden built for armhf for it's 
bootstrap path.
+Basically since the addition of the Go language support into Guix there was not
+a time when it was usable on armhf or aarch64. Hopefully we will soon finish
+getting full Go support on aarch64 and we can move all 352 dependents of 
address@hidden
+from "failing" to "succeeding" and have these architectures better supported.
+
+#### About GNU Guix
+
+[GNU Guix](https://www.gnu.org/software/guix) is a transactional package
+manager and an advanced distribution of the GNU system that [respects
+user
+freedom](https://www.gnu.org/distros/free-system-distribution-guidelines.html).
+Guix can be used on top of any system running the kernel Linux, or it
+can be used as a standalone operating system distribution for i686,
+x86_64, ARMv7, and AArch64 machines.
+
+In addition to standard package management features, Guix supports
+transactional upgrades and roll-backs, unprivileged package management,
+per-user profiles, and garbage collection.  When used as a standalone
+GNU/Linux distribution, Guix offers a declarative, stateless approach to
+operating system configuration management.  Guix is highly customizable
+and hackable through [Guile](https://www.gnu.org/software/guile)
+programming interfaces and extensions to the
+[Scheme](http://schemers.org) language.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]