Bundle as Single Executable

conda-pack can be used to distribute conda environments as executable shell scripts for Linux and macOS.

Packaging a Simple Binary

We will package the normaliz binary in this example. It provides a command line tool which is compiled from C++ code.

Create an environment and conda pack it:

$ conda create -y -n normaliz normaliz=3.8.5
$ conda pack -n normaliz

Add an entrypoint that activates the environment and starts normaliz:

$ mkdir pack
$ tar -zxf normaliz.tar.gz -C pack
$ cat > pack/entrypoint.sh <<- 'EOF'
  #!/bin/sh
  source bin/activate
  conda-unpack
  exec bin/normaliz $@
  EOF
$ chmod +x pack/entrypoint.sh

Optional: reduce the size by removing files that are not needed here:

$ rm -rf pack/lib/*.a pack/usr/share pack/usr/include
$ find pack/lib -name '*.dylib' -type f -exec strip -S \{\} \; # macOS
$ find pack/lib -name '*.so' -type f -exec strip --strip-unneeded \{\} \; # Linux

Pack everything into a single shell script with makeself:

$ conda install -y conda-forge::makeself
$ makeself pack/ normaliz.run Normaliz ./entrypoint.sh

The shell script normaliz.run now works on other machines with the same platform. Note that arguments to bin/normaliz need to be given after an initial since earlier arguments are consumed by makeself:

$ ./normaliz.run -- --version
Normaliz 3.8.5

Packaging a Complex Environment

Complex environments can be packaged in the same way. Here we package the computer algebra system SageMath which comes with a Jupyter notebook interface:

$ conda create -y -n sagemath sage=9.2
$ conda pack -n sagemath
$ mkdir pack
$ tar -zxf sagemath.tar.gz -C pack
$ cat > pack/entrypoint.sh <<- 'EOF'
  #!/bin/sh
  source bin/activate
  conda-unpack
  exec bin/sage --notebook=jupyter $@
  EOF
$ chmod +x pack/entrypoint.sh
$ makeself pack/ sagemath.run SageMath ./entrypoint.sh
$ ./sagmath.run # opens a browser with Jupyter running SageMath

The above creates a huge bundle that takes a long time to pack and unpack (and might exceed the available space in your /tmp). This can be speeded up by reducing the level of compression and by uncompressing things permanently:

$ cat > pack/unpack.sh <<- 'EOF'
  #!/bin/sh
  source bin/activate
  conda-unpack
  EOF
$ chmod +x pack/unpack.sh
$ cat > pack/sagemath.run <<- 'EOF'
  #!/bin/sh
  dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
  cd "$dir"
  ./bin/sage --notebook=jupyter $@
  EOF
$ chmod +x pack/sagemath.run
$ mkdir tmp
$ TMPDIR=tmp/ makeself --complevel 6 --target ./sagemath-9.2 pack/ sagemath.install SageMath ./unpack.sh

The resulting shell script unpacks the environment into ./sagemath-9.2. This can be overwritten with the –target parameter:

$ ./sagemath.install
$ ./sagemath-9.2/sagemath.run # opens a browser with Jupyter running SageMath