summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--topics/pangenome/impg/impg-agc-bindings.gmi76
-rw-r--r--topics/rust/guix-rust-bootstrap.gmi144
2 files changed, 220 insertions, 0 deletions
diff --git a/topics/pangenome/impg/impg-agc-bindings.gmi b/topics/pangenome/impg/impg-agc-bindings.gmi
index b190b1d..ef7c55b 100644
--- a/topics/pangenome/impg/impg-agc-bindings.gmi
+++ b/topics/pangenome/impg/impg-agc-bindings.gmi
@@ -23,6 +23,16 @@ It should be straightforward to create a Rust module that calles into the shared
 
 One early choice is a separation of concerns. We will try to build the library independently of the Rust package. This follows a standard model. For example cargo should not build zlib - it is provided by the environment. The bindings, meanwhile, are defined and built in cargo.
 
+# Tasks
+
+* [ ] Get guix to compile impg with AGC
+* [ ] Add optimization
+* [ ] Make sure spoa build in spoa-rs is optimized
+* [ ] Create static binary for distribution
+* [ ] Create singularity example
+
+# Steps
+
 ## Setting up Guix with rust
 
 Guix provides a reproducible build environment. If you get over the fact that it is Lisp, it proves a remarkably nice way to handle dependencies. The first step is to set up guix so you get a recent set of dependencies. For this run guix pull and set it up in a profile
@@ -133,3 +143,69 @@ We will also write a
 * [ ] Guix build that creates an optimized impg
 
 And that last one allows us to distribute prebuilt binaries in CONDA and apptainer/singularity/docker.
+
+Note that this is the same approach as taken by
+
+=> https://github.com/rust-lang/libz-sys/blob/main/build.rs
+
+which binds against libz. It *optionally* builds the source tree of zlib which is included as a submodule
+
+=> https://github.com/rust-lang/libz-sys/tree/main/src
+
+In our case, a rebuild can be useful when AGC lib can not be found. Note that the cargo edition of libz-sys does not invoke make or cmake. It builds it by 'hand'!
+
+There is also libz-rs, but that is a somewhat typical Rust rewrite of libz:
+
+=> https://github.com/trifectatechfoundation/zlib-rs
+
+I also took a quick look at the rust spoa crate. Here a build is always forced, but I don't think it actually optimizes the build. Add a note to my tasks.
+
+## First guix package by Fred
+
+Fred drafted a first guix package which can build impg with
+
+```
+guix build -L .guix/modules -f guix.scm
+
+/gnu/store/cdjiq6aalpc849hl8irmbn8xax9mq2b6-impg-0.3.1/bin/impg
+Command-line tool for querying overlaps in PAF files
+
+Usage: impg <COMMAND>
+
+Commands:
+  index       Create an IMPG index
+  lace        Lace files together (graphs or VCFs)
+  partition   Partition the alignment
+  query       Query overlaps in the alignment
+  similarity  Compute pairwise similarity between sequences in a region
+  stats       Print alignment statistics
+
+Options:
+  -h, --help     Print help
+  -V, --version  Print version
+```
+
+It builds against rust 1.85 and uses the new cargo support in Guix. It does not have to rebuild the cargo packages already in guix. Nice and a good start!
+
+=> https://github.com/pangenome/impg/blob/f5ebaf8b511ee06bdeb193ef509836c26cd4793a/.guix/modules/impg/impg.scm#L4
+
+we'll still need to add AGC, static output and optimizations.
+
+## Adding a guix package for AGC
+
+As a first step we build a package for AGC that compiles libagc.a using AVX2:
+
+=> https://github.com/pjotrp/impg/commit/ed16948cc4145ff933a19ba54c3bc1fe4cec709f
+
+we used the vendored in source for raduls-inplace and isa-l. Not sure they are really required, but I think it is harmless here.
+
+## Make sure libagc.a is linked to impg
+
+To create a rust package for binding libagc it is worth reading:
+
+=> https://doc.rust-lang.org/cargo/reference/build-scripts.html#a-sys-packages
+
+* The library crate should link to the native library libfoo. This will often probe the current system for libfoo before resorting to building from source.
+* The library crate should provide declarations for types and functions in libfoo, but not higher-level abstractions.
+
+So we should create an agc-rs crate that provides a high-level interface to the upcoming libagc-sys crate. No wonder these crates proliferate.
diff --git a/topics/rust/guix-rust-bootstrap.gmi b/topics/rust/guix-rust-bootstrap.gmi
new file mode 100644
index 0000000..636aff2
--- /dev/null
+++ b/topics/rust/guix-rust-bootstrap.gmi
@@ -0,0 +1,144 @@
+# Guix Rust Bootstrap
+
+To develop code against rust you often need a recent edition of rust. With Guix this is possible because you don't depend on the underlying linux distribution to provide recent versions of glibc and other libraries. Here we have a recipe that should work anywhere on Linux.
+
+I succeeded in running the latest Rust on Octopus and building packages with guix.
+
+To make it work the following steps are required:
+
+* Update guix with guix-pull if your guix is older than 3 months
+* Unset GUIX_PROFILE on some systems
+* Set your updated guix profile vars
+* Create a container that has all dependencies for rust itself
+* Run rustup
+* Run cargo with LD_LIBRARY_PATH set to $GUIX_ENVIRONMENT/lib
+
+# Get Guix updated
+
+Important is to have a recent version of Guix. This is achieved with 'guix pull' and making sure it works.
+
+
+```sh
+guix pull -p ~/opt/guix-pull --url=https://codeberg.org/guix/guix
+```
+
+it takes a few minutes. Next set the environment
+
+```sh
+unset GUIX_PROFILE
+. ~/opt/guix-pull/etc/profile
+```
+
+This will point the path to a recent guix. You can make sure with
+
+```
+guix describe
+  guix 772c456
+    repository URL: https://codeberg.org/guix/guix
+    branch: master
+    commit: 772c456717e755829397a6ff6dba4c1e135426d8
+```
+
+which can be validated against the Guix tree. Running
+
+
+```sh
+guix package -A rust
+rust                    1.85.1                  rust-src,tools,out,cargo       gnu/packages/rust.scm:1454:4
+```
+
+shows the current *stable* version in Guix. Now, of course, we want something more to get rust latest.
+
+# Update Rust and Cargo to latest (stable)
+
+The trick is to set up a container with Rust in your git working directory:
+
+```
+mkdir -p ~/.cargo ~/.rustup # to prevent rebuilds
+guix shell --share=$HOME/.cargo  --share=$HOME/.rustup -C -N -D -F -v 3 guix gcc-toolchain make libdeflate pkg-config xz coreutils sed zstd zlib nss-certs openssl curl
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+. ~/.cargo/env
+rustup default stable
+```
+
+Now rustc shows it is recent:
+
+```
+rustc --version
+rustc 1.90.0 (1159e78c4 2025-09-14)
+```
+
+Next run 'cargo build' with:
+
+```
+env LD_LIBRARY_PATH=$GUIX_ENVIRONMENT/lib cargo build
+  Compiling libagc-sys v0.1.0 (/home/wrk/iwrk/opensource/code/pangenome/libagc-sys)
+    Finished 'dev' profile [unoptimized + debuginfo] target(s) in 0.06s
+$ ./target/debug/libagc-sys
+./target/debug/libagc-sys: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directory
+$ env LD_LIBRARY_PATH=$GUIX_ENVIRONMENT/lib ./target/debug/libagc-sys
+Hello, world!
+```
+
+and your source should build and run. Note the libgcc_s.so.1 error.
+
+## What if you get a libgcc or librt error?
+
+The problem is that cargo picks up the wrong libgcc:
+
+```
+$ ls /gnu/store/*/lib/libgcc_s.so.1
+/gnu/store/m2vhzr0dy352cn59sgcklcaykprrr4j6-gcc-14.3.0-lib/lib/libgcc_s.so.1
+/gnu/store/rbs3nrx9z6sfawn3fa8r8z1kffdbnk8q-gcc-toolchain-15.2.0/lib/libgcc_s.so.1
+/gnu/store/v3bq3shn333kh7m6gj3r58l0v7mkn4in-profile/lib/libgcc_s.so.1
+/gnu/store/xm7i1gvi0i9pyndlkv627r08rsw1ny96-gcc-15.2.0-lib/lib/libgcc_s.so.1
+```
+
+This is because Guix itself builds on an older libgcc and librt. You need to tell it explicitly what library to load that built your cargo:
+
+```
+ldd ~/.cargo/bin/cargo
+        linux-vdso.so.1 (0x00007ffd409b2000)
+        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fd2cf433000)
+        librt.so.1 => /lib/librt.so.1 (0x00007fd2cf42e000)
+```
+
+in the container:
+
+```
+ls -l /lib/libgcc_s.so.1
+lrwxrwxrwx 1 65534 overflow 82 Jan  1  1970 /lib/libgcc_s.so.1 -> /gnu/store/rbs3nrx9z6sfawn3fa8r8z1kffdbnk8q-gcc-toolchain-15.2.0/lib/libgcc_s.so.1
+```
+
+which happens to be the one in $GUIX_ENVIRONMENT/lib! So setting the library path solves it.
+
+The reason that we don't get the automatically resolving libraries that you normally have in guix is that we have updated rust by *hand* using rustup. Guix has no control over this process.
+
+# spoa-rs on octopus01
+
+I just did above to build spoa-rs. Only had to add cmake to the shell packages.
+
+# Updating the container
+
+Now your build may fail because you miss a crucial library or tool. This is a feature of guix containers as it makes dependencies explicit.
+
+Just add them to the guix shell command. Let's say we add zlib
+
+```
+guix shell --share=$HOME/.cargo  --share=$HOME/.rustup -C -N -D -F -v 3 guix gcc-toolchain make libdeflate pkg-config xz coreutils sed zstd zlib nss-certs openssl curl zlib
+```
+
+# Troubleshooting
+
+## Collisions
+
+Guix may complain about collisions. These are mostly naming issues:
+
+```
+warning: collision encountered:
+  /gnu/store/nym6kiinrg2mb8z4lwnvfx5my8df9vrs-glibc-for-fhs-2.41/bin/ldd
+  /gnu/store/rbs3nrx9z6sfawn3fa8r8z1kffdbnk8q-gcc-toolchain-15.2.0/bin/ldd
+warning: choosing /gnu/store/nym6kiinrg2mb8z4lwnvfx5my8df9vrs-glibc-for-fhs-2.41/bin/ldd
+```
+
+it will like one into your environment. You can still use both tools by using the full path and normally ignore the warning.