Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update a few NUT for Windows documents and scripts #2141

Merged
merged 7 commits into from
Oct 31, 2023
6 changes: 3 additions & 3 deletions INSTALL.nut.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.


Expand Down
3 changes: 2 additions & 1 deletion NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions ci_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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*)
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions docs/config-prereqs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
------------------
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions scripts/Windows/Installer/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NUT-Installer.msi
NUT-Installer.wixobj
NUT-Installer.wixpdb
NUT-Installer.xml
log.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Language="1033" Id="878DBBDE-8551-4151-811A-686A7E4BD66B" Name="NUT - Network UPS Tools" Manufacturer="Eaton" Version="2.6.5.6" UpgradeCode="CAB45634-9010-4B36-A9BB-4D4F976F96FA">
<Package Keywords="Installer,MSI,Database" Description="NUT" Comments="Contact: Your local administrator" Manufacturer="Eaton Corporation" InstallerVersion="100" Languages="1033" Compressed="yes" SummaryCodepage="1252" InstallScope="perMachine" />
<Product Language="1033" Id="878DBBDE-8551-4151-811A-686A7E4BD66B" Name="NUT - Network UPS Tools" Manufacturer="The Network UPS Tools (NUT) project" Version="@PACKAGE_VERSION@" UpgradeCode="CAB45634-9010-4B36-A9BB-4D4F976F96FA">
<Package Keywords="Installer,MSI,Database" Description="NUT" Comments="Contact: Your local administrator" Manufacturer="The Network UPS Tools (NUT) project" InstallerVersion="100" Languages="1033" Compressed="yes" SummaryCodepage="1252" InstallScope="perMachine" />
<UI>
<Property Id="ErrorDialog"><![CDATA[ErrorDlg]]></Property>
<Property Id="DefaultUIFont"><![CDATA[DlgFont8]]></Property>
Expand Down
130 changes: 130 additions & 0 deletions scripts/Windows/Installer/README.adoc
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion scripts/Windows/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
File renamed without changes.
56 changes: 34 additions & 22 deletions scripts/Windows/build-mingw-nut.sh
Original file line number Diff line number Diff line change
@@ -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/

Expand All @@ -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:
Expand All @@ -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)
Expand All @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions scripts/Windows/build-mingw-prereqs.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/bin/sh

# Copyright (C) 2022 by Jim Klimov <jimklimov+nut@gmail.com>
# Copyright (C) 2022-2023 by Jim Klimov <jimklimov+nut@gmail.com>
# 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.
Expand Down