Notes on setting up Ivy in Python 3
17 Oct 2022 |
|
I use Ivy as part of my day-to-day research. It’s a cool language with lots of nice properties, but initially setting it up on a modern machine can be a bit tricky. It’s written in Python 2, which is no longer easily installable on modern systems, and requires a specific old version of Z3. As a result, it becomes tedious to juggle Python interpreter and dependency versions if you need Python and Z3 for other stuff on the same machine.
I spent some time a few years ago porting IVy to run under Python 3. I’ve also shown a bunch of people in my lab how to get it running in a local Python virtual environment, which means that dependencies (in particular, Ivy’s ancient fork of the Z3 solver) don’t pollute your wider system. However, I keep losing my notes about what steps to take so hopefully this is the last time I have to reconstruct them!
0. Install Python3 and venv if you don’t already have it
$ # Ubuntu/PopOS/etc...
$ sudo apt-get install python3.10-venv
$ # MacOS...
$ brew install python@3.10
1. Check out the Python 3 Ivy fork and set up your virtual environment
$ git clone git@github.com:dijkstracula/ivy.git --recurse-submodules
$ cd ivy
$ git checkout nathan/python3_port
Branch 'nathan/python3_port' set up to track remote branch 'nathan/python3_port' from 'origin'.
Switched to a new branch 'nathan/python3_port'
$ python3 -m venv ./venv
$ ls venv
bin include lib lib64 pyvenv.cfg
Enter the virtual environment, which you’ll have to do each time you want to
run Ivy, and ensure that your PATH points python
into your venv.
$ source ./venv/bin/activate
(venv) $ which python
/home/ntaylor/code/ivy/venv/bin/python
(venv) $ python --version
Python 3.10.12
(venv) $
By contrast, you likely do not have a valid z3 installation (or if you do, it’s installed globally by you, and not the very specific version we need here.)
(venv) $ which z3
z3 not found
(venv) $ python -c 'import z3; print(z3.get_version())'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'z3'
(venv) $
2. Build and install the z3 fork.
The only dependency we care about is Z3 (the instructions for picotls are probably not fundamentally different if you are doing TLS protocol verification). We are going to compile Z3 in order to install it locally within our virtual environment as opposed to a global installation in /usr (or /opt, etc…)
IVy comes with a build_submodules.py
script that normally automates this;
however, we need to give a different --prefix
to the Z3 configure script so
we’ll run the command manually.
(venv) $ cd submodules/z3
(venv) $ python scripts/mk_make.py --prefix=$VIRTUAL_ENV --python
...
Python pkg dir: /home/ntaylor/code/ivy/venv/lib/python3.10/site-packages
Python version: 3.10
...
Z3 was successfully built.
...
Use the following command to install Z3 at prefix /home/ntaylor/code/ivy/venv.
sudo make install
(venv) $
Ensure that the output of running the configure script points into your virtual
environment. Because we are installing Z3 locally, we do not need to run make install
with sudo
.
(venv) $ cd build; make -j8 install
...
Z3 was successfully installed.
(venv) $
You can now confirm that the Z3 binary, on your $PATH, is the one inside your virtual environment; and, that version 4.7.1 can be loaded from your Python interpreter:
(venv) $ which z3
/home/ntaylor/code/ivy/venv/bin/z3
(venv) $ python3 -c 'import z3; print(z3.get_version())'
(4, 7, 1, 0)
(venv) $
3. Install Ivy into your virtual environment
As I often want to modify the Ivy source myself, I do a develop
installation
so that I can modify Ivy without needing to constantly repackage and reinstall
it.
(venv) $ cd ../../../ # back to the root Z3 directory
(venv) $ python setup.py develop
...
Creating /home/ntaylor/code/ivy/venv/lib/python3.10/site-packages/ms-ivy.egg-link (link to .)
...
Installed /home/ntaylor/code/ivy
...
Finished processing dependencies for ms-ivy==1.8.23
(venv) $ which ivyc
/home/ntaylor/code/ivy/venv/bin/ivyc
(venv) $
And now we can test compiling an Ivy program!
(venv) $ cd /tmp/
(venv) $ ivyc target=test foo.ivy
g++ -Wno-parentheses-equality -std=c++11 -I /home/ntaylor/code/ivy/ivy/include -L /home/ntaylor/code/ivy/ivy/lib -Xlinker -rpath -Xlinker /home/ntaylor/code/ivy/ivy/lib -I /home/ntaylor/code/ivy/venv/lib/python3.10/site-packages/z3/include -L /home/ntaylor/code/ivy/venv/lib/python3.10/site-packages/z3/lib -Xlinker -rpath -Xlinker /home/ntaylor/code/ivy/venv/lib/python3.10/site-packages/z3/lib -I /home/ntaylor/code/ivy/venv/include -L /home/ntaylor/code/ivy/venv/lib -Xlinker -rpath -Xlinker /home/ntaylor/code/ivy/venv/lib -g -o foo foo.cpp -lz3 -pthread
(venv) $ ivy_launch foo
...
Happy proving!