> 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 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