diff --git a/Makefile b/Makefile
index e99d09c5ee..7c1e6d9e9c 100644
--- a/Makefile
+++ b/Makefile
@@ -310,62 +310,6 @@ endif
 		$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
 	done
 
-ifdef CONFIG_WIN32
-
-INSTALLER = qemu-setup-$(VERSION)$(EXESUF)
-
-nsisflags = -V2 -NOCD
-
-ifneq ($(wildcard $(SRC_PATH)/dll),)
-ifeq ($(ARCH),x86_64)
-# 64 bit executables
-DLL_PATH = $(SRC_PATH)/dll/w64
-nsisflags += -DW64
-else
-# 32 bit executables
-DLL_PATH = $(SRC_PATH)/dll/w32
-endif
-endif
-
-.PHONY: installer
-installer: $(INSTALLER)
-
-INSTDIR=/tmp/qemu-nsis
-
-$(INSTALLER): $(SRC_PATH)/qemu.nsi
-	$(MAKE) install prefix=${INSTDIR}
-ifdef SIGNCODE
-	(cd ${INSTDIR}; \
-         for i in *.exe; do \
-           $(SIGNCODE) $${i}; \
-         done \
-        )
-endif # SIGNCODE
-	(cd ${INSTDIR}; \
-         for i in qemu-system-*.exe; do \
-           arch=$${i%.exe}; \
-           arch=$${arch#qemu-system-}; \
-           echo Section \"$$arch\" Section_$$arch; \
-           echo SetOutPath \"\$$INSTDIR\"; \
-           echo File \"\$${BINDIR}\\$$i\"; \
-           echo SectionEnd; \
-         done \
-        ) >${INSTDIR}/system-emulations.nsh
-	makensis $(nsisflags) \
-                $(if $(BUILD_DOCS),-DCONFIG_DOCUMENTATION="y") \
-                $(if $(CONFIG_GTK),-DCONFIG_GTK="y") \
-                -DBINDIR="${INSTDIR}" \
-                $(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \
-                -DSRCDIR="$(SRC_PATH)" \
-                -DOUTFILE="$(INSTALLER)" \
-                -DDISPLAYVERSION="$(VERSION)" \
-                $(SRC_PATH)/qemu.nsi
-	rm -r ${INSTDIR}
-ifdef SIGNCODE
-	$(SIGNCODE) $(INSTALLER)
-endif # SIGNCODE
-endif # CONFIG_WIN
-
 # Add a dependency on the generated files, so that they are always
 # rebuilt before other object files
 ifneq ($(wildcard config-host.mak),)
@@ -405,7 +349,6 @@ endif
 	@echo  ''
 ifdef CONFIG_WIN32
 	@echo  'Windows targets:'
-	@echo  '  installer       - Build NSIS-based installer for QEMU'
 ifdef QEMU_GA_MSI_ENABLED
 	@echo  '  msi             - Build MSI-based installer for qemu-ga'
 endif
diff --git a/meson.build b/meson.build
index caf99f5082..6d1fc2fb19 100644
--- a/meson.build
+++ b/meson.build
@@ -1064,3 +1064,26 @@ if pod2man.found() and build_docs
                                   '--release=" "', '@INPUT@'])
   endforeach
 endif
+
+if host_machine.system() == 'windows'
+  nsis_cmd = [
+    find_program('scripts/nsis.sh'),
+    '@OUTPUT@',
+    get_option('prefix'),
+    meson.current_source_dir(),
+    host_machine.cpu_family(),
+    '-DDISPLAYVERSION=@0@'.format(config_host['VERSION']),
+  ]
+  if build_docs
+    nsis_cmd += '-DCONFIG_DOCUMENTATION=y'
+  endif
+  if 'CONFIG_GTK' in config_host
+    nsis_cmd += '-DCONFIG_GTK=y'
+  endif
+
+  custom_target('nsis',
+                output: 'qemu-setup-' + config_host['VERSION'] + '.exe',
+                input: files('qemu.nsi'),
+                build_always_stale: true,
+                command: nsis_cmd + ['@INPUT@'])
+endif
diff --git a/scripts/nsis.sh b/scripts/nsis.sh
new file mode 100755
index 0000000000..ad23708724
--- /dev/null
+++ b/scripts/nsis.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+OUTFILE="$1"
+shift
+PREFIX="$1"
+shift
+SRCDIR="$1"
+shift
+CPU="$1"
+shift
+
+DESTDIR=$(mktemp -d)
+trap "rm -rf $DESTDIR" EXIT
+make DESTDIR="$DESTDIR" install
+
+signcode() {
+    if [ -z "$SIGNCODE" ]; then
+        return
+    fi
+    "$SIGNCODE" "$@"
+}
+
+shopt -s nullglob
+
+(
+    cd "$DESTDIR$PREFIX"
+    for i in qemu-system-*.exe; do
+        arch=${i%.exe}
+        arch=${arch#qemu-system-}
+        echo Section \"$arch\" Section_$arch
+        echo SetOutPath \"\$INSTDIR\"
+        echo File \"\${BINDIR}\\$i\"
+        echo SectionEnd
+    done
+) > "$DESTDIR$PREFIX/system-emulations.nsh"
+
+(
+    cd "$DESTDIR$PREFIX"
+    for i in *.exe; do
+        signcode "$i"
+    done
+)
+
+if [ "$CPU" = "x86_64" ]; then
+    CPUARG="-DW64"
+    DLLDIR="w64"
+else
+    DLLDIR="w32"
+fi
+
+if [ -d "$SRCDIR/dll" ]; then
+   DLLARG="-DDLLDIR=$SRCDIR/dll/$DLLDIR"
+fi
+
+makensis -V2 -NOCD -DSRCDIR="$SRCDIR" -DBINDIR="$DESTDIR$PREFIX" \
+         $CPUARG $DLLARG -DOUTFILE="$OUTFILE" "$@"
+
+signcode "$OUTFILE"
