diff --git a/appveyor.yml b/appveyor.yml
index 652647b26781a56474efff9b67857858caeb501f..83fc9cd6a876b11827564031a5f61a864719c834 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -57,7 +57,7 @@ build_script:
   - echo %errorlevel%
 
 artifacts:
-  - path: build
+  - path: dist
     name: sakia-win$(PYTHON_ARCH)
 # upload to releases
 deploy:
diff --git a/ci/appveyor/build.cmd b/ci/appveyor/build.cmd
index a1b9b313e4a0f0b3dc536e1148fd2f863329fbf0..d5b374fb3ebd70672907d496b758cc69ad28b9ea 100644
--- a/ci/appveyor/build.cmd
+++ b/ci/appveyor/build.cmd
@@ -12,6 +12,7 @@ pyrcc5 -version
 lrelease -version
 
 pip install -r requirements.txt
+pip install pyinstaller
 
 python gen_resources.py
 if %errorlevel% neq 0 exit /b 1s
@@ -19,5 +20,5 @@ if %errorlevel% neq 0 exit /b 1s
 python gen_translations.py
 if %errorlevel% neq 0 exit /b 1
 
-@REM python setup.py build
-@REM if %errorlevel% neq 0 exit /b 1
+pyinstaller sakia.spec
+if %errorlevel% neq 0 exit /b 1
diff --git a/ci/travis/before_deploy.sh b/ci/travis/before_deploy.sh
index f80fb656c0d199f73f5dc5acf48a68053a9c7eac..1cb92cf75b16c7e117aabf6b742edbabffc1f7c0 100755
--- a/ci/travis/before_deploy.sh
+++ b/ci/travis/before_deploy.sh
@@ -2,8 +2,8 @@
 
 if [ $TRAVIS_OS_NAME == "osx" ]
 then
-    zip -r sakia-${TRAVIS_OS_NAME}.zip build/*.dmg
+    zip -r sakia-${TRAVIS_OS_NAME}.zip dist/*
 elif [ $TRAVIS_OS_NAME == "linux" ]
 then
-    zip -r sakia-${TRAVIS_OS_NAME}.zip build/exe*
+    zip -r sakia-${TRAVIS_OS_NAME}.zip dist/
 fi
diff --git a/ci/travis/build.sh b/ci/travis/build.sh
index b044d97633282d00e3f30724827ccfd4089922b7..bd31a38563cbe37c5b95394262776ae687f57918 100755
--- a/ci/travis/build.sh
+++ b/ci/travis/build.sh
@@ -6,7 +6,7 @@ eval "$(pyenv virtualenv-init -)"
 cd $HOME/build/ucoin-io/sakia
 pyenv activate sakia-env
 pip install coveralls
-pip install cx_Freeze
+pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
 pip install -r requirements.txt
 if [ $TRAVIS_OS_NAME == "linux" ]
 then
@@ -19,9 +19,9 @@ python gen_translations.py
 
 if [ $TRAVIS_OS_NAME == "osx" ]
 then
-    python setup.py bdist_dmg
+    pyinstaller sakia.spec
 elif [ $TRAVIS_OS_NAME == "linux" ]
 then
-    python setup.py build
+    pyinstaller sakia.spec
 fi
 
diff --git a/hooks/hook-lib2to3.py b/hooks/hook-lib2to3.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae3b35142f25cb6148e306d3327c01f47e299ea9
--- /dev/null
+++ b/hooks/hook-lib2to3.py
@@ -0,0 +1,15 @@
+#-----------------------------------------------------------------------------
+# Copyright (c) 2005-2016, PyInstaller Development Team.
+#
+# Distributed under the terms of the GNU General Public License with exception
+# for distributing bootloader.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
+# This is needed to bundle draft3.json and draft4.json files that come
+# with jsonschema module
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files('lib2to3')
diff --git a/sakia.spec b/sakia.spec
new file mode 100644
index 0000000000000000000000000000000000000000..9ab862da24f2eb82078903fef4190a1d33f8c1fa
--- /dev/null
+++ b/sakia.spec
@@ -0,0 +1,41 @@
+# -*- mode: python -*-
+from PyInstaller.compat import is_darwin
+
+block_cipher = None
+
+a = Analysis(['src/sakia/main.py'],
+             pathex=['.'],
+             binaries=None,
+             datas=None,
+             hiddenimports=[],
+             hookspath=['hooks'],
+             runtime_hooks=[],
+             excludes=[],
+             win_no_prefer_redirects=False,
+             win_private_assemblies=False,
+             cipher=block_cipher)
+
+if is_darwin:
+    a.binaries = a.binaries - TOC([
+     ('/usr/local/lib/libsodium.so', None, None),])
+
+pyz = PYZ(a.pure, a.zipped_data,
+             cipher=block_cipher)
+
+exe = EXE(pyz,
+          a.scripts,
+          exclude_binaries=True,
+          name='sakia',
+          debug=True,
+          strip=False,
+          upx=True,
+          console=True )
+
+coll = COLLECT(exe,
+               a.binaries,
+               a.zipfiles,
+               a.datas,
+               strip=False,
+               upx=True,
+               name='sakia')
+