diff --git a/.gitignore b/.gitignore
index 5d88f6b68726292919f8d6efe6344a37d8de54a4..cc2bda918b0682af2c0fae3e505dbfb816ffec67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 /bld
 /build
 /interface/teqpversion.hpp
+/pypirc
diff --git a/buildwheels.py b/buildwheels.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d35ae0555500c1e7ec29ec662b148ddcc744cb4
--- /dev/null
+++ b/buildwheels.py
@@ -0,0 +1,35 @@
+import sys
+import os
+import subprocess
+import glob
+
+# Check presence of twine variables or config file
+userc = False
+if os.path.exists('pypirc'):
+    userc = True
+else:
+    for k in ['TWINE_USERNAME','TWINE_PASSWORD']:
+        if k not in os.environ:
+            raise KeyError(f'You must set the twine environment variable {k}')
+
+for pyver in ['3.7','3.8','3.9']:
+    # Build the wheel if it is not already built
+    abbrv = pyver.replace('.', '')
+    if not glob.glob(f'teqp*cp{abbrv}*.whl'):
+        condaenv = f'conda-{pyver}'
+        subprocess.check_call(f'conda create -y -n {condaenv} python={pyver}', shell=True)
+        subprocess.check_call(f'conda activate {condaenv} && python -m pip install -U pip wheel', shell=True)
+        try:
+            subprocess.check_call(f'conda activate {condaenv} && python -m pip -vvv wheel .', shell=True)
+        except:
+            pass
+        finally:
+            subprocess.check_call(f'conda env remove -y -n {condaenv}',shell=True)
+
+# Upload wheels
+if userc:
+    twine_call = f'twine upload --config-file pypirc *.whl'
+else:
+    twine_call = f'twine upload *.whl'
+
+subprocess.check_call(twine_call, shell=True)
\ No newline at end of file