diff --git a/INSTALL.nut.adoc b/INSTALL.nut.adoc index 5563f81b17..302b3b5948 100644 --- a/INSTALL.nut.adoc +++ b/INSTALL.nut.adoc @@ -633,8 +633,8 @@ It should currently be possible to build the codebase in native Windows with MSYS2/MinGW and cross-building from Linux with mingw (preferably in a Debian/Ubuntu container). Refer to link:config-prereqs.txt[Prerequisites for building NUT on different OSes] -and link:scripts/Windows/README[scripts/Windows/README file] for respective -build environment preparation instructions. +and link:scripts/Windows/README.adoc[scripts/Windows/README.adoc file] +for respective build environment preparation instructions. Note that to use NUT for Windows, non-system dependency DLL files must be located in same directory as each EXE file that uses them. This can be @@ -679,7 +679,7 @@ Building for Windows For suggestions about setting up the NUT build environment variants for Windows, please see link:docs/config-prereqs.txt and/or -link:scripts/Windows/README files. Note this is rather experimental +link:scripts/Windows/README.adoc files. Note this is rather experimental at this point. diff --git a/NEWS.adoc b/NEWS.adoc index 97df10241d..a8424c8eb8 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -233,7 +233,8 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. It is known that at this time some features are not complete, for more details see https://github.com/orgs/networkupstools/projects/2/views/1 * Cross-builds of NUT for Windows using Linux and MinGW (and many custom - built dependency packages, as documented in link:scripts/Windows/README[]) + built dependency packages, as documented in the + link:scripts/Windows/README.adoc[scripts/Windows/README.adoc file]) are now regularly tested on NUT CI farm with moderate integration via custom build script `scripts/Windows/build-mingw-nut.sh` [#1489] * Semi-native NUT for Windows builds with MSYS2/MinGW x64 environment are diff --git a/appveyor.yml b/appveyor.yml index 1ab71e3f99..e9e55e444e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,7 +55,7 @@ install: before_build: - cmd: | REM Ensure we have a net-snmp to build against - REM Adapted from scripts/Windows/README document. + REM Adapted from scripts/Windows/README.adoc document. REM Here we hope to build it once, then use the REM stashed version across Appveyor rebuilds. REM Preserve the current working directory: diff --git a/ci_build.sh b/ci_build.sh index 66699ab2dc..ba903c622b 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -1982,9 +1982,9 @@ bindings) # These mingw modes below are currently experimental and not too integrated # with this script per se; it is intended to run for NUT CI farm on prepared -# Linux+mingw worker nodes (see scripts/Windows/README) in an uniform manner, -# using mostly default settings (warnings in particular) and some hardcoded -# in that script (ARCH, CFLAGS, ...). +# Linux+mingw worker nodes (see scripts/Windows/README.adoc) in an uniform +# manner, using mostly default settings (warnings in particular) and some +# values hardcoded in that script (ARCH, CFLAGS, ...). # Note that semi-native builds with e.g. MSYS2 on Windows should "just work" as # on any other supported platform (more details in docs/config-prereqs.txt). cross-windows-mingw*) diff --git a/configure.ac b/configure.ac index 102d03027e..83c64c7cf4 100644 --- a/configure.ac +++ b/configure.ac @@ -4541,6 +4541,7 @@ AC_CONFIG_FILES([ scripts/ufw/Makefile scripts/ufw/nut.ufw.profile scripts/Windows/Makefile + scripts/Windows/Installer/NUT-Installer.xml scripts/Makefile server/Makefile tools/Makefile diff --git a/docs/config-prereqs.txt b/docs/config-prereqs.txt index ebecf9f1ec..ca581bdfae 100644 --- a/docs/config-prereqs.txt +++ b/docs/config-prereqs.txt @@ -1191,7 +1191,7 @@ antivirus completely or exempt at least the NUT build area from protection. Windows with mingw ------------------ -See `scripts/Windows/README` for original recommendations for the effort, +See `scripts/Windows/README.adoc` for original recommendations for the effort, including possibilities of cross-builds with mingw available in Linux. Unfortunately these did not work for me at the time of testing, yielding @@ -1209,7 +1209,7 @@ and redirect on SourceForge. You can download and unpack 7z archives from https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/ into e.g. `C:\Progra~1\mingw-w64\x86_64-8.1.0-release-posix-seh-rt_v6-rev0` location on your Windows system. Then for building further NUT dependencies -see `scripts/Windows/README`. +see `scripts/Windows/README.adoc`. Windows with MSYS2 ------------------ @@ -1344,7 +1344,7 @@ involved is very important. Notable packages *not found* in the repo: -* snmp (net-snmp, ucd-snmp) -- instructions in `scripts/Windows/README` +* snmp (net-snmp, ucd-snmp) -- instructions in `scripts/Windows/README.adoc` document now covers building it from source in MSYS2 MinGW x64 environment, essentially same as for Linux cross builds with proper `ARCH` and `PREFIX` * libregex (C version, direct NUT `configure` script support was added by diff --git a/scripts/Windows/Installer/.gitignore b/scripts/Windows/Installer/.gitignore index 5466afe66c..c3ce80fccc 100644 --- a/scripts/Windows/Installer/.gitignore +++ b/scripts/Windows/Installer/.gitignore @@ -1,4 +1,5 @@ NUT-Installer.msi NUT-Installer.wixobj NUT-Installer.wixpdb +NUT-Installer.xml log.txt diff --git a/scripts/Windows/Installer/NUT-Installer.xml b/scripts/Windows/Installer/NUT-Installer.xml.in similarity index 99% rename from scripts/Windows/Installer/NUT-Installer.xml rename to scripts/Windows/Installer/NUT-Installer.xml.in index 62661d9413..7348d6ac31 100644 --- a/scripts/Windows/Installer/NUT-Installer.xml +++ b/scripts/Windows/Installer/NUT-Installer.xml.in @@ -1,7 +1,7 @@ - - + + diff --git a/scripts/Windows/Installer/README.adoc b/scripts/Windows/Installer/README.adoc new file mode 100644 index 0000000000..21f16d7712 --- /dev/null +++ b/scripts/Windows/Installer/README.adoc @@ -0,0 +1,130 @@ +NUT for Windows Installer +========================= + +This component aims to provide an integrated installer for NUT on Windows, +including registration as the preferred handler of certain USB vendor and +product identifiers. + +Various waves of the NUT for Windows effort happened over the decades, with +the latest one being integration of the platform-specific source code which +was previously available in side projects, into the main Network UPS Tools +project and its continuous-integration builds, between NUT v2.8.0 and v2.8.1 +releases (over 2022-2023 time frame). + +NOTE: This document aims to revive institutional knowledge about producing +a NUT for Windows installer file. Currently builds of NUT for Windows are +quite possible, they can result in preparation of a tarball of an installed +directory tree which is immediately usable on Windows. However, separate +steps may be needed for USB specifically (so that NUT drivers and not the +default "HID Battery" handler can attach to the device) and for OS Service +integration. It is assumed that the installer would handle these rituals. + +Prerequisites for building NUT for Windows +------------------------------------------ + +Please see the documentation provided with the NUT sources about prerequisites +needed for semi-native builds (on Windows using MinGW x64 and MSYS2 projects) +and cross-builds (on Linux with mingw64 packages): + +* linkdoc:/docs/config-prereqs.txt +* linkdoc:/scripts/Windows/README.adoc + +With these dependencies in place, the common NUT `ci_build.sh` script can be +used to wrap the typical configuration, build and installation procedures. +Similar results can be of course achieved by direct use of the `configure` +script, which may be the way to go particularly for customized builds. + +See also `scripts/Windows/build-mingw-nut.sh` for the cross-build wrapper +details. + +Prerequisites for building the installer +---------------------------------------- + +NUT for Windows uses the WiX Toolset to codify and implement the installer: + +* https://wixtoolset.org/ +* https://wixtoolset.org/docs/intro/ +* https://wixtoolset.org/docs/tools/wixexe/ +* https://wixtoolset.org/docs/tools/heat/ +* link:https://wixtoolset.org/docs/v3/overview/candle/[candle.exe] and + link:https://wixtoolset.org/docs/v3/overview/light/[light.exe] tools + were used in current scripts (dating from 2013) but were obsoleted + after WiX v3 and became part of `wix.exe` according to + https://wixtoolset.org/docs/fourthree/ update notes +* https://github.com/wixtoolset/ +* https://github.com/wixtoolset/wix/ + +The toolset in turn reqires the .NET framework (and the related NuGet tool) +which is available on Windows and Linux platforms, at least. In case of the +latter (for cross-builds) note that many of the newer distribution releases +should include dotnet packages in their repositories; for earlier releases +a Microsoft repository can be added -- as detailed in their documentation: + +* https://learn.microsoft.com/en-us/dotnet/core/install/linux +* https://dotnet.microsoft.com/en-us/download +* https://www.nuget.org/downloads + +For example, on Ubuntu the installation can be performed like this: +---- +:; sudo apt-get update && \ + sudo apt-get install -y dotnet-sdk-7.0 nuget +---- + +NOTE: For installation on Ubuntu 20.04 and older, where an additional +package repository is required, please see instructions at +https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu-2004 + +Subsequent installation of the toolset on either platform would be: +---- +:; dotnet tool install --global wix +---- + +Maintaining the recipes and building the installer artifact +----------------------------------------------------------- + +NOTE: To be investigated, modernized and completed per +https://github.com/networkupstools/nut/issues/1485 + +Files were not touched considerably since 2013 (or earlier?) and would +likely need deeper investigation and update to be useful. Findings so far: + +- Directory `scripts/Windows/DriverInstaller` contains a helper + program (currently named `wdi-simple`) for driver installation + +- Directory `scripts/Windows/Installer` (with this document) contains + the batch file script to call WiX tools (currently geared for WiX v3 + or older) and the XML file which describes the installer actions and + the file/directory structures it would deliver. + * It would be helpful to find how to generate the filesystem structure + (names, GUIDs, what else?) based on the prototype area prepared by + `make install DESTDIR=...` during a NUT build. It does not have to + be part of *every* build (e.g. we can want this separated by driver + types to allow end-users to install just a subset of NUT, similar + to how this happends with multi-package approach on Unix/Linux) but + an automated process which makes maintenance easier would be great: + let a human sort where different filenames are categorized, and let + automation discover that some installed files are not mentioned or + some listed files are not present. + +- Directory `scripts/Windows/Installer/ImageFiles` contains various + resources used by the installer, including apparently `Others/` for + third-party files and `emptyDir` as a target for NUT `make install`? + * This may be moderately compatible with what the Makefile driven + installation does with current codebase -- especially how it pulls + third-party library DLL files into the prototype install area. + +- The `scripts/Windows/wininit.c` program provides a rough equivalent + to POSIX init scripts, to wrap various NUT daemons as a single unit. + Its git history saw several re-architecting decisions, so if there + are any concerns if the current version does "the right thing", we + have some precedent ideas to look at. To a lesser extent, similar + code might have appeared and disappeared in the Windows-branch code + of daemons like `upsd` and `upsmon` before it condensed in this one. + +The batch file and the XML manifest currently list a few libraries from +msys/mingw (as of back when this was coded). Current Makefile recipes +take a more active approach by walking the dynamic dependencies of the +built NUT binaries to copy those from the build environment. + +The batch file takes care to pass sample configuration and documentation +files through `unix2dos` -- keep this in mind for new implementations. diff --git a/scripts/Windows/Makefile.am b/scripts/Windows/Makefile.am index 1224cc8a00..c2f8f9b9f5 100644 --- a/scripts/Windows/Makefile.am +++ b/scripts/Windows/Makefile.am @@ -5,7 +5,7 @@ AM_CFLAGS = -I$(top_srcdir)/include ../include/nut_version.h: FORCE (cd ../include/ && $(MAKE) $(AM_MAKEFLAGS) nut_version.h) -EXTRA_DIST = winevent.mc build-mingw-nut.sh README +EXTRA_DIST = winevent.mc build-mingw-nut.sh README.adoc FORCE: diff --git a/scripts/Windows/README b/scripts/Windows/README.adoc similarity index 100% rename from scripts/Windows/README rename to scripts/Windows/README.adoc diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh index b557ace3c6..95c13e70c6 100755 --- a/scripts/Windows/build-mingw-nut.sh +++ b/scripts/Windows/build-mingw-nut.sh @@ -1,4 +1,7 @@ #!/bin/bash + +# NOTE: bash syntax (non-POSIX script) is used below! +# # script to cross compile NUT for Windows from Linux using MinGW-w64 # http://mingw-w64.sourceforge.net/ @@ -10,10 +13,14 @@ SCRIPTDIR="`cd "$SCRIPTDIR" && pwd`" DLLLDD_SOURCED=true . "${SCRIPTDIR}/dllldd.sh" # default to update source then build -WINDIR=$(pwd) -TOP_DIR=$WINDIR/../.. -BUILD_DIR=$WINDIR/nut_build -INSTALL_DIR=$WINDIR/nut_install + +# These paths are somewhat related: +[ -n "${WINDIR-}" ] || WINDIR="$(pwd)" +[ -n "${TOP_DIR-}" ] || TOP_DIR="$WINDIR/../.." + +# These may be located elsewhere: +[ -n "${BUILD_DIR-}" ] || BUILD_DIR="$WINDIR/nut_build" +[ -n "${INSTALL_DIR-}" ] || INSTALL_DIR="$WINDIR/nut_install" # This should match the tarball and directory name, # if a stable version is used: @@ -30,19 +37,19 @@ fi [ -n "$SOURCEMODE" ] || SOURCEMODE="out-of-tree" -rm -rf $BUILD_DIR $INSTALL_DIR +rm -rf "$BUILD_DIR" "$INSTALL_DIR" CONFIGURE_SCRIPT="./configure" case "$SOURCEMODE" in stable) # FIXME # Stable version (download the latest stable archive) VER_OPT_SHORT="`echo "$VER_OPT" | awk -F. '{print $1"."$2}'`" - if [ ! -s nut-$VER_OPT.tar.gz ] ; then - wget https://www.networkupstools.org/source/$VER_OPT_SHORT/nut-$VER_OPT.tar.gz + if [ ! -s "nut-$VER_OPT.tar.gz" ] ; then + wget "https://www.networkupstools.org/source/$VER_OPT_SHORT/nut-$VER_OPT.tar.gz" fi - rm -rf nut-$VER_OPT - tar -xzf nut-$VER_OPT.tar.gz - mv nut-$VER_OPT $BUILD_DIR + rm -rf "nut-$VER_OPT" + tar -xzf "nut-$VER_OPT.tar.gz" + mv "nut-$VER_OPT" "$BUILD_DIR" ;; dist) # In-place version (no download) @@ -52,8 +59,8 @@ dist) make dist SRC_ARCHIVE=$(ls -1 nut-?.?.?*.tar.gz | sort -n | tail -1) cd scripts/Windows - tar -xzf ../../$SRC_ARCHIVE - mv nut-?.?.?* $BUILD_DIR + tar -xzf "../../$SRC_ARCHIVE" + mv nut-?.?.?* "$BUILD_DIR" ;; out-of-tree) CONFIGURE_SCRIPT="../../../configure" @@ -65,11 +72,11 @@ out-of-tree) make distclean fi cd scripts/Windows - mkdir -p $BUILD_DIR + mkdir -p "$BUILD_DIR" ;; esac -cd $BUILD_DIR || exit +cd "$BUILD_DIR" || exit if [ -z "$INSTALL_WIN_BUNDLE" ]; then echo "NOTE: You might want to export INSTALL_WIN_BUNDLE=true to use main NUT Makefile" @@ -111,7 +118,7 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ # location is passed to `make install` as DESTDIR below. $CONFIGURE_SCRIPT $HOST_FLAG $BUILD_FLAG --prefix=/ \ $KEEP_NUT_REPORT_FEATURE_FLAG \ - PKG_CONFIG_PATH=${ARCH_PREFIX}/lib/pkgconfig \ + PKG_CONFIG_PATH="${ARCH_PREFIX}/lib/pkgconfig" \ --without-pkg-config --with-all=auto \ --without-systemdsystemunitdir \ --with-pynut=app \ @@ -144,24 +151,29 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$ # (maybe even do "cp -pf" if some system dislikes "ln"); also # on a modern Windows one could go to their installed "sbin" to # mklink .\libupsclient-3.dll ..\bin\libupsclient-3.dll - (cd $INSTALL_DIR/bin && ln libupsclient*.dll ../sbin/) - (cd $INSTALL_DIR/bin && ln libupsclient*.dll ../cgi-bin/) || true + (cd "$INSTALL_DIR/bin" && ln libupsclient*.dll ../sbin/) + (cd "$INSTALL_DIR/cgi-bin" && ln ../bin/libupsclient*.dll ./) \ + || echo "NOTE: FAILED to process OPTIONAL cgi-bin directory; was NUT CGI enabled?" >&2 + + echo "NOTE: Adding third-party dependency libraries for each installed program" >&2 + echo " Do not worry about lack of libnut* and libups* in system locations" >&2 # Cover dependencies for nut-scanner (not pre-linked) # Note: lib*snmp*.dll not listed below, it is # statically linked into binaries that use it - (cd $INSTALL_DIR/bin && cp -pf ${ARCH_PREFIX}/bin/{libgnurx,libusb,libltdl}*.dll .) || true - (cd $INSTALL_DIR/bin && cp -pf ${ARCH_PREFIX}/lib/libwinpthread*.dll .) || true + (cd "$INSTALL_DIR/bin" && cp -pf "${ARCH_PREFIX}/bin"/{libgnurx,libusb,libltdl}*.dll .) || true + (cd "$INSTALL_DIR/bin" && cp -pf "${ARCH_PREFIX}/lib"/libwinpthread*.dll .) || true # Steam-roll over all executables/libs we have here and copy # over resolved dependencies from the cross-build environment: - (cd $INSTALL_DIR && { dllldddir . | while read D ; do cp -pf "$D" ./bin/ ; done ; } ) || true + (cd "$INSTALL_DIR" && { dllldddir . | while read D ; do cp -pf "$D" ./bin/ ; done ; } ) || true # Hardlink libraries for sbin (alternative: all bins in one dir): - (cd $INSTALL_DIR/sbin && { DESTDIR="$INSTALL_DIR" dllldddir . | while read D ; do ln -f ../bin/"`basename "$D"`" ./ ; done ; } ) || true + (cd "$INSTALL_DIR/sbin" && { DESTDIR="$INSTALL_DIR" dllldddir . | while read D ; do ln -f ../bin/"`basename "$D"`" ./ ; done ; } ) || true # Hardlink libraries for cgi-bin if present: - (cd $INSTALL_DIR/cgi-bin && { DESTDIR="$INSTALL_DIR" dllldddir . | while read D ; do ln -f ../bin/"`basename "$D"`" ./ ; done ; } ) || true + (cd "$INSTALL_DIR/cgi-bin" && { DESTDIR="$INSTALL_DIR" dllldddir . | while read D ; do ln -f ../bin/"`basename "$D"`" ./ ; done ; } ) \ + || echo "NOTE: FAILED to process OPTIONAL cgi-bin directory; was NUT CGI enabled?" >&2 fi echo "$0: install phase complete ($?)" >&2 diff --git a/scripts/Windows/build-mingw-prereqs.sh b/scripts/Windows/build-mingw-prereqs.sh index 6f6fa4cb77..90e0a9a8d5 100755 --- a/scripts/Windows/build-mingw-prereqs.sh +++ b/scripts/Windows/build-mingw-prereqs.sh @@ -1,9 +1,9 @@ #!/bin/sh -# Copyright (C) 2022 by Jim Klimov +# Copyright (C) 2022-2023 by Jim Klimov # Licensed same as NUT # -# Helper automating the nuances from NUT::scripts/Windows/README +# Helper automating the nuances from NUT::scripts/Windows/README.adoc # to provide prerequisites needed in semi-native or cross-builds. # # NOTE: Currently constrained to providing net-snmp under MSYS2.