Skip to content

Commit

Permalink
PTFM-18032 dx-toolkit Windows installer
Browse files Browse the repository at this point in the history
Summary:
Added a make target ('make pynsist_installer') which creates an .exe installer that delivers:

dxpy
dx.exe (and other scripts provided with dxpy)
dx-verify-file.exe
ua.exe

Test Plan: Built installer and tested on Windows 7 and Windows Server 2012.

Reviewers: brogoff, nicolasbockg

Reviewed By: nicolasbockg

Differential Revision: https://dnanexus.phacility.com/D1034
  • Loading branch information
billagee committed Jul 26, 2016
1 parent a9cd722 commit dc7c049
Show file tree
Hide file tree
Showing 9 changed files with 442 additions and 4 deletions.
2 changes: 2 additions & 0 deletions build/pynsist_files/cli-quickstart.url
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://wiki.dnanexus.com/Command-Line-Client/Quickstart
51 changes: 51 additions & 0 deletions build/pynsist_files/dnanexus-shell.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
@echo off
REM Copyright (C) 2013-2016 DNAnexus, Inc.
REM
REM This file is part of dx-toolkit (DNAnexus platform client libraries).
REM
REM Licensed under the Apache License, Version 2.0 (the "License"); you may not
REM use this file except in compliance with the License. You may obtain a copy
REM of the License at
REM
REM http://www.apache.org/licenses/LICENSE-2.0
REM
REM Unless required by applicable law or agreed to in writing, software
REM distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
REM WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
REM License for the specific language governing permissions and limitations
REM under the License.
REM
REM
REM Run this file in Command Prompt to initialize DNAnexus environment vars.

REM Set DNANEXUS_HOME to the location of this file
set "SOURCE_DIR=%~dp0"
set "DNANEXUS_HOME=%SOURCE_DIR%"

REM Add bin dir to PATH
set "PATH=%DNANEXUS_HOME%bin;%PATH%"

REM Check the registry for the Python27 path:
set PY27_KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Python\PythonCore\2.7\InstallPath"
FOR /F "usebackq skip=2 tokens=1,2*" %%A IN (
`REG QUERY %PY27_KEY_NAME% /ve 2^>nul`) DO (
set PY_INSTALL_DIR=%%C
)
if defined PY_INSTALL_DIR echo PY_INSTALL_DIR = %PY_INSTALL_DIR%
if NOT defined PY_INSTALL_DIR (
msg %USERNAME% Python installation dir not found!
exit 1
)

REM Add Python27 and Python27\Scripts to PATH
set "PATH=%PY_INSTALL_DIR%;%PY_INSTALL_DIR%Scripts;%PATH%"

REM Set PYTHONPATH so the dx-*.exe wrappers can locate dxpy
set "PYTHONPATH=%DNANEXUS_HOME%share\dnanexus\lib\python2.7\site-packages"

REM Regenerate the dxpy console script .exe wrappers, so the .exes can
REM locate python.exe on this machine
REM python -m wheel install-scripts dxpy

REM Bring up the interactive shell
start cmd.exe /u /k echo DNAnexus CLI initialized. For help, run: 'dx help'
38 changes: 38 additions & 0 deletions build/pynsist_files/dnanexus-shell.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2013-2016 DNAnexus, Inc.
#
# This file is part of dx-toolkit (DNAnexus platform client libraries).
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
#
# Run this file in PowerShell to initialize DNAnexus environment vars.

# Set DNANEXUS_HOME to the location of this file
$script:THIS_PATH = $myinvocation.mycommand.path
$script:BASE_DIR = split-path (resolve-path "$THIS_PATH") -Parent
$env:DNANEXUS_HOME = $BASE_DIR

# Add bin and Scripts dirs to PATH so dx*.exe are available
$env:PATH = "C:/Python27;$env:DNANEXUS_HOME/bin;$env:DNANEXUS_HOME/python27/Scripts;" + $env:PATH

# Add our custom Lib dir to PYTHONPATH so the dx*.exe wrappers can locate dxpy
$env:PYTHONPATH = "$env:DNANEXUS_HOME/python27/Lib/site-packages;" + $env:PYTHONPATH

# Set utf-8 as default IO encoding
$env:PYTHONIOENCODING = "utf-8"

# Print banner
"DNAnexus CLI initialized. For help, run: 'dx help'"
""
"Client version: " + (dx --version)
""
Binary file added build/pynsist_files/dnanexus.ico
Binary file not shown.
74 changes: 74 additions & 0 deletions build/pynsist_files/installer.cfg.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[Application]
name=DNAnexus CLI
target=powershell.exe
parameters=-ExecutionPolicy Bypass -NoLogo -NoExit -File "$INSTDIR\dnanexus-shell.ps1"
#console=true
version=TEMPLATE_STRING_TOOLKIT_VERSION
icon=dnanexus.ico
# To point shortcut at dx instead:
#entry_point=dxpy.scripts.dx:main
#extra_preamble=prerun-stuff.py

[Shortcut DNAnexus Help]
target=$INSTDIR\cli-quickstart.url
icon=dnanexus.ico

# Shortcut for the .bat cmd.exe launcher:
#[Shortcut DNAnexus CLI (cmd)]
#target=$INSTDIR\dnanexus-shell.bat
##parameters=
#console=true

# How to add a shortcut for a python script:
#[Shortcut dx-app-wizard]
#entry_point=dxpy.scripts.dx_app_wizard:main
#console=true
#icon=foo.ico

[Python]
version=2.7.11
format=installer

[Build]
nsi_template=pyapp_installpy_dnanexus.nsi

[Include]
# Importable packages that your application requires, one per line
#packages = dxpy
# bs4
# colorama
# concurrent
# dateutil
# magic
# requests
# six
# wheel
# ws4py

# Other files and folders that should be installed
files = dnanexus-shell.ps1
cli-quickstart.url
TEMPLATE_STRING_DXPY_WHEEL_FILENAME
../../bin/dx-verify-file.exe > $INSTDIR\\bin
../../bin/jq.exe > $INSTDIR\\bin
../../src/ua/dist/ua.exe > $INSTDIR\\bin
../../src/ua/dist/libboost_atomic-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_chrono-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_date_time-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_filesystem-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_iostreams-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_program_options-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_regex-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_signals-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_system-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libboost_thread-mt.dll > $INSTDIR\\bin
../../src/ua/dist/libcares-2.dll > $INSTDIR\\bin
../../src/ua/dist/libcurl-4.dll > $INSTDIR\\bin
../../src/ua/dist/libeay32.dll > $INSTDIR\\bin
../../src/ua/dist/libgcc_s_dw2-1.dll > $INSTDIR\\bin
../../src/ua/dist/libgnurx-0.dll > $INSTDIR\\bin
../../src/ua/dist/libmagic-1.dll > $INSTDIR\\bin
../../src/ua/dist/libstdc++-6.dll > $INSTDIR\\bin
../../src/ua/dist/magic.mgc > $INSTDIR\\bin
../../src/ua/dist/ssleay32.dll > $INSTDIR\\bin
../../src/ua/dist/zlib1.dll > $INSTDIR\\bin
192 changes: 192 additions & 0 deletions build/pynsist_files/pyapp_dnanexus.nsi.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
; dx-toolkit NSIS installer config file - based on default pynsist template:
; https://github.com/takluyver/pynsist/blob/master/nsist/pyapp.nsi

!define COMPANYNAME "DNAnexus Inc."
!define DXPY_WHEEL_FILENAME "TEMPLATE_STRING_DXPY_WHEEL_FILENAME"
!define PRODUCT_NAME "[[ib.appname]]"
!define PRODUCT_VERSION "[[ib.version]]"
!define PY_VERSION "[[ib.py_version]]"
!define PY_MAJOR_VERSION "[[ib.py_major_version]]"
!define BITNESS "[[ib.py_bitness]]"
!define ARCH_TAG "[[arch_tag]]"
!define INSTALLER_NAME "[[ib.installer_name]]"
!define PRODUCT_ICON "[[icon]]"

SetCompressor lzma

RequestExecutionLevel admin

[% block modernui %]
; Modern UI installer stuff
!include "MUI2.nsh"
!define MUI_ABORTWARNING
;!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_ICON "[[icon]]"

; UI pages
[% block ui_pages %]
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
[% endblock ui_pages %]
!insertmacro MUI_LANGUAGE "English"
[% endblock modernui %]

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "${INSTALLER_NAME}"
InstallDir "$PROGRAMFILES${BITNESS}\${PRODUCT_NAME}"
ShowInstDetails show

Section -SETTINGS
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
SectionEnd

[% block sections %]

Section "!${PRODUCT_NAME}" sec_app
SectionIn RO
SetShellVarContext all
File ${PRODUCT_ICON}
SetOutPath "$INSTDIR\pkgs"
File /r "pkgs\*.*"
SetOutPath "$INSTDIR"

; Install files
[% for destination, group in grouped_files %]
SetOutPath "[[destination]]"
[% for file in group %]
File "[[ file ]]"
[% endfor %]
[% endfor %]

; Install directories
[% for dir, destination in ib.install_dirs %]
SetOutPath "[[ pjoin(destination, dir) ]]"
File /r "[[dir]]\*.*"
[% endfor %]

[% block install_shortcuts %]
; Install shortcuts
; The output path becomes the working directory for shortcuts
SetOutPath "%HOMEDRIVE%\%HOMEPATH%"
[% if single_shortcut %]
[% for scname, sc in ib.shortcuts.items() %]
CreateShortCut "$SMPROGRAMS\[[scname]].lnk" "[[sc['target'] ]]" \
'[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
[% endfor %]
[% else %]
[# Multiple shortcuts: create a directory for them #]
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
[% for scname, sc in ib.shortcuts.items() %]
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\[[scname]].lnk" "[[sc['target'] ]]" \
'[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
[% endfor %]
[% endif %]
SetOutPath "$INSTDIR"
[% endblock install_shortcuts %]

; Byte-compile Python files.
DetailPrint "Byte-compiling Python modules..."
nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"'

; Set PYTHONPATH to the dir containing the installed dxpy wheel.
;MessageBox MB_OK 'PYTHONPATH is "$INSTDIR\share\dnanexus\lib\python2.7\site-packages"'
;System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("PYTHONPATH", "$INSTDIR\share\dnanexus\lib\python2.7\site-packages").r0'
;StrCmp $0 0 error
; ; Generate dxpy console script .exe wrappers - they'll be installed in
; ; the user's Python27\Scripts\ dir.
; DetailPrint "Installing wrapper executables..."
; ExecWait '"C:\Python27\python.exe" -m wheel install-scripts dxpy' $0
; ;MessageBox MB_OK 'ExecWait returned "$0"'
; Goto done
;error:
; MessageBox MB_OK "Can't set PYTHONPATH environment variable!"
;done:

DetailPrint "Installing dxpy..."
; Install dxpy, its dependencies, and console scripts in $INSTDIR\python27
ExecWait '"C:\Python27\Scripts\pip.exe" install --root "$INSTDIR" "$INSTDIR\TEMPLATE_STRING_DXPY_WHEEL_FILENAME"' $0
StrCmp $0 0 pass error
pass:
;MessageBox MB_OK 'dxpy installed'
;MessageBox MB_OK 'ExecWait returned "$0"'
Goto done
error:
MessageBox MB_OK 'Error: dxpy installation failed!'
MessageBox MB_OK 'ExecWait returned "$0"'
done:

WriteUninstaller $INSTDIR\uninstall.exe
; Add ourselves to Add/remove programs
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"DisplayIcon" "$INSTDIR\${PRODUCT_ICON}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"Publisher" "${COMPANYNAME}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"NoRepair" 1

; Check if we need to reboot
IfRebootFlag 0 noreboot
MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" \
/SD IDNO IDNO noreboot
Reboot
noreboot:
SectionEnd

Section "Uninstall"
DetailPrint "Uninstalling dxpy root..."
RMDir /r "$INSTDIR\python27"
DetailPrint "Uninstalling bin dir..."
RMDir /r "$INSTDIR\bin"

SetShellVarContext all
Delete $INSTDIR\uninstall.exe
Delete "$INSTDIR\${PRODUCT_ICON}"
RMDir /r "$INSTDIR\pkgs"
; Uninstall files
[% for file, destination in ib.install_files %]
Delete "[[pjoin(destination, file)]]"
[% endfor %]
; Uninstall directories
[% for dir, destination in ib.install_dirs %]
RMDir /r "[[pjoin(destination, dir)]]"
[% endfor %]
[% block uninstall_shortcuts %]
; Uninstall shortcuts
[% if single_shortcut %]
[% for scname in ib.shortcuts %]
Delete "$SMPROGRAMS\[[scname]].lnk"
[% endfor %]
[% else %]
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
[% endif %]
[% endblock uninstall_shortcuts %]
RMDir $INSTDIR
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
SectionEnd

[% endblock sections %]

; Functions

Function .onMouseOverSection
; Find which section the mouse is over, and set the corresponding description.
FindWindow $R0 "#32770" "" $HWNDPARENT
GetDlgItem $R0 $R0 1043 ; description item (must be added to the UI)

[% block mouseover_messages %]
StrCmp $0 ${sec_app} "" +2
SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}"

[% endblock mouseover_messages %]
FunctionEnd
Loading

0 comments on commit dc7c049

Please sign in to comment.