diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ae463a5dd9414deaedf0d86e908bfc607746caf2..a7fd89bb27adac12abffb14aa7a551d0de381923 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -66,6 +66,7 @@ pkg_source:
 pkg_windows:
   stage: pkg
   script:
+    - meson rewrite kwargs set project / version "$VERSION"
     - mkdir -p windows/deps/tarballs && cp /usr/lib/dynare-runner/matlab64-* windows/deps/tarballs/
     - make -C windows
     - rm windows/deps/tarballs/matlab64-* # No need to cache these files
diff --git a/meson.build b/meson.build
index d1e7f485295187e786aa0f8b79cc64cdad07263a..041805b366ba42f0e27910f89a7f1a904782406a 100644
--- a/meson.build
+++ b/meson.build
@@ -8,7 +8,6 @@
 # - add the possibility to customize the integration test names (with a new optional 'name' keyword in the dictionaries)
 # - Add an option to skip the removal of the temporary test directories, for debugging purposes
 # - See what to do with xvfb-run (see #1892). Maybe try to detect it from meson.build, and pass it optionally to the test driver script
-# - See whether the tests can be automatically disabled if the MATLAB/Octave executable is not found (using the disabler option of find_program?)
 # - Add priorities to have some tests run before the others (e.g. obs_trend_and_prefilter stuff)
 # - Decide whether we want to keep MALLOC_PERTURB_ for the testsuite; it can have a significant performance impact; see the doc of test() for how to do so
 
@@ -79,7 +78,7 @@ if get_option('build_for') == 'matlab'
   endif
 
   matlab_version_hex = run_command('scripts/get-matlab-version', '--hex', matlab_path, check : true).stdout().strip()
-  matlab_exe = find_program(matlab_path / 'bin' / 'matlab', required : not meson.is_cross_build())
+  matlab_exe = find_program(matlab_path / 'bin' / 'matlab', required : not meson.is_cross_build(), disabler : true)
 
   if host_machine.system() == 'linux' and host_machine.cpu_family() == 'x86_64'
     mexext = 'mexa64'
@@ -134,7 +133,7 @@ if get_option('build_for') == 'matlab'
 
   slicot_dep = declare_dependency(dependencies : [ fortran_compiler.find_library('slicot64_pic'), blas_dep, lapack_dep ])
 else # Octave build
-  octave_exe = find_program('octave', required : not meson.is_cross_build())
+  octave_exe = find_program('octave', required : not meson.is_cross_build(), disabler : true)
   mkoctfile_exe = find_program('mkoctfile')
   octave_minimal_version = '6.2.0'
   octave_version = run_command(mkoctfile_exe, '-v', check : true).stdout().replace('mkoctfile, version ', '')
diff --git a/scripts/windows-cross-matlab.ini b/scripts/windows-cross-matlab.ini
index 0ada1e0abcfcb5b10e6cf22f3c14af4593f87ecb..673c55298eedd5fee269739b6e5aded54107c9d6 100644
--- a/scripts/windows-cross-matlab.ini
+++ b/scripts/windows-cross-matlab.ini
@@ -1,9 +1,8 @@
 # Meson cross file for targeting Windows from Linux
-# This is the MATLAB-specific cross file, to be include before the common cross file
+# This is the MATLAB-specific cross file, to be included before the common cross file
 
 [project options]
 build_for='matlab'
-#matlab_path='/tmp/deps/matlab64/R2018a'
 
 [constants]
-#slicot_path='/tmp/deps/lib64/Slicot/without-underscore/lib/'
+slicot_path='/tmp/windeps/lib64/Slicot/without-underscore/'
diff --git a/scripts/windows-cross-octave.ini b/scripts/windows-cross-octave.ini
index c838bc5ed88422b8da51c5d8a7383ea37eebc5c9..34560ef6fa271876ede996b8129143e16de6234c 100644
--- a/scripts/windows-cross-octave.ini
+++ b/scripts/windows-cross-octave.ini
@@ -1,11 +1,11 @@
 # Meson cross file for targeting Windows from Linux
-# This is the Octave-specific cross file, to be include before the common cross file
+# This is the Octave-specific cross file, to be included before the common cross file
 
 [binaries]
-#mkoctfile='/tmp/deps/mkoctfile64'
+mkoctfile='/tmp/windeps/mkoctfile64'
 
 [project options]
 build_for='octave'
 
 [constants]
-#slicot_path='/tmp/deps/lib64/Slicot/with-underscore/lib/'
+slicot_path='/tmp/windeps/lib64/Slicot/with-underscore/'
diff --git a/scripts/windows-cross.ini b/scripts/windows-cross.ini
index c5ca2c77c77233796c9894f9a4671a7da31b68bb..69b127e076419a64f981b9bcb59121b9d65b8b1d 100644
--- a/scripts/windows-cross.ini
+++ b/scripts/windows-cross.ini
@@ -40,6 +40,6 @@ fortran_args = arch_flags + [ '-B', slicot_path ]
 c_args = arch_flags
 
 [properties]
-#sys_root='/tmp/deps/sys_root'
-#pkg_config_libdir = '/tmp/deps/sys_root/mingw64/lib/pkgconfig'
-#boost_root = '/tmp/deps/sys_root/mingw64'
+sys_root='/tmp/windeps/lib64-msys2'
+pkg_config_libdir = '/tmp/windeps/lib64-msys2/mingw64/lib/pkgconfig'
+boost_root = '/tmp/windeps/lib64-msys2/mingw64'
diff --git a/windows/build.sh b/windows/build.sh
index 54224e67e5c02387a7dbe6082ca9075e2790c3a5..d7c367984efcc6122acc6fa521a01ec50fca000b 100755
--- a/windows/build.sh
+++ b/windows/build.sh
@@ -28,145 +28,71 @@ set -ex
 # Set root directory
 ROOT_DIRECTORY=$(dirname "$(readlink -f "$0")")
 
+# Check that build directories do not already exist
+[[ -d /tmp/windeps ]] && { echo "Please remove the /tmp/windeps directory" 2>&1; exit 1; }
+[[ -d "$ROOT_DIRECTORY"/../build-win-matlab ]] && { echo "Please remove the build-win-matlab directory" 2>&1; exit 1; }
+[[ -d "$ROOT_DIRECTORY"/../build-win-old-matlab ]] && { echo "Please remove the build-win-old-matlab directory" 2>&1; exit 1; }
+[[ -d "$ROOT_DIRECTORY"/../build-win-octave ]] && { echo "Please remove the build-win-octave directory" 2>&1; exit 1; }
+
 # Create TMP folder and make sure it is deleted upon exit
 TMP_DIRECTORY=$(mktemp -d)
-
 cleanup()
 {
     [[ -z $TMP_DIRECTORY ]] || rm -rf -- "$TMP_DIRECTORY"
 }
 trap cleanup EXIT
 
-# Set the number of threads
-NTHREADS=$(nproc)
-
-# Set Dynare version, if not already set by Gitlab CI
-if [[ -z $VERSION ]]; then
-    VERSION=$(grep '^AC_INIT(' ../configure.ac | sed 's/AC_INIT(\[dynare\], \[\(.*\)\])/\1/')
-    if [[ -d ../.git/ ]]; then
-        VERSION=$VERSION-$(git rev-parse --short HEAD)
-    fi
-fi
-
-BASENAME=dynare-$VERSION
-
-# Set directories for dependencies
-LIB64="$ROOT_DIRECTORY"/deps/lib64
-LIB64_MSYS2="$ROOT_DIRECTORY"/deps/lib64-msys2
-
-# Set compilation flags
-# For the architectural baseline, we follow MSYS2:
-# https://www.msys2.org/news/#2022-10-18-new-minimum-hardware-requirements-cpus-from-20067
-arch_flags="-march=nocona -msahf -mtune=generic"
-export CFLAGS="-O3 $arch_flags"
-# MSYS2 libraries are now built with -fstack-protector-strong, see:
-# https://www.msys2.org/news/#2022-10-23-mingw-packages-now-built-with-d_fortify_source2-and-fstack-protector-strong
-# As of 2023-01-03, when linking against HDF5 (and possibly other libraries),
-# it is necessary to compile our own code with -fstack-protector to avoid undefined symbols
-# at link time.
-# Note that specifying -fstack-protector-strong or -fstack-protector-all will lead
-# to a dependency on libssp-0.dll (at least when using the MinGW compilers from Debian),
-# and there seems to be no easy way of linking it statically.
-# Also note that adding this flag is not necessary when building from MSYS2 shell.
-# Maybe revisit this once our runners are upgraded to Debian “Bookworm” 12.
-export CXXFLAGS="-O3 $arch_flags -fstack-protector"
-export FCFLAGS="-O3 $arch_flags"
+# Create a directory for dependencies under /tmp.
+# Meson does not like when dependencies are under the source tree.
+# We use a fixed name to avoid having to regenerate the cross files.
+mkdir /tmp/windeps
+ln -s "$ROOT_DIRECTORY"/deps/lib64 /tmp/windeps/
+ln -s "$ROOT_DIRECTORY"/deps/lib64-msys2 /tmp/windeps/
+ln -s "$ROOT_DIRECTORY"/deps/matlab64 /tmp/windeps/
+ln -s "$ROOT_DIRECTORY"/deps/mkoctfile64 /tmp/windeps/
 
 # Go to source root directory
 cd ..
 
-# Autoreconf if needed
-[[ -f configure ]] || autoreconf -si
-
-## Compile preprocessor (64-bit) and documentation
-./configure --host=x86_64-w64-mingw32 \
-	    --with-boost="$LIB64_MSYS2" \
-	    --disable-octave \
-	    --disable-matlab \
-	    PACKAGE_VERSION="$VERSION" \
-	    PACKAGE_STRING="dynare $VERSION"
-make -j"$NTHREADS"
-x86_64-w64-mingw32-strip preprocessor/src/dynare-preprocessor.exe
-x86_64-w64-mingw32-strip matlab/preprocessor64/dynare_m.exe
+common_meson_opts=(-Dbuildtype=release --cross-file scripts/windows-cross.ini)
 
-## Define functions for building MEX files
-
-## Note that we do out-of-tree compilation, since we want to do these in
-## parallel
+# Create Windows 64-bit DLL binaries for MATLAB ≥ R2018a
+meson setup --cross-file scripts/windows-cross-matlab.ini -Dmatlab_path=/tmp/windeps/matlab64/R2018a \
+      "${common_meson_opts[@]}" build-win-matlab
+meson compile -v -C build-win-matlab
 
 # Create Windows 64-bit DLL binaries for MATLAB ≥ R2014a and ≤ R2017b
-build_windows_matlab_mex_64_a ()
-{
-    mkdir -p "$TMP_DIRECTORY"/matlab-win64-a/
-    cd "$TMP_DIRECTORY"/matlab-win64-a/
-    "$ROOT_DIRECTORY"/../mex/build/matlab/configure \
-                     --host=x86_64-w64-mingw32 \
-		     --with-gsl="$LIB64_MSYS2" \
-		     --with-matio="$LIB64_MSYS2" \
-		     --with-slicot="$LIB64"/Slicot/without-underscore \
-		     --with-matlab="$ROOT_DIRECTORY"/deps/matlab64/R2014a \
-		     MEXEXT=mexw64 \
-		     PACKAGE_VERSION="$VERSION" \
-		     PACKAGE_STRING="dynare $VERSION"
-    make -j"$NTHREADS" all
-    x86_64-w64-mingw32-strip -- **/*.mexw64
-    mkdir -p "$ROOT_DIRECTORY"/../mex/matlab/win64-8.3-9.3
-    mv -- **/*.mexw64 "$ROOT_DIRECTORY"/../mex/matlab/win64-8.3-9.3
-}
-
-# Create Windows 64-bit DLL binaries for MATLAB ≥ R2018a
-build_windows_matlab_mex_64_b ()
-{
-    mkdir -p "$TMP_DIRECTORY"/matlab-win64-b/
-    cd "$TMP_DIRECTORY"/matlab-win64-b/
-    "$ROOT_DIRECTORY"/../mex/build/matlab/configure \
-                     --host=x86_64-w64-mingw32 \
-		     --with-gsl="$LIB64_MSYS2" \
-		     --with-matio="$LIB64_MSYS2" \
-		     --with-slicot="$LIB64"/Slicot/without-underscore \
-		     --with-matlab="$ROOT_DIRECTORY"/deps/matlab64/R2018a \
-		     MEXEXT=mexw64 \
-		     PACKAGE_VERSION="$VERSION" \
-		     PACKAGE_STRING="dynare $VERSION"
-    make -j"$NTHREADS" all
-    x86_64-w64-mingw32-strip -- **/*.mexw64
-    mkdir -p "$ROOT_DIRECTORY"/../mex/matlab/win64-9.4-9.14
-    mv -- **/*.mexw64 "$ROOT_DIRECTORY"/../mex/matlab/win64-9.4-9.14
-}
+meson setup --cross-file scripts/windows-cross-matlab.ini -Dmatlab_path=/tmp/windeps/matlab64/R2014a \
+      "${common_meson_opts[@]}" build-win-old-matlab
+meson compile -v -C build-win-old-matlab
 
 # Create Windows DLL binaries for Octave/MinGW (64bit)
-build_windows_octave_mex_64 ()
-{
-    mkdir -p "$TMP_DIRECTORY"/octave-64/
-    cd "$TMP_DIRECTORY"/octave-64/
-    "$ROOT_DIRECTORY"/../mex/build/octave/configure \
-                     --host=x86_64-w64-mingw32 \
-                     --with-gsl="$LIB64_MSYS2" \
-                     --with-matio="$LIB64_MSYS2" \
-                     --with-slicot="$LIB64"/Slicot/with-underscore \
-                     MKOCTFILE="$ROOT_DIRECTORY"/deps/mkoctfile64 \
-                     OCTAVE=/bin/true \
-                     PACKAGE_VERSION="$VERSION" \
-                     PACKAGE_STRING="dynare $VERSION"
-    make -j"$NTHREADS" all
-    x86_64-w64-mingw32-strip -- **/*.mex
-    mkdir -p "$ROOT_DIRECTORY"/../mex/octave/win64
-    mv -- **/*.mex "$ROOT_DIRECTORY"/../mex/octave/win64
-}
+meson setup --cross-file scripts/windows-cross-octave.ini \
+      "${common_meson_opts[@]}" build-win-octave
+meson compile -v -C build-win-octave
 
-## Actually build the MEX files
+# If not in CI, build the docs
+if [[ -z $CI ]]; then
+    meson compile -v -C build-win-matlab doc
+    ln -sf build-win-matlab build-doc
+fi
 
-TASKS=(build_windows_matlab_mex_64_a build_windows_matlab_mex_64_b build_windows_octave_mex_64)
-# Reset the number of threads. The mex files for MATLAB/Octave will be built
-# in parallel, so we need to account for the number of tasks and lower the value of NTHREADS.
-NTHREADS=$((NTHREADS/${#TASKS[@]}))
-[[ $NTHREADS -ge 1 ]] || NTHREADS=1 # Ensure that there is at least 1 thread
-# Build all the mex files (parallel).
-# Some variables and functions need to be available in subshells.
-cd "$ROOT_DIRECTORY"
-export TMP_DIRECTORY ROOT_DIRECTORY LIB64 LIB64_MSYS2 VERSION NTHREADS
-export -f "${TASKS[@]}"
-parallel "set -ex;shopt -s globstar;" ::: "${TASKS[@]}"
+# Determine Dynare version if not passed by an environment variable as in the CI
+if [[ -z $VERSION ]]; then
+    cd build-win-matlab
+    VERSION=$(meson introspect --projectinfo | sed -En 's/^.*"version": "([^"]*)".*$/\1/p')
+    cd ..
+fi
+
+# Strip binaries
+x86_64-w64-mingw32-strip build-win-matlab/preprocessor/src/dynare-preprocessor.exe
+x86_64-w64-mingw32-strip -- build-win-matlab/*.mexw64
+x86_64-w64-mingw32-strip -- build-win-old-matlab/*.mexw64
+x86_64-w64-mingw32-strip -- build-win-octave/*.mex
+
+# Add a preprocessor copy for backward compatibility
+mkdir -p matlab/preprocessor64/
+cp build-win-matlab/preprocessor/src/dynare-preprocessor.exe matlab/preprocessor64/dynare_m.exe
 
 # Add supported_octave_version.m (see matlab/dynare.m)
 while read -r line
@@ -178,28 +104,23 @@ do
 done < "$ROOT_DIRECTORY"/deps/versions.mk
 [[ -n $OCTAVE_VERSION ]] || { echo "Can't find OCTAVE_VERSION in versions.mk" >&2; exit 1; }
 # shellcheck disable=SC1117
-echo -e "function v = supported_octave_version\nv=\"${OCTAVE_VERSION}\";\nend" > ../matlab/supported_octave_version.m
-
-if [[ -z $CI ]]; then
-    echo "Building out of GitLab CI is not supported, documentation support needs to be fixed" 2>&1
-    exit 1
-fi
+echo -e "function v = supported_octave_version\nv=\"${OCTAVE_VERSION}\";\nend" > matlab/supported_octave_version.m
 
 ## Create Windows installer
+cd windows
 makensis -DVERSION="$VERSION" dynare.nsi
 mkdir -p exe
+BASENAME=dynare-$VERSION
 mv dynare-"$VERSION"-win.exe "$ROOT_DIRECTORY"/exe/"$BASENAME"-win.exe
 
 ## Create 7z and zip archives (for people not allowed to download/execute the installer)
 
 # Set name of the root directory in the 7z and zip archives
-ZIPNAME=dynare-$VERSION
-ZIPDIR="$TMP_DIRECTORY"/"$ZIPNAME"
+ZIPDIR="$TMP_DIRECTORY"/"$BASENAME"
 mkdir -p "$ZIPDIR"
 
 cd ..
 cp -p NEWS.md "$ZIPDIR"
-cp -p VERSION "$ZIPDIR"
 cp -p license.txt "$ZIPDIR"
 cp -p windows/README.txt "$ZIPDIR"
 cp -pr windows/deps/mingw64 "$ZIPDIR"
@@ -207,11 +128,14 @@ mkdir -p "$ZIPDIR"/contrib/ms-sbvar/TZcode
 cp -pr contrib/ms-sbvar/TZcode/MatlabFiles "$ZIPDIR"/contrib/ms-sbvar/TZcode
 mkdir -p "$ZIPDIR"/contrib/jsonlab
 cp -pr contrib/jsonlab/* "$ZIPDIR"/contrib/jsonlab
-mkdir "$ZIPDIR"/mex
-cp -pr mex/octave/ "$ZIPDIR"/mex
-cp -pr mex/matlab/ "$ZIPDIR"/mex
+mkdir -p "$ZIPDIR"/mex/matlab/win64-8.3-9.3
+cp -p build-win-old-matlab/*.mexw64 "$ZIPDIR"/mex/matlab/win64-8.3-9.3
+mkdir -p "$ZIPDIR"/mex/matlab/win64-9.4-9.14
+cp -p build-win-matlab/*.mexw64 "$ZIPDIR"/mex/matlab/win64-9.4-9.14
+mkdir -p "$ZIPDIR"/mex/octave/win64
+cp -p build-win-octave/*.mex "$ZIPDIR"/mex/octave/win64
 mkdir "$ZIPDIR"/preprocessor
-cp -p preprocessor/src/dynare-preprocessor.exe "$ZIPDIR"/preprocessor
+cp -p build-win-matlab/preprocessor/src/dynare-preprocessor.exe "$ZIPDIR"/preprocessor
 cp -pr matlab "$ZIPDIR"
 mkdir -p "$ZIPDIR"/matlab/modules/dseries/externals/x13/windows/64
 cp -p windows/deps/lib64/x13as/x13as.exe "$ZIPDIR"/matlab/modules/dseries/externals/x13/windows/64
@@ -226,7 +150,7 @@ cp -pr build-doc/dynare-manual.html "$ZIPDIR"/doc
 cd "$TMP_DIRECTORY"
 
 mkdir -p "$ROOT_DIRECTORY"/zip
-zip -9 --quiet --recurse-paths "$ROOT_DIRECTORY"/zip/"$BASENAME"-win.zip "$ZIPNAME"
+zip -9 --quiet --recurse-paths "$ROOT_DIRECTORY"/zip/"$BASENAME"-win.zip "$BASENAME"
 
 mkdir -p "$ROOT_DIRECTORY"/7z
-7zr a -mx=9 "$ROOT_DIRECTORY"/7z/"$BASENAME"-win.7z "$ZIPNAME"
+7zr a -mx=9 "$ROOT_DIRECTORY"/7z/"$BASENAME"-win.7z "$BASENAME"
diff --git a/windows/deps/Makefile b/windows/deps/Makefile
index 2d3258389660d5dce0d21e0fd78826fd1294da6a..70f54f45fe36239fc36706ac7fced986da6a0c8d 100644
--- a/windows/deps/Makefile
+++ b/windows/deps/Makefile
@@ -21,6 +21,9 @@ ROOT_PATH = $(realpath .)
 
 WGET_OPTIONS := --no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error
 
+# See comments in scripts/windows-cross.ini
+FFLAGS := -O3 -march=nocona -msahf -mtune=generic
+
 .PHONY: all build octave matlab msys2 \
 	build build-slicot build-x13as \
 	clean-lib clean-libslicot clean-matlab clean-octave clean-msys2 clean-x13as-bin \
@@ -48,12 +51,6 @@ tarballs/slicot-$(SLICOT_VERSION).tar.gz:
 	mkdir -p tarballs
 	wget $(WGET_OPTIONS) -O $@ https://deb.debian.org/debian/pool/main/s/slicot/slicot_$(SLICOT_VERSION).orig.tar.gz
 
-sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer: tarballs/slicot-$(SLICOT_VERSION).tar.gz
-	rm -rf sources64/slicot-*-with-32bit-integer
-	mkdir -p $@
-	tar xf $< --directory $@ --strip-components=1
-	touch $@
-
 sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer: tarballs/slicot-$(SLICOT_VERSION).tar.gz
 	rm -rf sources64/slicot-*-with-64bit-integer
 	mkdir -p $@
@@ -66,49 +63,27 @@ sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer-and-underscore: tarballs/s
 	tar xf $< --directory $@ --strip-components=1
 	touch $@
 
-sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer-and-underscore: tarballs/slicot-$(SLICOT_VERSION).tar.gz
-	rm -rf sources64/slicot-*-with-64bit-integer-and-underscore
-	mkdir -p $@
-	tar xf $< --directory $@ --strip-components=1
-	touch $@
-
-lib64/Slicot/without-underscore/lib/libslicot_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer
-	make -C $< lib SLICOTLIB=../libslicot_pic.a OPTS="-O2 -g -fno-underscoring" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
-	x86_64-w64-mingw32-strip --strip-debug $</libslicot_pic.a
-	mkdir -p $(dir $@)
-	cp $</libslicot_pic.a $@
-
-lib64/Slicot/without-underscore/lib/libslicot64_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer
-	make -C $< lib SLICOTLIB=../libslicot64_pic.a OPTS="-O2 -g -fno-underscoring -fdefault-integer-8" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
+lib64/Slicot/without-underscore/libslicot64_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer
+	make -C $< lib SLICOTLIB=../libslicot64_pic.a OPTS="$(FFLAGS) -fno-underscoring -fdefault-integer-8" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
 	x86_64-w64-mingw32-strip --strip-debug $</libslicot64_pic.a
 	mkdir -p $(dir $@)
 	cp $</libslicot64_pic.a $@
 
-lib64/Slicot/with-underscore/lib/libslicot_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer-and-underscore
-	make -C $< lib SLICOTLIB=../libslicot_pic.a OPTS="-O2 -g" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
+lib64/Slicot/with-underscore/libslicot_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer-and-underscore
+	make -C $< lib SLICOTLIB=../libslicot_pic.a OPTS="$(FFLAGS)" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
 	x86_64-w64-mingw32-strip --strip-debug $</libslicot_pic.a
 	mkdir -p $(dir $@)
 	cp $</libslicot_pic.a $@
 
-lib64/Slicot/with-underscore/lib/libslicot64_pic.a: sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer-and-underscore
-	make -C $< lib SLICOTLIB=../libslicot64_pic.a OPTS="-O2 -g -fdefault-integer-8" FORTRAN=x86_64-w64-mingw32-gfortran LOADER=x86_64-w64-mingw32-gfortran ARCH=x86_64-w64-mingw32-ar
-	x86_64-w64-mingw32-strip --strip-debug $</libslicot64_pic.a
-	mkdir -p $(dir $@)
-	cp $</libslicot64_pic.a $@
-
-build-slicot: lib64/Slicot/without-underscore/lib/libslicot_pic.a \
-	lib64/Slicot/without-underscore/lib/libslicot64_pic.a \
-	lib64/Slicot/with-underscore/lib/libslicot_pic.a \
-	lib64/Slicot/with-underscore/lib/libslicot64_pic.a
+build-slicot: lib64/Slicot/without-underscore/libslicot64_pic.a \
+	lib64/Slicot/with-underscore/libslicot_pic.a
 
 clean-slicot-tar:
 	rm -f tarballs/slicot-$(SLICOT_VERSION).tar.gz
 
 clean-slicot-src:
-	rm -rf sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer
 	rm -rf sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer
 	rm -rf sources64/slicot-$(SLICOT_VERSION)-with-32bit-integer-and-underscore
-	rm -rf sources64/slicot-$(SLICOT_VERSION)-with-64bit-integer-and-underscore
 
 clean-libslicot:
 	rm -rf lib64/Slicot
@@ -157,7 +132,7 @@ matlab64: tarballs/matlab64-$(MATLAB64_VERSION).tar.xz
 matlab: matlab64
 
 clean-matlab:
-	rm -f tarballs/matlab64.tar.xz
+	rm -f tarballs/matlab64*.tar.xz
 	rm -rf matlab64
 
 #
@@ -173,7 +148,11 @@ MSYS2_EXCLUDES := --exclude .MTREE --exclude .BUILDINFO --exclude .PKGINFO
 lib64-msys2: tarballs/mingw-w64-x86_64-boost-$(MINGW64_BOOST_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-gsl-$(MINGW64_GSL_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-matio-$(MINGW64_MATIO_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-zlib-$(MINGW64_ZLIB_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-hdf5-$(MINGW64_HDF5_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libaec-$(MINGW64_LIBAEC_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-openssl-$(MINGW64_OPENSSL_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-curl-$(MINGW64_CURL_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-zstd-$(MINGW64_ZSTD_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-brotli-$(MINGW64_BROTLI_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libidn2-$(MINGW64_LIBIDN2_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libpsl-$(MINGW64_LIBPSL_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libssh2-$(MINGW64_LIBSSH2_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-nghttp2-$(MINGW64_NGHTTP2_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libiconv-$(MINGW64_LIBICONV_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libunistring-$(MINGW64_LIBUNISTRING_VERSION)-any.pkg.tar.zst
 	rm -rf $@
 	mkdir $@
-	for f in $^; do tar xf $$f --directory $@ --strip-components 1 $(MSYS2_EXCLUDES); done
+	for f in $^; do tar xf $$f --directory $@ $(MSYS2_EXCLUDES); done
+	# Workaround for https://sourceforge.net/p/matio/bugs/42/
+	patch -d lib64-msys2/mingw64/lib/pkgconfig/ < matio.pc.patch
+	# Workaround for https://github.com/msys2/MINGW-packages/issues/18554
+	patch -d lib64-msys2/mingw64/lib/pkgconfig/ < hdf5.pc.patch
 	touch $@
 
 mingw64: tarballs/mingw-w64-x86_64-gcc-$(MINGW64_GCC_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-gcc-libs-$(MINGW64_GCC_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-gmp-$(MINGW64_GMP_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-binutils-$(MINGW64_BINUTILS_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-headers-git-$(MINGW64_HEADERS_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-crt-git-$(MINGW64_CRT_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-winpthreads-git-$(MINGW64_WINPTHREADS_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libwinpthread-git-$(MINGW64_WINPTHREADS_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-zlib-$(MINGW64_ZLIB_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-zstd-$(MINGW64_ZSTD_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-isl-$(MINGW64_ISL_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-mpc-$(MINGW64_MPC_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-mpfr-$(MINGW64_MPFR_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-libiconv-$(MINGW64_LIBICONV_VERSION)-any.pkg.tar.zst tarballs/mingw-w64-x86_64-windows-default-manifest-$(MINGW64_WINDOWS_DEFAULT_MANIFEST_VERSION)-any.pkg.tar.zst
diff --git a/windows/deps/hdf5.pc.patch b/windows/deps/hdf5.pc.patch
new file mode 100644
index 0000000000000000000000000000000000000000..90e93f560c528b1bf3bbe09add4e4064435cd5e1
--- /dev/null
+++ b/windows/deps/hdf5.pc.patch
@@ -0,0 +1,9 @@
+--- hdf5.pc.orig	2023-07-27 14:48:13.395698365 +0200
++++ hdf5.pc	2023-09-19 15:36:49.497960385 +0200
+@@ -10,5 +10,4 @@
+ Cflags: -I${includedir}
+ Libs: -L${libdir}  -lhdf5
+ Requires: 
+-Libs.private:  -lhdf5  -lshlwapi -lm -lws2_32 -lwsock32 -l/mingw64/lib/libcurl.dll.a -l/mingw64/lib/libssl.dll.a -l/mingw64/lib/libcrypto.dll.a -l/mingw64/lib/libz.dll.a
+-Requires.private: 
++Requires.private: libcurl zlib
diff --git a/windows/deps/matio.pc.patch b/windows/deps/matio.pc.patch
new file mode 100644
index 0000000000000000000000000000000000000000..cb81cdec14cb61a472445430181c2c8bee805910
--- /dev/null
+++ b/windows/deps/matio.pc.patch
@@ -0,0 +1,10 @@
+--- matio.pc.orig	2023-07-27 14:48:13.395698365 +0200
++++ matio.pc	2023-09-19 14:12:05.423816518 +0200
+@@ -6,5 +6,6 @@
+ Name: MATIO
+ Description: MATIO Library
+ Version: 1.5.23
+-Libs: -L${libdir} -lmatio -lhdf5 -lz
++Libs: -L${libdir} -lmatio -lz
++Requires.private: hdf5
+ Cflags: -I${includedir}  
diff --git a/windows/deps/versions.mk b/windows/deps/versions.mk
index 526873f62cd9ed6af9d059975b39504e34a38991..52e426df0b53ddca271c6b127012d64431e058f3 100644
--- a/windows/deps/versions.mk
+++ b/windows/deps/versions.mk
@@ -24,6 +24,7 @@ MINGW64_BOOST_VERSION = 1.81.0-7
 MINGW64_GSL_VERSION = 2.7.1-1
 
 # pacman -Ss mingw-w64-x86_64-matio
+# NB: matio.pc.patch may need to be updated when upgrading
 MINGW64_MATIO_VERSION = 1.5.23-4
 
 # Dependency of matio (and of the MinGW compiler)
@@ -32,6 +33,7 @@ MINGW64_ZLIB_VERSION = 1.2.13-3
 
 # Dependency of matio
 # pacman -Ss mingw-w64-x86_64-hdf5
+# NB: hdf5.pc.patch may need to be updated when upgrading
 MINGW64_HDF5_VERSION = 1.14.1.2-2
 
 # Dependency of HDF5 (provides szip library)
diff --git a/windows/dynare.nsi b/windows/dynare.nsi
index 348cc53e151033d68baa15c048dc9c5ff5f9193c..61282eb4e953e5087bc472df2c5505088cf754df 100644
--- a/windows/dynare.nsi
+++ b/windows/dynare.nsi
@@ -49,13 +49,13 @@ Section "Dynare core (preprocessor and M-files)"
  SectionIn RO
 !insertmacro DETERMINE_CONTEXT
  SetOutPath $INSTDIR
- File README.txt ..\NEWS.md ..\license.txt ..\VERSION
+ File README.txt ..\NEWS.md ..\license.txt
 
  SetOutPath $INSTDIR\matlab
  File /r ..\matlab\*.m
 
  SetOutPath $INSTDIR\preprocessor
- File ..\preprocessor\src\dynare-preprocessor.exe
+ File ..\build-win-matlab\preprocessor\src\dynare-preprocessor.exe
 
  SetOutPath $INSTDIR\matlab\preprocessor64
  File ..\matlab\preprocessor64\dynare_m.exe
@@ -92,12 +92,12 @@ SectionEnd
 
 Section "MEX files for MATLAB 64-bit, version 8.3 to 9.3 (R2014a to R2017b)"
  SetOutPath $INSTDIR\mex\matlab\win64-8.3-9.3
- File ..\mex\matlab\win64-8.3-9.3\*.mexw64
+ File ..\build-win-old-matlab\*.mexw64
 SectionEnd
 
 Section "MEX files for MATLAB 64-bit, version 9.4 to 9.14 (R2018a to R2023a)"
  SetOutPath $INSTDIR\mex\matlab\win64-9.4-9.14
- File ..\mex\matlab\win64-9.4-9.14\*.mexw64
+ File ..\build-win-matlab\*.mexw64
 SectionEnd
 
 Section "MinGW compiler for MATLAB 64-bit"
@@ -107,7 +107,7 @@ SectionEnd
 
 Section "MEX files for Octave 8.3.0 (64-bit)"
  SetOutPath $INSTDIR\mex\octave\win64
- File ..\mex\octave\win64\*
+ File ..\build-win-octave\*.mex
 SectionEnd
 
 Section "Documentation and examples"
diff --git a/windows/install-packages.sh b/windows/install-packages.sh
index 1eab1e6e8ad86ec6633e98743ecccde3ea7b8606..db0ed947ccbcedb113d17d5903066d39a04de4cd 100755
--- a/windows/install-packages.sh
+++ b/windows/install-packages.sh
@@ -22,9 +22,9 @@
 
 [[ $(id -u) == 0 ]] || { echo "You must be root" >&2; exit 1; }
 
-PACKAGES=(make p7zip zip zstd wget autoconf automake
+PACKAGES=(make p7zip zip zstd wget meson mingw-w64-tools
           gcc-mingw-w64-x86-64-posix g++-mingw-w64-x86-64-posix
-          gfortran-mingw-w64-x86-64-posix parallel flex libfl-dev bison texlive
+          gfortran-mingw-w64-x86-64-posix flex libfl-dev bison texlive
           texlive-publishers texlive-latex-extra texlive-science
           texlive-fonts-extra lmodern python3-sphinx latexmk nsis)