all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Help defining a trivial package.
@ 2019-08-23 19:42 Pierre-Henry F.
  2019-08-25 12:17 ` Timothy Sample
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre-Henry F. @ 2019-08-23 19:42 UTC (permalink / raw)
  To: help-guix\@gnu.org

Hello!

Would someone help defining a trivial package?

Essentially:

    …/releases$ tree

    .

    ├── release_1.tar.lz

    ├── release_2.tar.lz

    └── release_3.tar.lz

    …/release_3$ tree

    .

    ├── bin

    │   └── program

    └── src

        └── hello_world.py

    …/release_3$ cat ./bin/program

    #! /usr/bin/env bash

    script_path="${BASH_SOURCE[0]}"

    script_dir="$(dirname $script_path)"

    python3 "$script_dir/../src/hello_world.py"

    …/release_3$ ./bin/program

    Hello world!

Defining this package would mean:

  1. download the release_3.tar.lz

  2. uncompress release_3.tar.lz

  3. add ~…/release_3/bin~ to the path

     - where ~…~ is the path in the store

-----------------------------------------

expected conclusion:

  $ which program

  …/release_3/bin/program

  $ program

  Hello World!

Here is an attempt at defining the package (incomplete, does not work) in blog.scm:

    (define-module (blog)

      #:use-module (guix packages)

      #:use-module (guix download)

      #:use-module (guix build-system trivial)

      #:use-module (guix licenses)

      #:use-module (gnu packages python))

    (define-public blog

      (package

        (name "blog")

        (version "3")

        (source

          (origin

            (method url-fetch)

            (uri (string-append "/home/phf/programs/blog/release_" version ".tar.lz"))

            (sha256

              (base32

                "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))

        (build-system trivial-build-system)

        (arguments

          '(#:builder #~(begin

                          (mkdir #$output)

                          (chdir #$output)

                          ...

                          )))

        (inputs `(("python" ,python)))

        (synopsis "Guix 'hello world' to learn about Guix")

        (license gpl3+)))

Here is the line that I use to try to build and debug along the way:

    $ guix build --keep-failed --verbosity=2 --file=./blog.scm

Thank you for your answers !

Pierre-Henry

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Help defining a trivial package.
  2019-08-23 19:42 Help defining a trivial package Pierre-Henry F.
@ 2019-08-25 12:17 ` Timothy Sample
  2019-08-29 11:23   ` Pierre-Henry F.
  0 siblings, 1 reply; 7+ messages in thread
From: Timothy Sample @ 2019-08-25 12:17 UTC (permalink / raw)
  To: Pierre-Henry F.; +Cc: help-guix@gnu.org

Hi Pierre,

"Pierre-Henry F." <contact@phfrohring.com> writes:

> Would someone help defining a trivial package?

Sure!

> Here is an attempt at defining the package (incomplete, does not work) in blog.scm:
>
>     (define-module (blog)
>       #:use-module (guix packages)
>       #:use-module (guix download)
>       #:use-module (guix build-system trivial)
>       #:use-module (guix licenses)
>       #:use-module (gnu packages python))
>
>     (define-public blog
>       (package
>         (name "blog")
>         (version "3")
>         (source
>           (origin
>             (method url-fetch)
>             (uri (string-append "/home/phf/programs/blog/release_" version ".tar.lz"))
>             (sha256
>               (base32
>                 "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))
>         (build-system trivial-build-system)
>         (arguments
>           '(#:builder #~(begin
>                           (mkdir #$output)
>                           (chdir #$output)
>                           ...
>                           )))
>         (inputs `(("python" ,python)))
>         (synopsis "Guix 'hello world' to learn about Guix")
>         (license gpl3+)))
>
> Here is the line that I use to try to build and debug along the way:
>
>     $ guix build --keep-failed --verbosity=2 --file=./blog.scm
>

As a note for the future, it would be helpful to include the error
message that you saw when things went wrong.  Here, I’m assuming that
Guix said:

    guix build: error: #<unspecified>: not something we can build

Running “guix build --file=X” causes Guix to build the last expression
evaluated in the file “X”.  In your case, the last expression that gets
evaluated is the “define-public” form, which returns an unspecified
value.

While testing, you can put “blog” at the bottom of the file, causing
Guix to build your defined “blog” package.

Hope that helps!


-- Tim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Help defining a trivial package.
  2019-08-25 12:17 ` Timothy Sample
@ 2019-08-29 11:23   ` Pierre-Henry F.
  2019-08-29 15:26     ` Timothy Sample
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre-Henry F. @ 2019-08-29 11:23 UTC (permalink / raw)
  To: Timothy Sample; +Cc: help-guix\@gnu.org

> As a note for the future, it would be helpful to include the error
> message that you saw when things went wrong.  Here, I’m assuming that
> Guix said:
>
>     guix build: error: #<unspecified>: not something we can build
>
> Running “guix build --file=X” causes Guix to build the last expression
> evaluated in the file “X”.  In your case, the last expression that gets
> evaluated is the “define-public” form, which returns an unspecified
> value.
>
> While testing, you can put “blog” at the bottom of the file, causing
> Guix to build your defined “blog” package.
>
> Hope that helps!
>
>
> -- Tim

Great :-) !

So, we have, in ~bash~:

  $ lzip --decompress release_3.tar.lz
  $ tar xf release_3.tar
  $ cd blog/ # coming from the preceding line.
  $ tree
  .
  ├── bin
  │   └── program
  └── src
      └── hello_world.py

  $ cat src/hello_world.py
  print("Hello world!")

  $ cat bin/program
  #! /usr/bin/env bash

  script_path="${BASH_SOURCE[0]}"
  script_dir="$(dirname $script_path)"
  python3 "$script_dir/../src/hello_world.py"

That's it.

The idea is to build a Guix package that does exactly that.
Expected outcome:

  $ guix package -s blog
  # fetch release_3.tar.lz
  # uncompress ...
  # ...

  $ program
  Hello World!


My question: how to build that Guix package?  I try to get something working using
the docs.  This is how the package looks to far:

  (use-modules
    (guix packages)
    (guix download)
    (guix build-system trivial)
    (guix licenses)
    (guix gexp)
    (gnu packages base)
    (gnu packages python))


  ;; The "derivation" i.e. low level sequence of instructions that the build deamon is
  ;; supposed to execute on the behalf of the user.
  (define build-drv
    (gexp->derivation
      "the-thing"
      #~(begin
          (mkdir #$output)
          (chdir #$output)
          (symlink (string-append #$coreutils "/bin/ls")
            "list-files"))))


  (package
    (name "blog")
    (version "3")
    (source
      (origin
        (method url-fetch)
        (uri (string-append "/home/phf/programs/blog/releases/release_" version ".tar.lz"))
        (sha256
          (base32
            "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))
    (build-system trivial-build-system)
    (arguments `(#:builder ,build-drv))

    (inputs `(("python" ,python)))
    (synopsis "Guix 'hello world' to learn about Guix")
    (description "Guess what GNU Hello prints!")
    (home-page "http://www.gnu.org/software/hello/")
    (license gpl3+))

Assuming everything else is correct, would you please help refine ~build-drv~ until
it matches the ~bash~ above ?

This is what the execution trace looks like:

  phf@f02c:~/tools/guix/packages$ guix build --keep-failed --verbosity=2 --file=./blog.scm
  substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
  building /gnu/store/8b0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv...
  ERROR: In procedure primitive-load:
  In procedure scm_lreadr: /gnu/store/zlbf2x6n4084v0cpw2rh9dydqmi5b2rn-blog-3-guile-builder:1:10: Unknown # object: #\<
  note: keeping build directory `/tmp/guix-build-blog-3.drv-2'
  builder for `/gnu/store/8b0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv' failed with exit code 1
  build of /gnu/store/8b0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv failed
  View build log at '/var/log/guix/drvs/8b/0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv.bz2'.
  guix build: error: build of `/gnu/store/8b0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv' failed

  phf@f02c:~/tools/guix/packages$ ll /tmp/guix-build-blog-3.drv-2
  total 140K
  drwxr-xr-x  2 phf  phf  4.0K Aug 29 13:14 ./
  drwxrwxrwt 21 root root 132K Aug 29 13:14 ../

Thanks !
PHF

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Help defining a trivial package.
  2019-08-29 11:23   ` Pierre-Henry F.
@ 2019-08-29 15:26     ` Timothy Sample
       [not found]       ` <Al-P-mUDUQnoUvF4kgNS_NeITvHjEDEvxG8Gmk9aMiXX2FTUfL0lbZAq5h4m54GIGNXPwM271CzLWwt5sgOt1JI6Z1wxqxSwWmpnPHu7I5A=@phfrohring.com>
  0 siblings, 1 reply; 7+ messages in thread
From: Timothy Sample @ 2019-08-29 15:26 UTC (permalink / raw)
  To: Pierre-Henry F.; +Cc: help-guix@gnu.org

[-- Attachment #1: Type: text/plain, Size: 3360 bytes --]

Hi Pierre,

"Pierre-Henry F." <contact@phfrohring.com> writes:

> So, we have, in ~bash~:
>
>   $ lzip --decompress release_3.tar.lz
>   $ tar xf release_3.tar
>   $ cd blog/ # coming from the preceding line.
>   $ tree
>   .
>   ├── bin
>   │   └── program
>   └── src
>       └── hello_world.py
>
>   $ cat src/hello_world.py
>   print("Hello world!")
>
>   $ cat bin/program
>   #! /usr/bin/env bash
>
>   script_path="${BASH_SOURCE[0]}"
>   script_dir="$(dirname $script_path)"
>   python3 "$script_dir/../src/hello_world.py"
>
> That's it.
>
> The idea is to build a Guix package that does exactly that.
> Expected outcome:
>
>   $ guix package -s blog
>   # fetch release_3.tar.lz
>   # uncompress ...
>   # ...
>
>   $ program
>   Hello World!
>
>
> My question: how to build that Guix package?  I try to get something working using
> the docs.  This is how the package looks to far:
>
>   (use-modules
>     (guix packages)
>     (guix download)
>     (guix build-system trivial)
>     (guix licenses)
>     (guix gexp)
>     (gnu packages base)
>     (gnu packages python))
>
>
>   ;; The "derivation" i.e. low level sequence of instructions that the build deamon is
>   ;; supposed to execute on the behalf of the user.
>   (define build-drv
>     (gexp->derivation
>       "the-thing"
>       #~(begin
>           (mkdir #$output)
>           (chdir #$output)
>           (symlink (string-append #$coreutils "/bin/ls")
>             "list-files"))))
>
>
>   (package
>     (name "blog")
>     (version "3")
>     (source
>       (origin
>         (method url-fetch)
>         (uri (string-append "/home/phf/programs/blog/releases/release_" version ".tar.lz"))
>         (sha256
>           (base32
>             "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))
>     (build-system trivial-build-system)
>     (arguments `(#:builder ,build-drv))
>
>     (inputs `(("python" ,python)))
>     (synopsis "Guix 'hello world' to learn about Guix")
>     (description "Guess what GNU Hello prints!")
>     (home-page "http://www.gnu.org/software/hello/")
>     (license gpl3+))
>
> Assuming everything else is correct, would you please help refine ~build-drv~ until
> it matches the ~bash~ above ?
>
> This is what the execution trace looks like:
>
>   phf@f02c:~/tools/guix/packages$ guix build --keep-failed --verbosity=2 --file=./blog.scm
>   substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
>   building /gnu/store/8b0gyazhgmc9rkrxir7vxpav0x28xk3d-blog-3.drv...
>   ERROR: In procedure primitive-load:
>   In procedure scm_lreadr: /gnu/store/zlbf2x6n4084v0cpw2rh9dydqmi5b2rn-blog-3-guile-builder:1:10: Unknown # object: #\<

This error is because you can’t pass a derivation object as the
“#:builder” argument.  It has to be some quoted Scheme code that can run
in the build environment.

I took a little time and wrote a package definition that matches your
example.  There are some things you could do to change your source code
to make it more in-line with what Guix expects, but I didn’t do that.  I
hope that an example dealing with what you have will be more helpful.

I’ve attached the package definition I came up with (note that I changed
the URL of the tarball).


[-- Attachment #2: phf.scm --]
[-- Type: text/plain, Size: 1668 bytes --]

(use-modules ((gnu packages base) #:select (tar))
             ((gnu packages bash) #:select (bash-minimal))
             ((gnu packages compression) #:select (lzip))
             ((gnu packages python) #:select (python))
             (guix)
             (guix build-system trivial))

(package
  (name "blog")
  (version "3")
  (source
   (origin
     (method url-fetch)
     (uri (string-append "file:///tmp/phf/release_" version ".tar.lz"))
     (sha256
      (base32
       "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))
  (build-system trivial-build-system)
  (arguments
   `(#:modules ((guix build utils))
     #:builder
     (begin
       (use-modules (guix build utils))
       ;; Unpack
       (let ((source (assoc-ref %build-inputs "source"))
             (tar (assoc-ref %build-inputs "tar"))
             (lzip (assoc-ref %build-inputs "lzip")))
         (setenv "PATH" (string-append tar "/bin"
                                       ":" lzip "/bin"))
         (invoke "tar" "--lzip" "-xvf" source))
       ;; Configure
       (let ((bash (assoc-ref %build-inputs "bash"))
             (python (assoc-ref %build-inputs "python")))
         (substitute* "blog/bin/program"
           (("/usr/bin/env bash") (string-append bash "/bin/bash"))
           (("python3") (string-append python "/bin/python3"))))
       ;; Install
       (let ((out (assoc-ref %outputs "out")))
         (chmod "blog/bin/program" #o775)
         (copy-recursively "blog" out)))))
  (inputs
   `(("bash" ,bash-minimal)
     ("python" ,python)))
  (native-inputs
   `(("lzip" ,lzip)
     ("tar" ,tar)))
  (synopsis #f)
  (description #f)
  (home-page #f)
  (license #f))

[-- Attachment #3: Type: text/plain, Size: 684 bytes --]


The builder code imports the “(guix build utils)” module, which has some
really handy shell-like functions like “invoke” for running programs,
“substitute*” which is like “sed -i”, and “copy-recursively”, which is
like “cp -r”.

The “Unpack” section sets up the “PATH” variable for Tar, and then
invokes “tar” to unpack the tarball.

The “Configure” section replaces the references to Bash and Python with
their absolute paths in the Guix store.

The “Install” section makes the “program” file executable then copies
the code into the Guix-provided output directory.

I hope that makes sense and good luck!


-- Tim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Help defining a trivial package.
       [not found]       ` <Al-P-mUDUQnoUvF4kgNS_NeITvHjEDEvxG8Gmk9aMiXX2FTUfL0lbZAq5h4m54GIGNXPwM271CzLWwt5sgOt1JI6Z1wxqxSwWmpnPHu7I5A=@phfrohring.com>
@ 2019-09-03  1:58         ` Timothy Sample
  2019-09-04 11:21           ` Pierre-Henry F.
  0 siblings, 1 reply; 7+ messages in thread
From: Timothy Sample @ 2019-09-03  1:58 UTC (permalink / raw)
  To: Pierre-Henry F.; +Cc: help-guix

Hello,

"Pierre-Henry F." <contact@phfrohring.com> writes:
>
> Hello Tim !
>
> I'm using a couple of hours here an there to try to rebuild the package you gave me (Thank you for that :-) ).
> So far, I've built a very stupid but "working" package (see below if you really want to ;-) ).

Looks good so far!

> Will answer on the mailing list for others to benefit from this exchange.

I’ve added the mailing list back in, then.  ;)

> Needless to say, it's not exactly obvious to figure these things out /a priori/.

For sure.  By using the trivial build system, you’re working at a pretty
low level.  It’s especially tough to learn both Guix and Guile at the
same time.  For your reference, here’s a sketch of what the “#:builder”
code would look like if it were Python:

    import os, shutil, stat, subprocess, guix.build.utils

    # Unpack
    source = _build_inputs["source"]
    tar = _build_inputs["tar"]
    lzip = _build_inputs["lzip"]
    os.putenv("PATH", ":".join([tar + "/bin", lzip + "/bin"]))
    subprocess.run(["tar", "--lzip", "-xvf", source])

    # Configure
    bash = _build_inputs["bash"]
    python = _build_inputs["python"]
    guix.build.utils.substitute("blog/bin/program",
                                [["/usr/bin/bash", bash + "/bin/bash"],
                                 ["python3", python + "/bin/python3"]])

    # Install
    out = _outputs["out"]
    os.chmod("blog/bin/program", 0o755)
    shutil.copytree("blog", out)

Here, “_build_inputs” and “_outputs” are set by Guix, and are
dictionaries.  For “_build_inputs”, the keys are the strings you put in
the “inputs” part of the package, and the values are the paths where the
packages are installed.  So, “_build_inputs["python"]” points to the
directory in the store where Python is installed.  We usually only have
one output, which is called “out”.  This is the path in the store where
we install the package being built.

The only other thing is that “guix.build.utils.substitute” is basically
just find-and-replace.  It takes the name of a file and a list of
two-element lists and replaces all the occurrences of the first elements
in the file with their corresponding second elements.

Obviously the Guile interfaces are a little different, but hopefully
this Rosetta Stone makes it easier to see what’s going on.

As an aside, ever since I learned that there’s a way to do quasiquotes
in Python [1], I’ve wondered how strange it would be if Guix were
written in Python.  Pretty strange!  :)

[1] https://macropy3.readthedocs.io/en/latest/reference.html#quasiquote

> Anyway, thanks!

You’re welcome!


-- Tim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Help defining a trivial package.
  2019-09-03  1:58         ` Timothy Sample
@ 2019-09-04 11:21           ` Pierre-Henry F.
  2019-09-04 17:34             ` Timothy Sample
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre-Henry F. @ 2019-09-04 11:21 UTC (permalink / raw)
  To: Timothy Sample; +Cc: help-guix@gnu.org

[-- Attachment #1: Type: text/plain, Size: 7873 bytes --]

> import os, shutil, stat, subprocess, guix.build.utils
>
> # Unpack
> source = _build_inputs["source"]
> tar = _build_inputs["tar"]
> lzip = _build_inputs["lzip"]
> os.putenv("PATH", ":".join([tar + "/bin", lzip + "/bin"]))
> subprocess.run(["tar", "--lzip", "-xvf", source])
>
> # Configure
> bash = _build_inputs["bash"]
> python = _build_inputs["python"]
> guix.build.utils.substitute("blog/bin/program",
> [["/usr/bin/bash", bash + "/bin/bash"],
> ["python3", python + "/bin/python3"]])
>
> # Install
> out = _outputs["out"]
> os.chmod("blog/bin/program", 0o755)
> shutil.copytree("blog", out)

Excellent!

It's exactly how I understand the thing now (same approach to understanding as in
SICP and CTM :-) )

I rebuild the package (Attachment: blog_v2.scm) you gave me and added traces so it gives this when
you execute the thing:

    phf@f02c:~/programs/blog/guix$ guix build --keep-failed --verbosity=2 --file=./blog_v2.scm
    substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
    building /gnu/store/yhmlzaa07rp324nkc888rbacw7yfarsc-blog-3.drv...
    blog/bin/
    blog/bin/program
    blog/src/
    blog/src/hello_world.py

    Start of build expression execution

    Show inputs
      %build-inputs = (
        (lzip . /gnu/store/2kwysbg8f175gmqmsd5kjggmy6hvxi5k-lzip-1.20)
        (tar . /gnu/store/ipx79bfj2mrc8npj7s3qi3zri11jfhaw-tar-1.30)
        (source . /gnu/store/4xcgzx85274qy4k7yxzadnb7rrq4hfnd-release_3.tar.lz)
        (bash . /gnu/store/y2c5x3xwfbdigdlbxzfbk2g15ayy56cx-bash-minimal-4.4.23)
        (python . /gnu/store/b7fqhszxl02g6pfm3vw6b3cjz472qrly-python-3.7.0))

    Show outputs
      %outputs = ((out . /gnu/store/4s8ij47drq8avldf5fq7inpicrz8dasn-blog-3))

    Unpack source

    Reference interpreters available in the build

    Make executable available to the host system
    `blog/src/hello_world.py' -> `/gnu/store/4s8ij47drq8avldf5fq7inpicrz8dasn-blog-3/src/hello_world.py'
    `blog/bin/program' -> `/gnu/store/4s8ij47drq8avldf5fq7inpicrz8dasn-blog-3/bin/program'


    End of build expression execution

    successfully built /gnu/store/yhmlzaa07rp324nkc888rbacw7yfarsc-blog-3.drv
    The following graft will be made:
       /gnu/store/w90x2vyymw4ny4n1ii840s1iqw7xjf9h-blog-3.drv
    applying 1 graft for /gnu/store/w90x2vyymw4ny4n1ii840s1iqw7xjf9h-blog-3.drv...
    grafting '/gnu/store/4s8ij47drq8avldf5fq7inpicrz8dasn-blog-3' -> '/gnu/store/n4q3ppdqvpppfpm5glhq3cbfhybk1hs9-blog-3'...
    successfully built /gnu/store/w90x2vyymw4ny4n1ii840s1iqw7xjf9h-blog-3.drv
    /gnu/store/n4q3ppdqvpppfpm5glhq3cbfhybk1hs9-blog-3

It helped me bind the package spec and the execution.

So, I'm trying to integrate Guix in my workflow and hopefully propagate that to
others.  This is what I'm trying to achieve at minima:

Assume:

    phf@f02c:~/programs/blog$ tree
    .
    ├── bin
    │ ├── make_release
    │ └── program
    ├── guix
    │ ├── blog.scm
    │ └── manifest.scm
    ├── notes
    │ └── guix_refcard.pdf
    ├── notes.org
    ├── releases
    │ ├── release_1.tar.lz
    │ ├── release_2.tar.lz
    │ └── release_3.tar.lz
    └── src
        └── hello_world.py


Development:

    $ guix environment --manifest=./guix/manifest.scm --pure --container
    $ # Develop things. Add dependencies at will in manifest.scm


Build release:

    $ ./deployment/make_release
    Built release: release_4.tar.lz


Deployment:

    $ guix build --keep-failed --verbosity=2 --file=./blog.scm
    …
    /gnu/store/…-blog-4


Test:

    $ /gnu/store/…-blog-4/bin/program
    Hello world!


What would be very helpful:

    - Define blog.scm such that ~$ guix environment blog~ has the same effect as
      ~$ guix environment --manifest=./guix/manifest.scm --pure --container~

    - Define a package ~blog_executable.scm~ derived from ~blog.scm~ such that
      ~$ guix package -i blog_executable~ has the same effect has
      ~$ guix build --file=./blog_v2.scm~, but actually install the thing.

      ~blog_executable.scm~ is essentially ~blog.scm~ but stripped down to the bare
      minimum to get the executable working.


If all the above is true then I hope that we (multiple devs) can have the guarantee
to have the same dev environment and a simple deployment build that's just the
development environment minus dev dependencies.

With these things in place, a deployment should be deterministic and as simple as a:

    $ guix package -i blog_executable


To sum up, here are the questions I try to answer:

    - How to define ~blog.scm~ such that ~$ guix environment blog~ works?
    - How to define ~blog_executable.scm~ such that ~$ guix package -i blog_executable~ works?


Thanks!
PHF

PS: Python + quasiquotes => I'm trying to replace Python with Racket whenever I can
:-)


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Tuesday, September 3, 2019 3:58 AM, Timothy Sample <samplet@ngyro.com> wrote:

> Hello,
>
> "Pierre-Henry F." contact@phfrohring.com writes:
>
> > Hello Tim !
> > I'm using a couple of hours here an there to try to rebuild the package you gave me (Thank you for that :-) ).
> > So far, I've built a very stupid but "working" package (see below if you really want to ;-) ).
>
> Looks good so far!
>
> > Will answer on the mailing list for others to benefit from this exchange.
>
> I’ve added the mailing list back in, then. ;)
>
> > Needless to say, it's not exactly obvious to figure these things out /a priori/.
>
> For sure. By using the trivial build system, you’re working at a pretty
> low level. It’s especially tough to learn both Guix and Guile at the
> same time. For your reference, here’s a sketch of what the “#:builder”
> code would look like if it were Python:
>
> import os, shutil, stat, subprocess, guix.build.utils
>
> # Unpack
> source = _build_inputs["source"]
> tar = _build_inputs["tar"]
> lzip = _build_inputs["lzip"]
> os.putenv("PATH", ":".join([tar + "/bin", lzip + "/bin"]))
> subprocess.run(["tar", "--lzip", "-xvf", source])
>
> # Configure
> bash = _build_inputs["bash"]
> python = _build_inputs["python"]
> guix.build.utils.substitute("blog/bin/program",
> [["/usr/bin/bash", bash + "/bin/bash"],
> ["python3", python + "/bin/python3"]])
>
> # Install
> out = _outputs["out"]
> os.chmod("blog/bin/program", 0o755)
> shutil.copytree("blog", out)
>
> Here, “_build_inputs” and “_outputs” are set by Guix, and are
> dictionaries. For “_build_inputs”, the keys are the strings you put in
> the “inputs” part of the package, and the values are the paths where the
> packages are installed. So, “_build_inputs["python"]” points to the
> directory in the store where Python is installed. We usually only have
> one output, which is called “out”. This is the path in the store where
> we install the package being built.
>
> The only other thing is that “guix.build.utils.substitute” is basically
> just find-and-replace. It takes the name of a file and a list of
> two-element lists and replaces all the occurrences of the first elements
> in the file with their corresponding second elements.
>
> Obviously the Guile interfaces are a little different, but hopefully
> this Rosetta Stone makes it easier to see what’s going on.
>
> As an aside, ever since I learned that there’s a way to do quasiquotes
> in Python [1], I’ve wondered how strange it would be if Guix were
> written in Python. Pretty strange! :)
>
> [1] https://macropy3.readthedocs.io/en/latest/reference.html#quasiquote
>
> > Anyway, thanks!
>
> You’re welcome!
>
> -- Tim



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: blog_v2.scm --]
[-- Type: text/x-scheme; name="blog_v2.scm", Size: 2669 bytes --]

(use-modules ((gnu packages base) #:select (tar))
  ((gnu packages bash) #:select (bash-minimal))
  ((gnu packages compression) #:select (lzip))
  ((gnu packages python) #:select (python))
  (guix)
  (guix build-system trivial))




(package
  (name "blog")
  (version "3")
  (source
    (origin
      (method url-fetch)
      (uri (string-append "file:///home/phf/programs/blog/releases/release_" version ".tar.lz"))
      (sha256
        (base32
          "1y819b53ksyas6asldysr0r8p73n5i8ipbpmbgjrfx8qz8cy2zsx"))))
  (build-system trivial-build-system)
  (arguments
    `(#:modules ((guix build utils))
       #:builder
       (begin

         (use-modules (guix build utils))


         (newline)
         (display "Start of build expression execution")
         (newline)
         (newline)



         (display "Show inputs")
         (newline)
         ((lambda (name value)
            (display (string-join (list name "=" (format #f "~a" value) "\n"))))
           "  %build-inputs" %build-inputs)



         (newline)
         (display "Show outputs")
         (newline)
         ((lambda (name value)
            (display (string-join (list name "=" (format #f "~a" value) "\n"))))
           "  %outputs" %outputs)



         (newline)
         (display "Unpack source")
         (newline)
         (let ((source (assoc-ref %build-inputs "source"))
                (tar (assoc-ref %build-inputs "tar"))
                (lzip (assoc-ref %build-inputs "lzip")))

           (setenv "PATH" (string-append
                            tar "/bin"
                            ":"
                            lzip "/bin"))

           (invoke "tar" "--lzip" "-xvf" source))


         (newline)
         (display "Reference interpreters available in the build")
         (newline)
         (let ((bash (assoc-ref %build-inputs "bash"))
                (python (assoc-ref %build-inputs "python")))
           (substitute* "blog/bin/program"
             (("/usr/bin/env bash") (string-append bash "/bin/bash"))
             (("python3") (string-append python "/bin/python3"))))



         (newline)
         (display "Make executable available to the host system")
         (newline)
         (let ((out (assoc-ref %outputs "out")))
           (chmod "blog/bin/program" #o775)
           (copy-recursively "blog" out))
         (newline)



         (newline)
         (display "End of build expression execution")
         (newline)
         (newline)
         )))

  (inputs
    `(("bash" ,bash-minimal)
       ("python" ,python)))

  (native-inputs
    `(("lzip" ,lzip)
       ("tar" ,tar)))

  (synopsis #f)
  (description #f)
  (home-page #f)
  (license #f))

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Help defining a trivial package.
  2019-09-04 11:21           ` Pierre-Henry F.
@ 2019-09-04 17:34             ` Timothy Sample
  0 siblings, 0 replies; 7+ messages in thread
From: Timothy Sample @ 2019-09-04 17:34 UTC (permalink / raw)
  To: Pierre-Henry F.; +Cc: help-guix@gnu.org

Hello!

I’m glad the Python code was helpful.  :)  I’ve commented on some of
your other points below.

"Pierre-Henry F." <contact@phfrohring.com> writes:

> Development:
>
>     $ guix environment --manifest=./guix/manifest.scm --pure --container
>     $ # Develop things. Add dependencies at will in manifest.scm
>
>
> Build release:
>
>     $ ./deployment/make_release
>     Built release: release_4.tar.lz
>
>
> Deployment:
>
>     $ guix build --keep-failed --verbosity=2 --file=./blog.scm
>     …
>     /gnu/store/…-blog-4
>
>
> Test:
>
>     $ /gnu/store/…-blog-4/bin/program
>     Hello world!
>
>
> What would be very helpful:
>
>     - Define blog.scm such that ~$ guix environment blog~ has the same effect as
>       ~$ guix environment --manifest=./guix/manifest.scm --pure --container~

This really depends on what’s in “manifest.scm”.  If it contains tools
for building the blog, it would be same, but I take it that
“manifest.scm” has tools for hacking on the blog, too (like editors or
whatever).  In this case, it’s actually a feature that they’re separate.
It keeps the build and runtime time dependencies apart from the
development dependencies.  You can always combine the two, so that
“manifest.scm” only has to contain the extra stuff:

    guix environment --pure --container \
        -l blog.scm --ad-hoc -m manifest.scm

This will pull in all the build and runtime dependencies of the package
defined in “blog.scm” plus all the extra tools from “manifest.scm”.

>     - Define a package ~blog_executable.scm~ derived from ~blog.scm~ such that
>       ~$ guix package -i blog_executable~ has the same effect has
>       ~$ guix build --file=./blog_v2.scm~, but actually install the thing.
>
>       ~blog_executable.scm~ is essentially ~blog.scm~ but stripped down to the bare
>       minimum to get the executable working.

This is definitely possible.  All you need to do is make sure that the
package defined in “blog_executable.scm” has its source field set
properly.  What I’ve done in the past is use Guile-Git to use all of the
files that Git knows about as the source of the package.  This makes
sure transient build artifacts are not included (since they are likely
ignored by Git).  If you like, take a look at this file:

    https://git.savannah.nongnu.org/cgit/gash.git/tree/guix.scm

It is the main Guix package definition that I use when developing Gash
(a shell written in Guile that I maintain).  If you clone the repo, you
can run “guix package -f guix.scm” to build and install Gash from the
latest Git sources (the ones you just cloned).  There are two things to
note, though.  First, if you use it for testing the build, it can get
confusing as to which files are included: is it files in the working
tree, files in the index, or files from the latest commit?  I honestly
get confused and miss things all the time!  The second thing is that
since I wrote that package definition, Guix got a procedure called
“git-predicate” in “(guix git-download)” that does basically the same
thing as my “make-select”.  I recommend using the Guix procedure if
possible, I just haven’t looked into it yet.  :)

> If all the above is true then I hope that we (multiple devs) can have the guarantee
> to have the same dev environment and a simple deployment build that's just the
> development environment minus dev dependencies.
>
> With these things in place, a deployment should be deterministic and as simple as a:
>
>     $ guix package -i blog_executable
>
>
> To sum up, here are the questions I try to answer:
>
>     - How to define ~blog.scm~ such that ~$ guix environment blog~ works?
>     - How to define ~blog_executable.scm~ such that ~$ guix package -i blog_executable~ works?

I hope what I wrote above helps answer these questions!


-- Tim

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-09-04 17:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-23 19:42 Help defining a trivial package Pierre-Henry F.
2019-08-25 12:17 ` Timothy Sample
2019-08-29 11:23   ` Pierre-Henry F.
2019-08-29 15:26     ` Timothy Sample
     [not found]       ` <Al-P-mUDUQnoUvF4kgNS_NeITvHjEDEvxG8Gmk9aMiXX2FTUfL0lbZAq5h4m54GIGNXPwM271CzLWwt5sgOt1JI6Z1wxqxSwWmpnPHu7I5A=@phfrohring.com>
2019-09-03  1:58         ` Timothy Sample
2019-09-04 11:21           ` Pierre-Henry F.
2019-09-04 17:34             ` Timothy Sample

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.