[bug#35110,1/3] gnu: Add make-linux-module.

Message ID 20190402192855.5314-1-dannym@scratchpost.org
State Accepted
Headers show
Series Add support for loadable modules. | expand

Checks

Context Check Description
cbaines/applying patch fail Apply failed

Commit Message

Danny Milosavljevic April 2, 2019, 7:28 p.m. UTC
* gnu/packages/linux.scm (make-linux-module): New procedure.
---
 gnu/packages/linux.scm | 66 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

Comments

Ludovic Courtès April 3, 2019, 8:16 p.m. UTC | #1
Hi Danny,

Danny Milosavljevic <dannym@scratchpost.org> skribis:

> * gnu/packages/linux.scm (make-linux-module): New procedure.

Neat!

Would it make sense to turn it into a ‘linux-module-build-system’?  That
would avoid having to create a package object that cannot be built, just
to pass it to ‘make-linux-module’.  ‘linux-libre’ and ‘kmod’ would be
implicit inputs.

> +;; FIXME: Remove CONFIG_MODULE_SRCVERSION_ALL=y from our configs.

What does that flag do?

> +      (name (string-append (package-name module) "-" (package-name linux)))
> +      (native-inputs
> +       `(("linux-source" ,linux-source)
> +         ("kmod" ,kmod)
> +         ;("elfutils" ,elfutils)  ; Needed to enable CONFIG_STACK_VALIDATION
> +         ("gcc" ,gcc-7)

Is it OK to use the default GCC?

Other than that it looks really cool!

Thank you,
Ludo’.
Danny Milosavljevic April 3, 2019, 8:48 p.m. UTC | #2
Hi Ludo,

On Wed, 03 Apr 2019 22:16:07 +0200
Ludovic Courtès <ludo@gnu.org> wrote:

> Would it make sense to turn it into a ‘linux-module-build-system’?  

I started on it but haven't finished it yet.

>That would avoid having to create a package object that cannot be built, just

It can be built, it's just not very useful standalone because it only contains
the source code and a few build artifacts (only the ones required to start
building a module).  On the other hand it can be substituted and that's nice
(if we can cut down the source code a lot, that is).

I don't understand how a build system would enable us to remove this step.
(If it can, that's cool!)

> to pass it to ‘make-linux-module’.  ‘linux-libre’ and ‘kmod’ would be
> implicit inputs.
> 
> > +;; FIXME: Remove CONFIG_MODULE_SRCVERSION_ALL=y from our configs.  
> 
> What does that flag do?

It adds a field "srcversion" to the ELF file of the module which is a hash of
all the source files used to build it.

Instead of removing it, we can also merge bug# 35111 instead and use that.

Otherwise, the problem is that if CONFIG_MODULE_SRCVERSION_ALL is set and
bug# 35111 not merged, one cannot build standalone modules because those
would require the file "Module.symvers" of the completely built kernel
to be available.

Linux would also write a new file "Module.symvers" in the MODPOST step of
the build of the module.

> Is it OK to use the default GCC?

Definitely not.  It has to be exactly the same gcc as used in building the
Linux kernel.

> Other than that it looks really cool!

It's just a quick hack.

I've started with the build system but it was too much work and I didn't
understand the mechanisms well enough.

For example, the lowest maintenance overhead would be to somehow have
most of linux-libre's phases be injected into the module package and have
both build in one build environment.  I.e. the module would have a package
which would actually have phases 'unpack 'prepare-linux 'build 'check 'install
where all the phases except for 'prepare-linux would be module-specific and
'prepare-linux would unpack the linux source and do everything just
like the linux-libre package would have done, up until the 'build phase.
It turned out that's too complicated to get to work for me for now.
Ludovic Courtès April 4, 2019, 7:48 a.m. UTC | #3
Hi Danny,

Danny Milosavljevic <dannym@scratchpost.org> skribis:

> On Wed, 03 Apr 2019 22:16:07 +0200
> Ludovic Courtès <ludo@gnu.org> wrote:
>
>> Would it make sense to turn it into a ‘linux-module-build-system’?  
>
> I started on it but haven't finished it yet.
>
>>That would avoid having to create a package object that cannot be built, just
>
> It can be built, it's just not very useful standalone because it only contains
> the source code and a few build artifacts (only the ones required to start
> building a module).  On the other hand it can be substituted and that's nice
> (if we can cut down the source code a lot, that is).

Can it be built (I’m talking about the ‘vhba-module’ package that you
sent)?  I’d expect it to look for the Linux makefile snippet and to fail
at that point, no?

> I don't understand how a build system would enable us to remove this step.
> (If it can, that's cool!)

We’d directly write:

  (define-public vhba-module
    (package
      (name "vhba-module")
      ;; …
      (build-system linux-module-build-system))

and that would abstract away the choice of dependencies (linux-libre,
kmod, GCC) and the set of build phases.

>> > +;; FIXME: Remove CONFIG_MODULE_SRCVERSION_ALL=y from our configs.  
>> 
>> What does that flag do?
>
> It adds a field "srcversion" to the ELF file of the module which is a hash of
> all the source files used to build it.
>
> Instead of removing it, we can also merge bug# 35111 instead and use that.
>
> Otherwise, the problem is that if CONFIG_MODULE_SRCVERSION_ALL is set and
> bug# 35111 not merged, one cannot build standalone modules because those
> would require the file "Module.symvers" of the completely built kernel
> to be available.
>
> Linux would also write a new file "Module.symvers" in the MODPOST step of
> the build of the module.

OK.  Sounds like we should merge #35111 then.

> For example, the lowest maintenance overhead would be to somehow have
> most of linux-libre's phases be injected into the module package and have
> both build in one build environment.  I.e. the module would have a package
> which would actually have phases 'unpack 'prepare-linux 'build 'check 'install
> where all the phases except for 'prepare-linux would be module-specific and
> 'prepare-linux would unpack the linux source and do everything just
> like the linux-libre package would have done, up until the 'build phase.
> It turned out that's too complicated to get to work for me for now.

What about factorizing these phases in a new (guix build
linux-module-build-system) module, which would export them as
‘%standard-phases’?  Then packages using ‘linux-module-build-system’
would use these phases by default, like we do for the other build
systems.

Does that make sense?

Thank you,
Ludo’.

Patch

diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 9e4261eb02..55a314258f 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -415,6 +415,72 @@  for ARCH and optionally VARIANT, or #f if there is no such configuration."
 It has been modified to remove all non-free binary blobs.")
     (license license:gpl2)))
 
+;; FIXME: Remove CONFIG_MODULE_SRCVERSION_ALL=y from our configs.
+(define (make-linux-module linux module)
+  "Given a LINUX package and a MODULE package, build MODULE using LINUX."
+  (let ((linux-source
+         (package
+           (inherit linux)
+           (name "linux-source")
+           (arguments
+             (substitute-keyword-arguments (package-arguments linux)
+              ((#:phases phases)
+               `(modify-phases ,phases
+                  (replace 'build
+                    (lambda _
+                      (invoke "make" "modules_prepare")))
+                  (delete 'strip) ; faster.
+                  (replace 'install
+                    (lambda* (#:key outputs #:allow-other-keys)
+                      (let* ((out (assoc-ref outputs "out"))
+                             (out-lib-build (string-append out "/lib/modules/build")))
+                        ; TODO: Only preserve the minimum, i.e. [Kbuild], Kconfig, scripts, include, ".config".
+                        (copy-recursively "." out-lib-build)
+                        #t))))))))))
+    (package
+      (inherit module)
+      (name (string-append (package-name module) "-" (package-name linux)))
+      (native-inputs
+       `(("linux-source" ,linux-source)
+         ("kmod" ,kmod)
+         ;("elfutils" ,elfutils)  ; Needed to enable CONFIG_STACK_VALIDATION
+         ("gcc" ,gcc-7)
+         ,@(package-native-inputs module)))
+      (arguments
+        (substitute-keyword-arguments
+         (default-keyword-arguments (package-arguments module)
+          `(#:phases #f
+            #:make-flags '()))
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (replace 'build
+               (lambda* (#:key inputs make-flags #:allow-other-keys)
+                 (apply invoke "make" "-C"
+                        (string-append (assoc-ref inputs "linux-source")
+                                       "/lib/modules/build")
+                        (string-append "M=" (getcwd))
+                        make-flags)))
+         ;; This block was copied from make-linux-libre--only took the
+         ;; "modules_install" part.
+         (replace 'install
+           (lambda* (#:key inputs native-inputs outputs #:allow-other-keys)
+             (let* ((out    (assoc-ref outputs "out"))
+                    (moddir (string-append out "/lib/modules"))
+                    (kmod   (assoc-ref (or native-inputs inputs) "kmod")))
+               ;; Install kernel modules
+               (mkdir-p moddir)
+               (invoke "make"
+                       "-C"
+                       (string-append (assoc-ref inputs "linux-source")
+                                      "/lib/modules/build")
+                       (string-append "M=" (getcwd))
+                       (string-append "DEPMOD=" kmod "/bin/depmod")
+                       (string-append "MODULE_DIR=" moddir)
+                       (string-append "INSTALL_PATH=" out)
+                       (string-append "INSTALL_MOD_PATH=" out)
+                       "INSTALL_MOD_STRIP=1"
+                       "modules_install")))))))))))
+
 (define %linux-libre-version "5.0.5")
 (define %linux-libre-hash "1yivxqprxfzhzid4qv9hpnb5i38kijrj2g2pyzz7niliya1c58li")