diff --git a/.github/workflows/windows-msys2.yml b/.github/workflows/windows-msys2.yml new file mode 100644 index 00000000..07556d5f --- /dev/null +++ b/.github/workflows/windows-msys2.yml @@ -0,0 +1,109 @@ +name: SSR for Windows, using MSYS2 +on: [push, pull_request] +jobs: + build-win: + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + env: + MSYS: winsymlinks:native + steps: + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: UCRT64 + install: >- + git + pacboy: >- + asio:p + autotools:p + cargo-c:p + cmake:p + fftw:p + fmt:p + jack2:p + libsndfile:p + libmysofa:p + libxml2:p + mesa:p + nsis:p + qt5-base:p + qt5-tools:p + rust:p + vrpn:p + yarn:p + - name: checkout asdf-rust + uses: actions/checkout@v3 + with: + repository: AudioSceneDescriptionFormat/asdf-rust + ref: '1.0.0' + path: asdf + submodules: true + - name: Install ASDF + working-directory: asdf + run: | + cargo cinstall --verbose --prefix=/ucrt64 + - name: checkout websocketpp + uses: actions/checkout@v3 + with: + repository: zaphoyd/websocketpp + path: websocketpp + - name: Get SSR source code + uses: actions/checkout@v3 + with: + submodules: true + # This is required to be able to fetch tags, + # see https://github.com/actions/checkout/issues/290: + fetch-depth: 0 + path: ssr + - name: autogen + working-directory: ssr + run: | + ./autogen.sh + - name: fetch Git tags + working-directory: ssr + run: | + # Fetch tags for obtaining the version number, + # see https://github.com/actions/checkout/issues/290: + git fetch --tags --force + - name: configure + working-directory: ssr + run: | + CONFIGURE_OPTIONS=( + --enable-browser-gui + --enable-dynamic-asdf + --enable-fudi-interface + --enable-gui + --enable-ip-interface + #--enable-polhemus + #--enable-razor + --enable-sofa + #--enable-vrpn + --enable-websocket-interface + --enable-windows-installer + --disable-ecasound + --disable-intersense + CPPFLAGS="-I/ucrt64/include -I`pwd`/../websocketpp -D_WEBSOCKETPP_CPP11_THREAD_" + LDFLAGS=-L/ucrt64/lib + ) + ./configure --disable-dependency-tracking "${CONFIGURE_OPTIONS[@]}" + - name: upload config.log + if: failure() + uses: actions/upload-artifact@v3 + with: + name: config.log + path: ssr/config.log + - name: make + working-directory: ssr + run: | + make + - name: make nsis + working-directory: ssr + run: | + make nsis + - name: upload installer + uses: actions/upload-artifact@v3 + with: + name: ssr-installer + path: "ssr/windows-installer/SoundScape Renderer * Installer.exe" diff --git a/Makefile.am b/Makefile.am index b427f558..fc2a4054 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,6 +123,15 @@ doc: .PHONY: doc +if ENABLE_WINDOWS_INSTALLER +nsis: install-strip + $(MAKE) -C data/nsis $@ +else +nsis: + @echo "You have to run './configure --enable-windows-installer' first!"; false +endif +.PHONY: nsis + .NOTPARALLEL: install # remove pkgdatadir and docdir (if empty) diff --git a/configure.ac b/configure.ac index 346fcba1..b1ed6f1e 100644 --- a/configure.ac +++ b/configure.ac @@ -51,7 +51,7 @@ AC_CANONICAL_TARGET dnl Compute the canonical host-system type variable, 'host', and its three dnl individual parts 'host_cpu', 'host_vendor', and 'host_os'. -dnl AC_CANONICAL_HOST +AC_CANONICAL_HOST dnl Runs many macros required for proper operation of the generated Makefiles. dnl see http://sources.redhat.com/automake/automake.html#Options for options @@ -123,6 +123,11 @@ dnl AC_DEFINE writes values in config.h dnl AC_DEFINE_UNQUOTED performs additional shell expansions, e.g. substitution dnl of variable with value. + +AS_IF([test "$host_os" = "mingw32"], [ + CXXFLAGS="$CXXFLAGS -mwin32" +]) + ENABLE_AUTO([all], [all renderers (use --enable-xyz to re-enable certain renderers)], [ @@ -496,6 +501,9 @@ ENABLE_FORCED([gui], [graphical user interface (using Qt)], AC_CHECK_HEADER([OpenGL/glu.h], , [have_gui=no]) LIBS="$LIBS -framework OpenGL" ]) + AS_IF([test "$host_os" = "mingw32"], [ + LIBS="$LIBS -lglu32 -lopengl32" + ]) AC_SEARCH_LIBS([gluNewQuadric], [GLU], , [have_gui=no]) # on some systems this is needed, on the others it doesn't hurt: AC_SEARCH_LIBS([glSelectBuffer], [GL], , [have_gui=no]) @@ -562,6 +570,13 @@ ENABLE_AUTO([fudi-interface], [FUDI interface (needs Asio and {fmt})], [have_fudi_interface=no]) ]) +AS_IF([test "$host_os" = "mingw32"], [ + AS_IF([test x$have_ip_interface = xyes -o x$have_websocket_interface = xyes -o x$have_fudi_interface = xyes], +[ + LIBS="$LIBS -lws2_32 -lwsock32" + ]) +]) + ENABLE_FORCED([ecasound], [Ecasound soundfile playback/recording], [ dnl Checking for libecasoundc. It does not provide pkg-config and installs @@ -723,6 +738,24 @@ ENABLE_AUTO([isatty], [support for isatty()], AC_SEARCH_LIBS([isatty], , , [have_isatty=no]) ]) +dnl trying to mimic the default setting +pkgdatadir='${datadir}/${PACKAGE}' + +ENABLE_EXPLICIT([windows-installer], [creation of an installer for Windows], +[ + AC_CHECK_PROG([have_nsis], [nsis], [yes], [no]) + AC_CHECK_PROG([have_windeployqt], [windeployqt], [yes], [no]) + AS_IF([test x$enable_windows_installer = xyes -o x$enable_windows_installer = x], + [WINDOWS_INSTALLER="SoundScape Renderer $PACKAGE_VERSION Installer"], + [WINDOWS_INSTALLER=$enable_windows_installer]) + + dnl WARNING: any user-specified --prefix, --bindir, ... is overwritten! + dnl however, it can still be specified at make time (although kinda useless)! + prefix=$(pwd)/windows-installer + docdir=\${prefix}/Documentation + pkgdatadir=\${prefix}/data +]) + ENABLE_AUTO([browser-gui], [creation of HTML/JavaScript files for browser GUI], [ AC_ARG_VAR([YARN], [Yarn package manager command]) @@ -744,6 +777,9 @@ ENABLE_AUTO([browser-gui], [creation of HTML/JavaScript files for browser GUI], ]) ]) +AC_SUBST(WINDOWS_INSTALLER) +AC_SUBST(pkgdatadir) + AC_SUBST(OPT_FLAGS) AC_SUBST(PKG_FLAGS) AC_SUBST(WARNING_FLAGS) @@ -752,6 +788,7 @@ AC_SUBST(DEBUGGING_FLAGS) dnl List of output files generated by AC_OUTPUT from their respective *.in files AC_CONFIG_FILES([Makefile src/Makefile man/Makefile browser-gui/Makefile]) AC_CONFIG_FILES([tests/Makefile data/Makefile]) +AC_CONFIG_FILES([data/nsis/Makefile data/nsis/installer-script.nsi]) dnl AC_OUTPUT should be the last command (except maybe some status messages) dnl It generates and runs config.status, which in turn creates the Makefiles and @@ -811,7 +848,13 @@ echo "| Network: legacy/WebSocket/FUDI ......... : $have_ip_interface/$have_webs echo "| Qt GUI/Browser GUI ..................... : $have_gui/$have_browser_gui" echo "|" echo "| Enable debugging/optimization .......... : $have_debugging/$have_optimization" +AS_IF([test x$have_windows_installer = xyes], +[ +echo "| Installer for Windows .................. : $WINDOWS_INSTALLER" +], +[ echo "| Install prefix ......................... : $prefix" +]) AS_IF([test x$have_ecasound = xyes -a x$have_ecasound_program != xyes], [ @@ -825,7 +868,25 @@ AS_IF([test x$have_manpages != xyes], echo "|> WARNING: help2man was not found!" echo "|> Disabling building of manpages" ]) +AS_IF([test x$have_windows_installer = xyes -a x$have_nsis != xyes], +[ + echo "|" + echo "|> WARNING: NSIS was not found!" + echo "|> It is needed for creating the Windows installer." +]) +AS_IF([test x$have_windows_installer = xyes -a x$have_windeployqt != xyes], +[ + echo "|" + echo "|> WARNING: windeployqt was not found!" + echo "|> It is needed for collecting dependencies for the Windows installer." +]) echo +AS_IF([test x$have_windows_installer = xyes], +[ +echo 'If everything looks OK, continue with "make" and "make nsis".' +], +[ echo 'If everything looks OK, continue with "make" and "make install".' +]) echo diff --git a/data/Makefile.am b/data/Makefile.am index 08fa3e31..ae4f7a4d 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -5,9 +5,20 @@ ## comments starting with a single # are copied to Makefile.in (and afterwards ## to Makefile), comments with ## are dropped. -dist_bin_SCRIPTS = ssr +if ENABLE_WINDOWS_INSTALLER +SUBDIRS = nsis +extrasdir = $(prefix)/Extras +scenesdir = $(prefix)/Scenes +## these are always distributed, but only installed if ENABLE_WINDOWS_INSTALLER +dist_scenes_DATA = \ + scenes/asdf2html.xsl \ + scenes/live_input.asd +else extrasdir = $(pkgdatadir) +## this compatibility script is not needed for the Windows installer +dist_bin_SCRIPTS = ssr +endif ## stuff that will end up in $prefix/share/ssr/ nobase_dist_pkgdata_DATA = \ @@ -33,7 +44,7 @@ nobase_dist_pkgdata_DATA = \ ## the whole directory is distributed, including browser GUI files EXTRA_DIST = websocket_resources -## stuff that will end up in $prefix/share/ssr/ +## stuff that will end up in $extrasdir nobase_dist_extras_DATA = \ reproduction_setups/2.0.asd \ reproduction_setups/2.1.asd \ @@ -85,17 +96,20 @@ dist_noinst_SCRIPTS = local_ssr.sh ##dist-hook: ## ... +# https://stackoverflow.com/q/63018330#comment111445661_63020485 +HASH := \# + # compute relative path between $(pkgdatadir) and $(extrasdir) REL_LINK_DIR = $(shell \ target="${extrasdir}"; \ common_part="${pkgdatadir}"; \ if test "x$$target" = "x$$common_part"; then echo .; exit; fi; \ back= ; \ - while test "x$${target\#$$common_part}" = "x$$target"; do \ + while test "x$${target$(HASH)$$common_part}" = "x$$target"; do \ common_part="`dirname "$$common_part"`"; \ back="../$$back" ; \ done; \ - echo "$${back}$${target\#$$common_part/}") + echo "$${back}$${target$(HASH)$$common_part/}") # create symbolic links in the install directory (for default files) and # before that, remove old symbolic links diff --git a/data/nsis/Makefile.am b/data/nsis/Makefile.am new file mode 100644 index 00000000..81128a31 --- /dev/null +++ b/data/nsis/Makefile.am @@ -0,0 +1,31 @@ +## This file will be processed by automake (which is called by autogen.sh) to +## generate Makefile.in, which in turn will be processed by configure to +## generate Makefile. + +## comments starting with a single # are copied to Makefile.in (and afterwards +## to Makefile), comments with ## are dropped. + +## This file is only taken into account if --enable-windows-installer was chosen! +if ENABLE_WINDOWS_INSTALLER + +# this is done after installing the executables +install-exec-hook: +## the line starting with "ldd" was adapted from +## https://github.com/msys2/MINGW-packages/issues/5204#issuecomment-1013818547 + for exec in $(SSR_executables); do \ + windeployqt --no-compiler-runtime $(DESTDIR)$(bindir)/$$exec ; \ + ldd $(DESTDIR)$(bindir)/$$exec | grep -iv system32 | cut -f2 -d\> | cut -f1 -d\( | while read a; do ! [ -e "$(DESTDIR)$(bindir)/`basename $$a`" ] && cp -v "$$a" $(DESTDIR)$(bindir)/ || true; done \ + done +## those are copied by windeployqt, but they are not needed: + $(RM) -r $(DESTDIR)$(bindir)/styles + $(RM) -r $(DESTDIR)$(bindir)/imageformats +## this is assumed to be available on the target system: + $(RM) -r $(DESTDIR)$(bindir)/libjack*.dll + +# create Windows installer +nsis: + cd $(DESTDIR)$(prefix) && MakeNSIS.exe -NOCD $(abs_builddir)/installer-script.nsi + +.PHONY: nsis + +endif diff --git a/data/nsis/installer-script.nsi.in b/data/nsis/installer-script.nsi.in new file mode 100644 index 00000000..a5f03cb8 --- /dev/null +++ b/data/nsis/installer-script.nsi.in @@ -0,0 +1,57 @@ +# https://nsis.sourceforge.io/Docs/ + +!define APPNAME "SoundScape Renderer @PACKAGE_VERSION@" + +Name "${APPNAME}" + +OutFile "@WINDOWS_INSTALLER@.exe" + +InstallDir "$PROGRAMFILES64\${APPNAME}" + +SetCompressor lzma + +#Page license +#Page components +Page directory +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles + +Section "Everything" + SetOutPath $INSTDIR + + File /r ".\bin" + File /r ".\data" + + WriteUninstaller "$INSTDIR\uninstall.exe" + + # Set the working directory of the following Start Menu shortcuts: + SetOutPath "$INSTDIR\bin" + + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-binaural.lnk" "cmd" "/k ssr-binaural.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-brs.lnk" "cmd" "/k ssr-brs.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-wfs.lnk" "cmd" "/k ssr-wfs.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-vbap.lnk" "cmd" "/k ssr-vbap.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-aap.lnk" "cmd" "/k ssr-aap.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-dca.lnk" "cmd" "/k ssr-dca.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\ssr-generic.lnk" "cmd" "/k ssr-generic.exe" + CreateShortcut "$SMPROGRAMS\${APPNAME}\uninstall.lnk" "$INSTDIR\uninstall.exe" + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ + "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" \ + "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" +SectionEnd + +Section "Uninstall" + RMDir /r "$INSTDIR\bin" + RMDir /r "$INSTDIR\data" + Delete "$INSTDIR\uninstall.exe" + RMDir $INSTDIR + + RMDir /r "$SMPROGRAMS\${APPNAME}" + + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" +SectionEnd diff --git a/src/Makefile.am b/src/Makefile.am index bb5d41c5..dbfe92a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,11 @@ AM_CPPFLAGS += -I$(srcdir)/../apf AM_CPPFLAGS += -I$(srcdir)/../gml/include AM_CPPFLAGS += -I$(srcdir)/../rapidjson/include +if ENABLE_WINDOWS_INSTALLER +AM_CPPFLAGS += -DSSR_DATA_DIR=\"../data\" +else AM_CPPFLAGS += -DSSR_DATA_DIR="\"$(pkgdatadir)\"" +endif ## this is somehow needed for Solaris (or not?) AM_CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS