build: implement packaging steps for the Windows build
Implement a `pkg-windows` target that ultimately results in `Status.zip` being written to `pkg/`. Note: this commit does not introduce code signing for the Windows build since that piece is still a work in progress. `pkg-windows` creates a portable folder in `tmp/windows/dist` with the help of [`windeployqt`][windeployqt], which copies the needed portions of Qt into the folder. Since DLL resolution is relatively inflexible, a launcher `Status.exe` is created at the top-level of the folder; the launcher opens `bin/Status.exe` while adding the portable folder's `bin/` to the `PATH`, allowing `bin/Status.exe` to resolve the DLLs in that folder. A few additional tools need to be installed (e.g. with [scoop][scoop]) and availble in `PATH`: * 7-zip * dos2unix (provides unix2dos) * findutils * go * rcedit * wget The above list builds on the tools list in PR #521, and the other requirements and instructions in that PR's description still apply. **Why not build an installer?** When starting work on packaging for the Windows build, my initial plan was to build an installer, and for that purpose I researched the [WiX Toolset][wix], the [Qt Installer Framework][qtif], and some other options. I found that building an installer is a bit complex. I then recalled, from personal experience, that [Cmder][cmder]'s [Mini download][mini] is installer-less. You simply unzip the download and place the `cmder_mini` folder wherever you prefer. Such an approach was also recommended to me in one of the Nim language's community chats. In addition to being simpler, the installer-less approach also gives installation of Status Desktop a lower profile than an installer-application would since nothing is written to the Windows registry, added to the *Add or remove programs* list, etc. I think that's a benefit given the privacy-security focus of Status, but others may feel differently so please provide feedback on this point! [windeployqt]: https://doc.qt.io/qt-5/windows-deployment.html [scoop]: https://scoop.sh/ [wix]: https://wixtoolset.org/ [qtif]: https://doc.qt.io/qtinstallerframework/index.html [cmder]: https://cmder.net/ [mini]: https://github.com/cmderdev/cmder/releases/download/v1.3.15/cmder_mini.zip
This commit is contained in:
parent
449b8c0454
commit
29e74b6b3f
91
Makefile
91
Makefile
|
@ -18,9 +18,13 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
|
|||
bottles \
|
||||
bottles-dummy \
|
||||
bottles-macos \
|
||||
check-pkg-target-linux \
|
||||
check-pkg-target-macos \
|
||||
check-pkg-target-windows \
|
||||
clean \
|
||||
deps \
|
||||
nim_status_client \
|
||||
nim_windows_launcher \
|
||||
pkg \
|
||||
pkg-linux \
|
||||
pkg-macos \
|
||||
|
@ -70,13 +74,31 @@ ifeq ($(detected_OS),Darwin)
|
|||
else ifeq ($(detected_OS),Windows)
|
||||
BOTTLES_TARGET := bottles-dummy
|
||||
PKG_TARGET := pkg-windows
|
||||
QRCODEGEN_MAKE_PARAMS := CC=gcc
|
||||
RUN_TARGET := run-windows
|
||||
VCINSTALLDIR ?= C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\
|
||||
export VCINSTALLDIR
|
||||
else
|
||||
BOTTLES_TARGET := bottles-dummy
|
||||
PKG_TARGET := pkg-linux
|
||||
RUN_TARGET := run-linux-or-macos
|
||||
endif
|
||||
|
||||
check-pkg-target-linux:
|
||||
ifneq ($(detected_OS),Linux)
|
||||
$(error The pkg-linux target must be run on Linux)
|
||||
endif
|
||||
|
||||
check-pkg-target-macos:
|
||||
ifneq ($(detected_OS),Darwin)
|
||||
$(error The pkg-macos target must be run on macOS)
|
||||
endif
|
||||
|
||||
check-pkg-target-windows:
|
||||
ifneq ($(detected_OS),Windows)
|
||||
$(error The pkg-windows target must be run on Windows)
|
||||
endif
|
||||
|
||||
bottles: $(BOTTLES_TARGET)
|
||||
|
||||
bottles-dummy: ;
|
||||
|
@ -142,7 +164,6 @@ else
|
|||
DOTHERSIDE_BUILD_CMD := cmake --build . --config Release $(HANDLE_OUTPUT)
|
||||
NIM_PARAMS += -L:$(DOTHERSIDE)
|
||||
NIM_EXTRA_PARAMS := --passL:"-lsetupapi -lhid"
|
||||
QRCODEGEN_MAKE_PARAMS := CC=gcc
|
||||
endif
|
||||
|
||||
# TODO: control debug/release builds with a Make var
|
||||
|
@ -206,6 +227,7 @@ STATUS_CLIENT_APPIMAGE ?= pkg/NimStatusClient-x86_64.AppImage
|
|||
|
||||
$(STATUS_CLIENT_APPIMAGE): nim_status_client $(APPIMAGE_TOOL) nim-status.desktop
|
||||
rm -rf pkg/*.AppImage
|
||||
rm -rf tmp/linux/dist
|
||||
mkdir -p tmp/linux/dist/usr/bin
|
||||
mkdir -p tmp/linux/dist/usr/lib
|
||||
mkdir -p tmp/linux/dist/usr/qml
|
||||
|
@ -285,18 +307,69 @@ ifdef MACOS_CODESIGN_IDENT
|
|||
scripts/sign-macos-pkg.sh $(STATUS_CLIENT_DMG) $(MACOS_CODESIGN_IDENT)
|
||||
endif
|
||||
|
||||
STATUS_CLIENT_EXE ?= pkg/Status.exe
|
||||
NIM_WINDOWS_PREBUILT_DLLS ?= tmp/windows/tools/pcre.dll
|
||||
|
||||
# not implemented yet
|
||||
# $(STATUS_CLIENT_EXE): nim_status_client
|
||||
$(NIM_WINDOWS_PREBUILT_DLLS):
|
||||
echo -e "\e[92mFetching:\e[39m prebuilt DLLs from nim-lang.org"
|
||||
rm -rf tmp/windows
|
||||
mkdir -p tmp/windows/tools
|
||||
cd tmp/windows/tools && \
|
||||
wget https://nim-lang.org/download/dlls.zip && \
|
||||
unzip dlls.zip
|
||||
|
||||
nim_windows_launcher: | deps
|
||||
$(ENV_SCRIPT) nim c -d:debug --outdir:./bin --passL:"-static-libgcc -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive" src/nim_windows_launcher.nim
|
||||
|
||||
STATUS_CLIENT_ZIP ?= pkg/Status.zip
|
||||
|
||||
$(STATUS_CLIENT_ZIP): nim_status_client nim_windows_launcher $(NIM_WINDOWS_PREBUILT_DLLS)
|
||||
rm -rf pkg/*.zip
|
||||
rm -rf tmp/windows/dist
|
||||
mkdir -p tmp/windows/dist/Status/bin
|
||||
mkdir -p tmp/windows/dist/Status/resources
|
||||
mkdir -p tmp/windows/dist/Status/vendor
|
||||
cp windows-install.txt tmp/windows/dist/Status/INSTALL.txt
|
||||
unix2dos -k tmp/windows/dist/Status/INSTALL.txt
|
||||
# cp LICENSE tmp/windows/dist/Status/LICENSE.txt
|
||||
# unix2dos -k tmp/windows/dist/Status/LICENSE.txt
|
||||
cp status.ico tmp/windows/dist/Status/resources/
|
||||
cp status.svg tmp/windows/dist/Status/resources/
|
||||
cp resources.rcc tmp/windows/dist/Status/resources/
|
||||
cp bin/nim_status_client.exe tmp/windows/dist/Status/bin/Status.exe
|
||||
mv bin/nim_windows_launcher.exe tmp/windows/dist/Status/Status.exe
|
||||
rcedit \
|
||||
tmp/windows/dist/Status/bin/Status.exe \
|
||||
--set-icon tmp/windows/dist/Status/resources/status.ico
|
||||
rcedit \
|
||||
tmp/windows/dist/Status/Status.exe \
|
||||
--set-icon tmp/windows/dist/Status/resources/status.ico
|
||||
cp $(DOTHERSIDE) tmp/windows/dist/Status/bin/
|
||||
cp tmp/windows/tools/*.dll tmp/windows/dist/Status/bin/
|
||||
cp "$(shell which libgcc_s_seh-1.dll)" tmp/windows/dist/Status/bin/
|
||||
cp "$(shell which libwinpthread-1.dll)" tmp/windows/dist/Status/bin/
|
||||
|
||||
echo -e $(BUILD_MSG) "deployable folder"
|
||||
windeployqt \
|
||||
--compiler-runtime \
|
||||
--qmldir ui \
|
||||
--release \
|
||||
tmp/windows/dist/Status/bin/DOtherSide.dll
|
||||
mv tmp/windows/dist/Status/bin/vc_redist.x64.exe tmp/windows/dist/Status/vendor/
|
||||
# implement code signing of applicable files in deployable folder
|
||||
|
||||
echo -e $(BUILD_MSG) "zip"
|
||||
mkdir -p pkg
|
||||
cd tmp/windows/dist/Status && \
|
||||
7z a ../../../../pkg/Status.zip *
|
||||
# can the final .zip file be code signed as well?
|
||||
|
||||
pkg: $(PKG_TARGET)
|
||||
|
||||
pkg-linux: $(STATUS_CLIENT_APPIMAGE)
|
||||
pkg-linux: check-pkg-target-linux $(STATUS_CLIENT_APPIMAGE)
|
||||
|
||||
pkg-macos: $(STATUS_CLIENT_DMG)
|
||||
pkg-macos: check-pkg-target-macos $(STATUS_CLIENT_DMG)
|
||||
|
||||
pkg-windows: $(STATUS_CLIENT_EXE)
|
||||
pkg-windows: check-pkg-target-windows $(STATUS_CLIENT_ZIP)
|
||||
|
||||
clean: | clean-common
|
||||
rm -rf bin/* node_modules pkg/* tmp/* $(STATUSGO)
|
||||
|
@ -312,10 +385,10 @@ run-linux-or-macos:
|
|||
LD_LIBRARY_PATH="$(QT5_LIBDIR)" \
|
||||
./bin/nim_status_client
|
||||
|
||||
run-windows:
|
||||
run-windows: $(NIM_WINDOWS_PREBUILT_DLLS)
|
||||
echo -e "\e[92mRunning:\e[39m bin/nim_status_client.exe"
|
||||
NIM_STATUS_CLIENT_DEV="$(NIM_STATUS_CLIENT_DEV)" \
|
||||
PATH="$(shell pwd)"/"$(shell dirname "$(DOTHERSIDE)")":"$(PATH)" \
|
||||
PATH="$(shell pwd)"/"$(shell dirname "$(DOTHERSIDE)")":"$(shell pwd)"/"$(shell dirname "$(NIM_WINDOWS_PREBUILT_DLLS)")":"$(PATH)" \
|
||||
./bin/nim_status_client.exe
|
||||
|
||||
endif # "variables.mk" was not included
|
||||
|
|
|
@ -23,6 +23,7 @@ if defined(macosx):
|
|||
# set the minimum supported macOS version to 10.13
|
||||
switch("passC", "-mmacosx-version-min=10.13")
|
||||
elif defined(windows):
|
||||
--app:gui
|
||||
--tlsEmulation:off
|
||||
switch("passL", "-Wl,-as-needed")
|
||||
else:
|
||||
|
|
|
@ -25,9 +25,19 @@ proc mainProc() =
|
|||
initializeOpenGL()
|
||||
|
||||
let app = newQApplication("Nim Status Client")
|
||||
QResource.registerResource(app.applicationDirPath & "/../resources.rcc")
|
||||
let resources =
|
||||
if defined(windows) and getEnv("NIM_STATUS_CLIENT_DEV").string == "":
|
||||
"/../resources/resources.rcc"
|
||||
else:
|
||||
"/../resources.rcc"
|
||||
QResource.registerResource(app.applicationDirPath & resources)
|
||||
|
||||
app.icon(app.applicationDirPath & "/../status.svg")
|
||||
let statusSvg =
|
||||
if defined(windows) and getEnv("NIM_STATUS_CLIENT_DEV").string == "":
|
||||
"/../resources/status.svg"
|
||||
else:
|
||||
"/../status.svg"
|
||||
app.icon(app.applicationDirPath & statusSvg)
|
||||
|
||||
let engine = newQQmlApplicationEngine()
|
||||
let signalController = signals.newController(app)
|
||||
|
@ -54,7 +64,7 @@ proc mainProc() =
|
|||
profile.init(args.account)
|
||||
wallet.init()
|
||||
chat.init()
|
||||
|
||||
|
||||
|
||||
var login = login.newController(status)
|
||||
var onboarding = onboarding.newController(status)
|
||||
|
@ -84,7 +94,7 @@ proc mainProc() =
|
|||
node.init()
|
||||
login.init()
|
||||
onboarding.init()
|
||||
|
||||
|
||||
initControllers()
|
||||
|
||||
# Handle node.stopped signal when user has logged out
|
||||
|
@ -100,7 +110,7 @@ proc mainProc() =
|
|||
# node.reset()
|
||||
# wallet.reset()
|
||||
# profile.reset()
|
||||
|
||||
|
||||
# 2. Re-init controllers that don't require a running node
|
||||
initControllers()
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
from os import getCurrentDir, joinPath
|
||||
from winlean import Handle, shellExecuteW
|
||||
|
||||
const NULL: Handle = 0
|
||||
let cwd = getCurrentDir()
|
||||
let workDir_str = joinPath(cwd, "bin")
|
||||
let exePath_str = joinPath(workDir_str, "Status.exe")
|
||||
let open_str = "open"
|
||||
let params_str = ""
|
||||
let workDir = newWideCString(workDir_str)
|
||||
let exePath = newWideCString(exePath_str)
|
||||
let open = newWideCString(open_str)
|
||||
let params = newWideCString(params_str)
|
||||
# SW_SHOW (5): activates window and displays it in its current size and position
|
||||
const showCmd: int32 = 5
|
||||
|
||||
discard shellExecuteW(NULL, open, exePath, params, workDir, showCmd)
|
|
@ -0,0 +1,42 @@
|
|||
REQUIREMENTS
|
||||
============
|
||||
|
||||
This application requires 64-bit Windows 7 or newer.
|
||||
|
||||
INSTALLING
|
||||
==========
|
||||
|
||||
After unzipping Status.zip, the Status folder can be placed wherever you prefer
|
||||
(and have permissions) on your computer.
|
||||
|
||||
RUNNING
|
||||
=======
|
||||
|
||||
Double-click Status.exe in the Status folder to launch the application.
|
||||
|
||||
If you see an error complaining about a DLL file, you should open
|
||||
vc_redist.x64.exe in the Status\vendor folder to install the Microsoft Visual
|
||||
C++ Redistributable. This is usually necessary only on versions of Windows
|
||||
older than Windows 10. Then retry launching the application.
|
||||
|
||||
You may wish to right-click Status.exe and "Send to > Desktop (create shortcut)".
|
||||
The application can then be launched by double-clicking the shortcut on your
|
||||
desktop.
|
||||
|
||||
Status.exe persists settings and encrypted data in your %LOCALAPPDATA%\Status
|
||||
folder.
|
||||
|
||||
UPGRADING
|
||||
=========
|
||||
|
||||
To upgrade this application download the latest Status.zip, delete this Status
|
||||
folder and the older Status.zip, unzip the newer one, and then place the new
|
||||
Status folder in your preferred location.
|
||||
|
||||
If you place the new Status folder in a different location than the old one
|
||||
then you should recreate any shortcuts you created for Status.exe.
|
||||
|
||||
UNINSTALLING
|
||||
============
|
||||
|
||||
Delete this Status folder and delete your %LOCALAPPDATA%\Status folder.
|
Loading…
Reference in New Issue