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 \
|
||||||
bottles-dummy \
|
bottles-dummy \
|
||||||
bottles-macos \
|
bottles-macos \
|
||||||
|
check-pkg-target-linux \
|
||||||
|
check-pkg-target-macos \
|
||||||
|
check-pkg-target-windows \
|
||||||
clean \
|
clean \
|
||||||
deps \
|
deps \
|
||||||
nim_status_client \
|
nim_status_client \
|
||||||
|
nim_windows_launcher \
|
||||||
pkg \
|
pkg \
|
||||||
pkg-linux \
|
pkg-linux \
|
||||||
pkg-macos \
|
pkg-macos \
|
||||||
|
@ -70,13 +74,31 @@ ifeq ($(detected_OS),Darwin)
|
||||||
else ifeq ($(detected_OS),Windows)
|
else ifeq ($(detected_OS),Windows)
|
||||||
BOTTLES_TARGET := bottles-dummy
|
BOTTLES_TARGET := bottles-dummy
|
||||||
PKG_TARGET := pkg-windows
|
PKG_TARGET := pkg-windows
|
||||||
|
QRCODEGEN_MAKE_PARAMS := CC=gcc
|
||||||
RUN_TARGET := run-windows
|
RUN_TARGET := run-windows
|
||||||
|
VCINSTALLDIR ?= C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\
|
||||||
|
export VCINSTALLDIR
|
||||||
else
|
else
|
||||||
BOTTLES_TARGET := bottles-dummy
|
BOTTLES_TARGET := bottles-dummy
|
||||||
PKG_TARGET := pkg-linux
|
PKG_TARGET := pkg-linux
|
||||||
RUN_TARGET := run-linux-or-macos
|
RUN_TARGET := run-linux-or-macos
|
||||||
endif
|
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: $(BOTTLES_TARGET)
|
||||||
|
|
||||||
bottles-dummy: ;
|
bottles-dummy: ;
|
||||||
|
@ -142,7 +164,6 @@ else
|
||||||
DOTHERSIDE_BUILD_CMD := cmake --build . --config Release $(HANDLE_OUTPUT)
|
DOTHERSIDE_BUILD_CMD := cmake --build . --config Release $(HANDLE_OUTPUT)
|
||||||
NIM_PARAMS += -L:$(DOTHERSIDE)
|
NIM_PARAMS += -L:$(DOTHERSIDE)
|
||||||
NIM_EXTRA_PARAMS := --passL:"-lsetupapi -lhid"
|
NIM_EXTRA_PARAMS := --passL:"-lsetupapi -lhid"
|
||||||
QRCODEGEN_MAKE_PARAMS := CC=gcc
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# TODO: control debug/release builds with a Make var
|
# 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
|
$(STATUS_CLIENT_APPIMAGE): nim_status_client $(APPIMAGE_TOOL) nim-status.desktop
|
||||||
rm -rf pkg/*.AppImage
|
rm -rf pkg/*.AppImage
|
||||||
|
rm -rf tmp/linux/dist
|
||||||
mkdir -p tmp/linux/dist/usr/bin
|
mkdir -p tmp/linux/dist/usr/bin
|
||||||
mkdir -p tmp/linux/dist/usr/lib
|
mkdir -p tmp/linux/dist/usr/lib
|
||||||
mkdir -p tmp/linux/dist/usr/qml
|
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)
|
scripts/sign-macos-pkg.sh $(STATUS_CLIENT_DMG) $(MACOS_CODESIGN_IDENT)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STATUS_CLIENT_EXE ?= pkg/Status.exe
|
NIM_WINDOWS_PREBUILT_DLLS ?= tmp/windows/tools/pcre.dll
|
||||||
|
|
||||||
# not implemented yet
|
$(NIM_WINDOWS_PREBUILT_DLLS):
|
||||||
# $(STATUS_CLIENT_EXE): nim_status_client
|
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: $(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
|
clean: | clean-common
|
||||||
rm -rf bin/* node_modules pkg/* tmp/* $(STATUSGO)
|
rm -rf bin/* node_modules pkg/* tmp/* $(STATUSGO)
|
||||||
|
@ -312,10 +385,10 @@ run-linux-or-macos:
|
||||||
LD_LIBRARY_PATH="$(QT5_LIBDIR)" \
|
LD_LIBRARY_PATH="$(QT5_LIBDIR)" \
|
||||||
./bin/nim_status_client
|
./bin/nim_status_client
|
||||||
|
|
||||||
run-windows:
|
run-windows: $(NIM_WINDOWS_PREBUILT_DLLS)
|
||||||
echo -e "\e[92mRunning:\e[39m bin/nim_status_client.exe"
|
echo -e "\e[92mRunning:\e[39m bin/nim_status_client.exe"
|
||||||
NIM_STATUS_CLIENT_DEV="$(NIM_STATUS_CLIENT_DEV)" \
|
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
|
./bin/nim_status_client.exe
|
||||||
|
|
||||||
endif # "variables.mk" was not included
|
endif # "variables.mk" was not included
|
||||||
|
|
|
@ -23,6 +23,7 @@ if defined(macosx):
|
||||||
# set the minimum supported macOS version to 10.13
|
# set the minimum supported macOS version to 10.13
|
||||||
switch("passC", "-mmacosx-version-min=10.13")
|
switch("passC", "-mmacosx-version-min=10.13")
|
||||||
elif defined(windows):
|
elif defined(windows):
|
||||||
|
--app:gui
|
||||||
--tlsEmulation:off
|
--tlsEmulation:off
|
||||||
switch("passL", "-Wl,-as-needed")
|
switch("passL", "-Wl,-as-needed")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -25,9 +25,19 @@ proc mainProc() =
|
||||||
initializeOpenGL()
|
initializeOpenGL()
|
||||||
|
|
||||||
let app = newQApplication("Nim Status Client")
|
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 engine = newQQmlApplicationEngine()
|
||||||
let signalController = signals.newController(app)
|
let signalController = signals.newController(app)
|
||||||
|
|
|
@ -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