diff --git a/.gitignore b/.gitignore
index 0cd8a23c45..44f0a3871e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@
cmd/ethereum/ethereum
cmd/mist/mist
+deploy/osx/Mist.app
+deploy/osx/Mist\ Installer.dmg
diff --git a/deploy/.gitignore b/deploy/.gitignore
new file mode 100644
index 0000000000..ea796b7cbb
--- /dev/null
+++ b/deploy/.gitignore
@@ -0,0 +1,16 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile ~/.gitignore_global
+
+/tmp
+*/**/*un~
+*un~
+.DS_Store
+*/**/.DS_Store
+ethereum/ethereum
+ethereal/ethereal
+osx/Mist.app
+osx/__MACOSX
+osx/Mist.dmg
diff --git a/deploy/README.md b/deploy/README.md
new file mode 100644
index 0000000000..2686911030
--- /dev/null
+++ b/deploy/README.md
@@ -0,0 +1,55 @@
+go-build
+========
+
+Build scripts for Ethereum Mist.
+
+### OS X
+Install all build dependencies.
+
+* brew install go gmp readline
+* npm install -g appdmg
+* go get -u github.com/ethereum/go-ethereum/cmd/mist
+* Open build.py and edit the (macdeployqt) paths.
+* python build.py
+
+If everything went ok you should now have a Mist.dmg file in your current folder.
+
+### Windows
+
+Install all build dependencies.
+
+* [Golang](http://golang.org/dl/) 1.2 or higher (32-bit required)
+* Install [Git](http://git-scm.com/) and [Mercurial](http://mercurial.selenic.com/)
+* [MinGW32](http://www.mingw.org/) (add X:\MinGW\bin directory to your PATH)
+* Use mingw32-get to install *gmp* packages
+* Install [Qt5 for Windows 32-bit MinGW](http://qt-project.org/downloads) (5.2.1 at the moment of writing)
+* Install [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) somewhere in your PATH. (read the [instructions](http://stackoverflow.com/questions/1710922/how-to-install-pkg-config-in-windows) here)
+* Install [NSIS](http://nsis.sourceforge.net/)
+
+After all these things have been satisfied ```go get -u github.com/ethereum/go-ethereum/cmd/mist```
+
+Once the compilation is completed you can create a setup binary.
+- Edit build.bat and change qtPath and mingwPath to the paths of your installed versions.
+- right-click the nsi file and select "Compile NSIS Script".
+
+If everything went well you should now have a windows-setup file.
+
+
+#### Troubleshooting
+
+Now it will be a miracle if the windows build works in one go.
+So here are some possible solutions for things that can go wrong:
+
+*Expected unqualified-id*
+```
+qopenglversionfunctions.h:785:43: error: expected unqualified-id before ')' token
+ void (QOPENGLF_APIENTRYP MemoryBarrier)(GLbitfield barriers);
+```
+
+See [this ticket](https://github.com/go-qml/qml/issues/56) for a couple of solutions.
+
+*pkg-config path*
+
+pkg-config might complain about the config path. Setup an environment value `PKG_CONFIG_PATH` and set it to `C:\Qt\Qt5.2.1\5.2.1\mingw48_32\lib\pkgconfig`. Adopted to your QT version.
+
+If there are any build problems please create an issue.
diff --git a/deploy/osx/Ethereal.icns b/deploy/osx/Ethereal.icns
new file mode 100644
index 0000000000..b02ad0ca3e
Binary files /dev/null and b/deploy/osx/Ethereal.icns differ
diff --git a/deploy/osx/Mist.icns b/deploy/osx/Mist.icns
new file mode 100644
index 0000000000..3ba75a4327
Binary files /dev/null and b/deploy/osx/Mist.icns differ
diff --git a/deploy/osx/background-source-pm.pxm b/deploy/osx/background-source-pm.pxm
new file mode 100644
index 0000000000..4cf97f8eaf
Binary files /dev/null and b/deploy/osx/background-source-pm.pxm differ
diff --git a/deploy/osx/background-source.psd b/deploy/osx/background-source.psd
new file mode 100644
index 0000000000..8fb1b33ce3
Binary files /dev/null and b/deploy/osx/background-source.psd differ
diff --git a/deploy/osx/background.png b/deploy/osx/background.png
new file mode 100644
index 0000000000..54bbab35d3
Binary files /dev/null and b/deploy/osx/background.png differ
diff --git a/deploy/osx/background@2x.png b/deploy/osx/background@2x.png
new file mode 100644
index 0000000000..20bbc6acea
Binary files /dev/null and b/deploy/osx/background@2x.png differ
diff --git a/deploy/osx/build.py b/deploy/osx/build.py
new file mode 100644
index 0000000000..f5e731efd9
--- /dev/null
+++ b/deploy/osx/build.py
@@ -0,0 +1,238 @@
+import sys, os, argparse, logging, shutil, subprocess, stat,glob
+from os.path import isfile
+
+# TODO handle icns
+# TODO create dmg
+# TODO Add client qml files and png files
+# CHMOD +x the main binary
+
+logging.basicConfig(
+ stream=sys.stdout,
+ format='%(asctime)s : %(levelname)s\t : %(message)s',
+ datefmt='%m/%d/%Y %I:%M:%S %p',
+ level=logging.DEBUG
+)
+
+XML_PLIST = """
+
+
+
+
+ CFBundleGetInfoString
+ Mist
+ CFBundleExecutable
+ Mist
+ CFBundleIdentifier
+ com.ethereum.mist
+ CFBundleName
+ Mist
+ CFBundleIconFile
+ Mist.icns
+ CFBundleShortVersionString
+ POC8
+ CFBundleInfoDictionaryVersion
+ POC8
+ CFBundlePackageType
+ APPL
+ IFMajorVersion
+ 0
+ IFMinorVersion
+ 5
+
+
+"""
+
+RUN_SCRIPT ="""
+#!/bin/bash
+cd "${0%/*}"
+./go-ethereum
+"""
+
+class AppBundler:
+ def copytree(self, src, dst, symlinks=False, ignore=None):
+ for item in os.listdir(src):
+ s = os.path.join(src, item)
+ d = os.path.join(dst, item)
+ if os.path.isdir(s):
+ shutil.copytree(s, d, symlinks, ignore)
+ else:
+ shutil.copy2(s, d)
+
+ # If macdeployqt handles qmldir then runs on app
+ def runMacDeployQT(self):
+ exe = '/usr/local/opt/qt5/bin/macdeployqt'
+ if not os.path.exists(exe): exe = 'macdeployqt'
+ p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ handles_qml = False
+ for line in p.stdout.readlines():
+ if '-qmldir=' in line:
+ handles_qml = True
+ break
+ if handles_qml and self.go_path is not None:
+ qml_path = os.path.join(self.go_path, 'src/github.com/ethereum/go-ethereum/cmd/mist/assets/qml/') #TODO this is terrible
+ out = os.path.join(self.output_dir + '/Mist.app')
+ command = exe + ' ' + out + ' -executable='+out+'/Contents/MacOS/Mist' + ' -qmldir=' + qml_path #TODO this is terrible
+ logging.info('Running macdeployqt with options')
+ p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ for line in p.stdout.readlines():
+ logging.info('macdeployqt: ' + line.strip())
+ else:
+ logging.error('Your version of macdeployqt does not handle qmldir')
+
+ # Add ICNS file to
+ def insertICNS(self):
+ path = os.path.join(self.output_dir, 'Mist.app/Contents/Resources/Mist.icns')
+
+ try:
+ shutil.copyfile('./Mist.icns',path) # TODO this is horrible
+ logging.info('Inserted Mist.icns')
+ except Exception as e:
+ logging.error(str(e))
+
+ def insertQMLnPNG(self):
+ pass # TODO
+
+ #def signApp(self):
+ # after macdeployqt copy /usr/local/opt/qt5/lib/QtCore.framework/Contents/Info.plist to .app/Contents/Resources/QtCore.framework/Resources/Info.plist
+ # codesign --verbose --force --sign "Developer ID Application: <>" /Users/_/Dropbox/Experiments/EthereumBuild/Ethereal.app/Contents/Frameworks/QtCore.framework
+ # do for rest
+ # codesign --verbose --deep --force --sign "Developer ID Application: <>" Ethereal.app
+ # codesign --verify --verbose=4 Ethereal.app
+
+ def insertAssets(self):
+ asset_path = os.path.join(self.go_path, 'src/github.com/ethereum/go-ethereum/cmd/mist/assets')
+ self.copytree(asset_path,"Mist.app/Contents/Resources/")
+ # Copy mnemonic word list
+ #shutil.copy(os.path.join(self.go_path, 'src/github.com/ethereum/eth-go/ethcrypto/mnemonic.words.lst'),"Mist.app/Contents/Resources/")
+
+ # Insert all QML files and other resource files Mist needs
+ def insertResources(self):
+ qml_path = os.path.join(self.go_path, 'src/github.com/ethereum/go-ethereum/cmd/mist/assets/qml/')
+ target_folder = "Mist.app/Contents/Resources/"
+ target_folder_qml = target_folder + "qml/"
+
+ os.makedirs(target_folder_qml)
+
+ files = glob.glob(qml_path)
+ for f in files:
+ print "Copying %s to %s" % (f, target_folder_qml)
+ if isfile(f):
+ shutil.copy(f, target_folder_qml)
+ else:
+ self.copytree(f, target_folder_qml)
+
+ files = glob.glob(os.path.join(self.go_path, 'src/github.com/ethereum/go-ethereum/cmd/mist/assets/*'))
+ for f in files:
+ print "Copying %s to %s" % (f, target_folder)
+ if isfile(f):
+ shutil.copy(f, target_folder)
+ else:
+ self.copytree(f, target_folder)
+ # Finds go-etherum binary and copies to app bundle
+
+ def insertGoBinary(self):
+ if self.go_path is not None:
+ binary = os.path.join(self.go_path, 'bin/mist')
+ if os.path.exists(binary):
+ try:
+ shutil.copyfile(binary, os.path.join(self.output_dir, 'Mist.app/Contents/MacOS/Mist')) # TODO this is horrible
+ os.chmod(os.path.join(self.output_dir, 'Mist.app/Contents/MacOS/Mist'), 0711)
+ logging.info('Inserted go-ethereum binary')
+ except Exception as e:
+ logging.error(str(e))
+ else:
+ logging.error('Cannot find go-etherum binary')
+ if self.handleHumanInput('Run "go get -u github.com/ethereum/go-ethereum" ?'):
+ logging.debug('Not Implemented')
+ pass
+ else:
+ logging.error('GOPATH not found, cannot continue')
+
+ # Write the Info.plist
+ def writePList(self):
+ try:
+ with open(os.path.join(self.output_dir, 'Mist.app/Contents/Info.plist'), 'wb') as f: # TODO this is horrible
+ f.write(XML_PLIST)
+ f.close()
+ logging.info('Info.plist written')
+ except Exception as e:
+ logging.error(str(e))
+
+ # Building out directory structure
+ def buildStructure(self, root, structure):
+ if root is not self.output_dir:
+ try:
+ os.mkdir(root)
+ logging.info('Created ' + root)
+ except Exception as e:
+ logging.error(str(e))
+ if self.handleHumanInput('Remove Directory?'):
+ try:
+ shutil.rmtree(root)
+ self.buildStructure(root, structure)
+ return
+ except Exception as e:
+ logging.error(str(e))
+ for item in structure.keys():
+ self.buildStructure(
+ os.path.join(root, item),
+ structure[item]
+ )
+
+ # Convert human input to boolean
+ def handleHumanInput(self, question=''):
+ if self.force: return True
+ try:
+ answer = raw_input(question + " [Y/n]: ").lower()
+ except:
+ return True
+ if answer is '' or answer[0:1] == 'y': return True
+ return False
+
+ logging.info('Copying QTWebProcess')
+ libexec_path = self.output_dir + '/Mist.app/Contents/libexec'
+ try:
+ os.mkdir(libexec_path)
+ shutil.copy2(path, libexec_path)
+ return True
+ except OSError as e:
+ print("Problem getting QTWebprocess on path %s. Error: %s" % (path, e))
+ return False
+
+ # Setup Variables
+ def __init__(self, args):
+ self.force = args['force']
+ self.output_dir = args['output']
+ self.app_name = "".join(x for x in args['name'] if x.isalnum()) # Simple Santize
+ self.app_structure = {
+ '%s.app' % self.app_name : {
+ 'Contents' : {
+ 'MacOS' : {},
+ 'Resources' : {}
+ }
+ }
+ }
+ self.go_path = os.environ.get('GOPATH')
+ self.buildStructure(self.output_dir, self.app_structure)
+ self.writePList()
+ self.insertICNS()
+ self.insertGoBinary()
+ self.insertAssets()
+
+ #self.insertResources()
+
+ self.runMacDeployQT()
+ os.system("sh script.sh " + self.output_dir + "/Mist.app/Contents")
+ os.system("appdmg dmg_spec.json Mist.dmg")
+
+ logging.info("fin'")
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Standalone Mist Go Client App Bundler')
+ parser.add_argument('-n','--name', help='Name of app bundle', default='Mist', required=False)
+ parser.add_argument('-q','--qtwebpath', help='Location of QtWebProcess', default='Mist', required=False)
+ parser.add_argument('-o','--output', help='Directory to write app bundle', default=os.getcwd(), required=False)
+ parser.add_argument('-f','--force', help='Force Fresh Build', default=False, required=False)
+ args = vars(parser.parse_args())
+ AppBundler(args)
diff --git a/deploy/osx/dmg_spec.json b/deploy/osx/dmg_spec.json
new file mode 100644
index 0000000000..c433124963
--- /dev/null
+++ b/deploy/osx/dmg_spec.json
@@ -0,0 +1,10 @@
+{
+ "title": "Mist Installer",
+ "icon": "Mist.icns",
+ "background": "background.png",
+ "icon-size": 144,
+ "contents": [
+ { "x": 900, "y": 244, "type": "link", "path": "/Applications" },
+ { "x": 140, "y": 244, "type": "file", "path": "Mist.app" }
+ ]
+}
diff --git a/deploy/osx/script.sh b/deploy/osx/script.sh
new file mode 100644
index 0000000000..345ab5ae84
--- /dev/null
+++ b/deploy/osx/script.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+BUILD_FOLDER_PATH=$1
+BUILD_QML_FOLDER_PATH="$BUILD_FOLDER_PATH/Resources/qml"
+BUILD_PLUGINS_FOLDER_PATH="$BUILD_FOLDER_PATH/PlugIns"
+
+declare -a BROKEN_FILES;
+k=0;
+for j in $(find ${BUILD_QML_FOLDER_PATH} -name *.dylib); do
+ BROKEN_FILES[${k}]=$j
+
+ ((k=k+1))
+done
+
+
+for i in "${BROKEN_FILES[@]}"; do
+ REPLACE_STRING="$BUILD_FOLDER_PATH/"
+ APP_CONTENT_FILE=${i//$REPLACE_STRING/""}
+ IFS='/' read -a array <<< "$APP_CONTENT_FILE"
+ LENGTH=${#array[@]}
+ LAST_ITEM_INDEX=$((LENGTH-1))
+ FILE=${array[${LENGTH} - 1]}
+
+ ORIGINE_PATH=$(find ${BUILD_PLUGINS_FOLDER_PATH} -name ${FILE})
+ ORIGINE_PATH=${ORIGINE_PATH//$REPLACE_STRING/""}
+ s=""
+ for((l=0;l<${LAST_ITEM_INDEX};l++)) do
+ s=$s"../"
+ done
+ s=$s$ORIGINE_PATH
+ echo "s: $s"
+
+ REMOVE_BROKEN_ALIAS=$(rm -rf $i)
+ RESULT=$(ln -s $s $i)
+done
diff --git a/deploy/windows/build.bat b/deploy/windows/build.bat
new file mode 100644
index 0000000000..b67a6024de
--- /dev/null
+++ b/deploy/windows/build.bat
@@ -0,0 +1,39 @@
+@ECHO off
+set origin=%GOPATH%\src\github.com\ethereum\go-ethereum\cmd\mist
+set ethgo=%GOPATH%\src\github.com\ethereum\eth-go
+set target=%GOPATH%\pkg\ethereum\
+set qtPath=C:\Qt\Qt5.2.1\5.2.1\mingw48_32
+set mingwPath=C:\MingW\
+
+ECHO "Setting up Windows binaries"
+
+ECHO "Copying assets from %GOPATH%"
+xcopy /s %origin%\assets %target%assets
+
+ECHO "Copying mnemonic words"
+copy %ethgo%\ethcrypto\mnemonic.words.lst %target%
+
+ECHO "Compiling Mist"
+cd %origin%
+go install
+
+ECHO "Copying to source folder"
+copy %GOPATH%\bin\mist.exe %target%
+
+ECHO "Running QT Deploy"
+cd %target%
+windeployqt --webkit2 --qmldir=assets\qml\ .
+
+echo "Copy missing DLLs & Others"
+
+copy %qtPath%\bin\QtWebProcess.exe %target%
+copy %qtPath%\bin\Qt5MultimediaWidgets.dll %target%
+copy %qtPath%\bin\Qt5PrintSupport.dll %target%
+copy %qtPath%\bin\Qt5OpenGL.dll %target%
+copy %qtPath%\bin\Qt5WebKitWidgets.dll %target%
+
+copy %qtPath%\bin\libgcc_s_dw2-1.dll %target%
+copy "%qtPath%\bin\libstdc++-6.dll" %target%
+copy %qtPath%\bin\libwinpthread-1.dll %target%
+
+copy %mingwPath%\bin\libgmp-10.dll %target%
diff --git a/deploy/windows/create-setup.nsi b/deploy/windows/create-setup.nsi
new file mode 100644
index 0000000000..ed2fdc29a6
--- /dev/null
+++ b/deploy/windows/create-setup.nsi
@@ -0,0 +1,111 @@
+;--------------------------------
+;Include Modern UI
+
+ !include "MUI2.nsh"
+
+;--------------------------------
+;General
+
+ ;Name and file
+ Name "Mist"
+ OutFile "mist-setup.exe"
+
+ ;Default installation folder
+ InstallDir "$PROGRAMFILES\Mist"
+
+ ;Get installation folder from registry if available
+ InstallDirRegKey HKCU "Software\Mist" ""
+
+ ;Request application privileges for Windows Vista
+ RequestExecutionLevel admin
+
+ SetCompressor /SOLID lzma ; had the strongest compression rate for Mist
+
+;--------------------------------
+;Variables
+
+;--------------------------------
+;Interface Settings
+
+
+ !define MUI_ICON "logo.ico"
+ !define MUI_HEADERIMAGE
+ !define MUI_HEADERIMAGE_BITMAP "ethereum.bmp"
+ !define MUI_HEADERIMAGE_RIGHT
+ !define MUI_ABORTWARNING
+
+;--------------------------------
+;Pages
+
+ ;!insertmacro MUI_PAGE_LICENSE "tmp/LICENCE"
+ ;!insertmacro MUI_PAGE_COMPONENTS
+ !insertmacro MUI_PAGE_DIRECTORY
+
+ ;Start Menu Folder Page Configuration
+ !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
+ !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Mist"
+ !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
+
+ ;!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
+
+ !insertmacro MUI_PAGE_INSTFILES
+
+ !insertmacro MUI_UNPAGE_CONFIRM
+ !insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+;Languages
+
+ !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Installer Sections
+
+Section
+
+ SetOutPath "$INSTDIR"
+
+ file /r $%GOPATH%\pkg\ethereum\*.*
+ file logo.ico
+
+ ;Store installation folder
+ WriteRegStr HKCU "Software\Mist" "" $INSTDIR
+
+ ;Create uninstaller
+ WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+
+ CreateShortCut "$DESKTOP\Mist.lnk" "$INSTDIR\mist.exe" "" "$INSTDIR\logo.ico" 0
+
+ ;create start-menu items
+ CreateDirectory "$SMPROGRAMS\Mist"
+ CreateShortCut "$SMPROGRAMS\Mist\Uninstall.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
+ CreateShortCut "$SMPROGRAMS\Mist\Mist.lnk" "$INSTDIR\mist.exe" "" "$INSTDIR\logo.ico" 0
+
+SectionEnd
+
+;--------------------------------
+;Descriptions
+
+ ;Assign language strings to sections
+ ;!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ ; !insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy)
+ ;!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;--------------------------------
+;Uninstaller Section
+
+Section "Uninstall"
+
+ ;ADD YOUR OWN FILES HERE...
+ RMDir /r "$INSTDIR\*.*"
+
+ RMDir "$INSTDIR"
+
+ Delete "$DESKTOP\Mist.lnk"
+ Delete "$SMPROGRAMS\Mist\*.*"
+ RmDir "$SMPROGRAMS\Mist"
+
+ DeleteRegKey /ifempty HKCU "Software\Mist"
+
+SectionEnd
diff --git a/deploy/windows/ethereum.bmp b/deploy/windows/ethereum.bmp
new file mode 100644
index 0000000000..7c52420932
Binary files /dev/null and b/deploy/windows/ethereum.bmp differ
diff --git a/deploy/windows/logo.ico b/deploy/windows/logo.ico
new file mode 100644
index 0000000000..bc85a69ddc
Binary files /dev/null and b/deploy/windows/logo.ico differ