diff --git a/.gitignore b/.gitignore
index b0f4ec1d845d085e20d48ca30035da6ae667e328..db2052d98b06c78cdd0e4cf674744c163d5eefb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,12 +70,9 @@ doc/internals/*.html
 doc/internals/ltxpng
 
 # MATLAB dir
-/matlab/preprocessor*
+/matlab/preprocessor64/
 /matlab/dynare_version.m
 
-# JULIA dir
-/julia/preprocessor*
-
 # DLL rules
 *.mex
 *.oct
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 83e522be35bf31d0c0e13a4e34acb54c2b92b630..7b502354cc062ef2709f03fb6cc72de568b12fa4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,7 +33,7 @@ build_binaries:
     - make -j $(nproc) LN_S="cp -p"
   artifacts:
     paths:
-      - matlab/preprocessor*/*
+      - preprocessor/dynare-preprocessor
       - mex/octave/
       - mex/matlab/
       - dynare++/parser/cc/*_tab.cc
diff --git a/Makefile.am b/Makefile.am
index 410ca9a22ef1ec784246b9c353bab502f2c929b7..5433c26a0a3a9bfaee12080e184488f9a313a742 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,25 +27,29 @@ EXTRA_DIST = \
 	scripts \
 	.dir-locals.el
 
-all-local: preprocessor/src/dynare_m$(EXEEXT)
-	if file preprocessor/src/dynare_m$(EXEEXT) | grep -q x86.64; then \
-	  ARCH="64"; \
-	else \
-	  ARCH="32"; \
-	fi; \
-	mkdir -p $(abs_srcdir)/matlab/preprocessor$$ARCH && \
-	$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare_m$(EXEEXT) $(abs_srcdir)/matlab/preprocessor$$ARCH
+all-local:
+# Create top-level preprocessor symlink needed by matlab/dynare.m (when Dynare is run
+# from the locally-built copy)
+	$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare-preprocessor$(EXEEXT) $(abs_builddir)/preprocessor/dynare-preprocessor$(EXEEXT)
+# Create backward-compatibility symlink for old location of preprocessor
+	$(MKDIR_P) matlab/preprocessor64/
+	$(LN_S) -f $(abs_builddir)/preprocessor/src/dynare-preprocessor$(EXEEXT) $(abs_srcdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
 
 clean-local:
-	rm -rf $(abs_srcdir)/matlab/preprocessor32 $(abs_srcdir)/matlab/preprocessor64
+	rm -f preprocessor/dynare-preprocessor$(EXEEXT)
+	rm -rf matlab/preprocessor64/
 
 dist-hook:
 	rm -rf `find $(distdir)/matlab $(distdir)/examples -name *~`
-	rm -rf $(distdir)/matlab/preprocessor* $(distdir)/matlab/dynare_version.m
+	rm -f $(distdir)/matlab/dynare_version.m
+	rm -rf $(distdir)/matlab/preprocessor64/
 	$(MKDIR_P) $(distdir)/mex/matlab $(distdir)/mex/octave
 	rm -rf `find $(distdir) -name '.git*'`
 
 install-exec-local:
+	$(MKDIR_P) $(DESTDIR)$(pkglibdir)/preprocessor
+# The following will break under Windows, but we don’t use the install rule there
+	$(LN_S) -f $(bindir)/dynare-preprocessor$(EXEEXT) $(DESTDIR)$(pkglibdir)/preprocessor/dynare-preprocessor$(EXEEXT)
 	$(MKDIR_P) $(DESTDIR)$(pkglibdir)/contrib/ms-sbvar/TZcode
 	cp -r contrib/ms-sbvar/TZcode/MatlabFiles $(DESTDIR)$(pkglibdir)/contrib/ms-sbvar/TZcode
 	$(MKDIR_P) $(DESTDIR)$(pkglibdir)/contrib/jsonlab
@@ -53,14 +57,17 @@ install-exec-local:
 	cp -r examples $(DESTDIR)$(pkglibdir)
 	cp -r matlab $(DESTDIR)$(pkglibdir)
 	find $(DESTDIR)$(pkglibdir) -name LICENSE.md -delete
-	rm -rf $(DESTDIR)$(pkglibdir)/matlab/preprocessor*
-	if file preprocessor/src/dynare_m | grep -q x86.64; then \
-	  ARCH="64"; \
-	else \
-	  ARCH="32"; \
-	fi; \
-	mkdir -p $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH && \
-	cp preprocessor/src/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH
+# Recreate backward-compatibility symlink
+	rm -f $(DESTDIR)$(pkglibdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
+	$(LN_S) -f $(bindir)/dynare-preprocessor$(EXEEXT) $(DESTDIR)$(pkglibdir)/matlab/preprocessor64/dynare_m$(EXEEXT)
+# We don’t fail over doc install rules, since the user may deliberately not have compiled them
+# (e.g. with the “nodoc” option under Debian)
+	$(MKDIR_P) $(docdir)
+	-cp doc/*.pdf doc/gsa/gsa.pdf doc/parallel/parallel.pdf doc/dseries-and-reporting/dseriesReporting.pdf preprocessor/doc/preprocessor/preprocessor.pdf preprocessor/doc/macroprocessor/macroprocessor.pdf doc/manual/build/latex/dynare-manual.pdf $(docdir)
+	-cp -r doc/manual/build/html $(docdir)/dynare-manual.html
+	$(MKDIR_P) $(docdir)/dynare++
+	-cp dynare++/doc/*.pdf $(docdir)/dynare++
 
 uninstall-local:
 	rm -rf $(DESTDIR)$(pkglibdir)
+	rm -rf $(DESTDIR)$(docdir)
diff --git a/macOS/build.sh b/macOS/build.sh
index d552c90dba4565f33ea053db468894b9c9dece19..8d062892ab262c15aab71371745cb99ff5a7a2af 100755
--- a/macOS/build.sh
+++ b/macOS/build.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-# Copyright © 2019-2020 Dynare Team
+# Copyright © 2019-2021 Dynare Team
 #
 # This file is part of Dynare.
 #
@@ -90,6 +90,7 @@ make -j"$NTHREADS"
 NAME=dynare-"$VERSION"
 PKGFILES="$ROOTDIR"/macOS/pkg/"$NAME"
 mkdir -p \
+      "$PKGFILES"/preprocessor \
       "$PKGFILES"/mex/matlab/maci64-8.3-9.3 \
       "$PKGFILES"/mex/matlab/maci64-9.4-9.9 \
       "$PKGFILES"/mex/octave \
@@ -109,6 +110,12 @@ cp -p  "$ROOTDIR"/license.txt                                        "$PKGFILES"
 cp -pr "$ROOTDIR"/matlab                                             "$PKGFILES"
 cp -pr "$ROOTDIR"/examples                                           "$PKGFILES"
 
+cp -p  "$ROOTDIR"/preprocessor/src/dynare-preprocessor               "$PKGFILES"/preprocessor
+
+# Recreate backward-compatibility symlink
+rm -f "$ROOTDIR"/matlab/preprocessor64/dynare_m
+ln -sf ../../preprocessor/dynare-preprocessor                        "$PKGFILES"/matlab/preprocessor64/dynare_m
+
 cp -L  "$ROOTDIR"/mex/matlab/*                                       "$PKGFILES"/mex/matlab/maci64-8.3-9.3
 
 cp -p  "$ROOTDIR"/scripts/dynare.el                                  "$PKGFILES"/scripts
diff --git a/matlab/dynare.m b/matlab/dynare.m
index f302e3100f24c60ea9b745c117f647b8ca4134b2..4df698911f1d899664e4a4c016f39800faf39976 100644
--- a/matlab/dynare.m
+++ b/matlab/dynare.m
@@ -194,18 +194,6 @@ if ~nolog
     diary(logfile)
 end
 
-if ispc
-    arch = getenv('PROCESSOR_ARCHITECTURE');
-else
-    [~, arch] = system('uname -m');
-end
-
-if isempty(strfind(arch, '64'))
-    arch_ext = '32';
-else
-    arch_ext = '64';
-end
-
 if preprocessoroutput
     fprintf(['Starting Dynare (version ' dynare_version() ').\n']);
     fprintf('Calling Dynare with arguments: ');
@@ -216,7 +204,7 @@ if preprocessoroutput
     end
 end
 
-command = ['"' dynareroot 'preprocessor' arch_ext filesep 'dynare_m" ' fname] ;
+command = ['"' dynareroot '..' filesep 'preprocessor' filesep 'dynare-preprocessor" ' fname] ;
 command = [ command ' mexext=' mexext ' "matlabroot=' matlabroot '"'];
 % Properly quote arguments before passing them to the shell
 if ~isempty(varargin)
diff --git a/preprocessor b/preprocessor
index cd443a6083ab294f21e35278a95352796480d98c..a9daec1c0739f244e2e041f20443af6a6fae555d 160000
--- a/preprocessor
+++ b/preprocessor
@@ -1 +1 @@
-Subproject commit cd443a6083ab294f21e35278a95352796480d98c
+Subproject commit a9daec1c0739f244e2e041f20443af6a6fae555d
diff --git a/windows/dynare.nsi b/windows/dynare.nsi
index 41226695d08bbdd097f35b78001f8b713cbf1733..65ad3cad0ee66eee096e2b2085a2d8faf1d35f64 100644
--- a/windows/dynare.nsi
+++ b/windows/dynare.nsi
@@ -54,8 +54,8 @@ Section "Dynare core (preprocessor and M-files)"
  SetOutPath $INSTDIR\matlab
  File /r ..\matlab\*.m
 
- SetOutPath $INSTDIR\matlab\preprocessor64
- File ..\matlab\preprocessor64\dynare_m.exe
+ SetOutPath $INSTDIR\preprocessor
+ File ..\preprocessor\src\dynare-preprocessor.exe
 
  SetOutPath $INSTDIR\matlab\modules\dseries\externals\x13\windows\64
  File deps\lib64\x13as\x13as.exe
@@ -141,6 +141,7 @@ Section "Uninstall"
  Delete $INSTDIR\license.txt
  Delete $INSTDIR\VERSION
  Rmdir /r $INSTDIR\matlab
+ Rmdir /r $INSTDIR\preprocessor
  Rmdir /r $INSTDIR\contrib
  Rmdir /r $INSTDIR\mex
  Rmdir /r $INSTDIR\dynare++