diff --git a/doc/meson.build b/doc/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..4da276655476cf71bc4722e6392db62681202727
--- /dev/null
+++ b/doc/meson.build
@@ -0,0 +1,29 @@
+latexmk = find_program('latexmk')
+
+# We have to set TEXINPUTS because the current directory is not the source
+# directory when latexmk is invoked (and using the -cd option in combination
+# with -outdir/-auxdir does not work in all cases because @OUTDIR@ and
+# @PRIVATE_DIR@ can be relative paths)
+
+# Without the -g flag, latexmk remembers a previous build failure and will refuse
+# to recompile even if the error has been fixed in the TeX source
+
+# The \graphicspath{} command does not compute directories relative to TEXINPUTS,
+# so add these manually
+logos_dir = meson.current_source_dir() / 'logos'
+
+custom_target('macroprocessor.pdf',
+              output : 'macroprocessor.pdf',
+              input : 'macroprocessor/macroprocessor.tex',
+              command : [ latexmk, '-pdf', '-g', '-outdir=@OUTDIR@', '-auxdir=@PRIVATE_DIR@', '@INPUT@'],
+              env : { 'TEXINPUTS': meson.current_source_dir() + '/macroprocessor:' + logos_dir + ':' },
+              install : true,
+              install_dir : 'share/doc/dynare')
+
+custom_target('preprocessor.pdf',
+              output : 'preprocessor.pdf',
+              input : 'preprocessor/preprocessor.tex',
+              command : [ latexmk, '-pdf', '-g', '-outdir=@OUTDIR@', '-auxdir=@PRIVATE_DIR@', '@INPUT@'],
+              env : { 'TEXINPUTS': meson.current_source_dir() + '/preprocessor:' + logos_dir + ':' },
+              install : true,
+              install_dir : 'share/doc/dynare')
diff --git a/meson.build b/meson.build
index 1d8ede8584396f619c62a65f270de457767b376c..68985f21d4c367694702a1842c53eae0c9b40b2d 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,5 @@
-# TODO for reaching feature parity with current autotools-based build system:
-# - Configuration option to disable documentation
-# - Add -Wold-style-cast flag except when building flex-generated files
+# Meson file for building the preprocessor in a standalone fashion.
+# It is not used when building Dynare as a whole.
 
 project('dynare-preprocessor', 'cpp',
         version : '6-unstable',
@@ -8,100 +7,7 @@ project('dynare-preprocessor', 'cpp',
 
 add_global_arguments('-DPACKAGE_VERSION="' + meson.project_version() + '"', language : 'cpp')
 
-boost_dep = dependency('boost')
+cpp_compiler = meson.get_compiler('cpp')
 
-## Flex stuff
-flex_exe = find_program('flex')
-# The -Ca flag comes from hitting a hard-coded size limit.
-# Partial explanation: https://www.owlfolio.org/possibly-useful/flex-input-scanner-rules-are-too-complicated
-# There is a Debian bug report about this: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=642040
-flex_gen = generator(flex_exe, output : '@BASENAME@.cc',
-                     arguments : ['-Ca', '-o', '@OUTPUT@', '@INPUT@'])
-flex_src = flex_gen.process('src/macro/Tokenizer.ll', 'src/DynareFlex.ll')
-# If FlexLexer.h is not found by the compiler, copy it to the build directory
-# (adding an include directory could create problems for cross-compilation, because
-# flex is typically provided by the system of the build machine)
-compiler = meson.get_compiler('cpp')
-if not compiler.has_header('FlexLexer.h')
-  message('FlexLexer.h cannot be found by the compiler, it will be manually copied to the build directory')
-  fs = import('fs')
-  flexlexer_h = fs.copyfile(fs.parent(fs.parent(flex_exe.full_path())) / 'include' / 'FlexLexer.h', 'FlexLexer.h')
-else
-  flexlexer_h = []
-endif
-
-## Bison stuff
-bison_exe = find_program('bison')
-# By convention, all our Bison source files define the api.location.file variable
-# so that the generated location file follows the @BASENAME@Location.hh pattern
-bison_gen = generator(bison_exe, output : ['@BASENAME@.cc', '@BASENAME@.hh', '@BASENAME@Location.hh'],
-                      arguments : ['-W', '-o', '@OUTPUT0@', '@INPUT@'])
-bison_src = bison_gen.process('src/macro/Parser.yy', 'src/DynareBison.yy')
-
-incdir = include_directories('src', 'src/macro')
-
-main_src = [ 'src/ComputingTasks.cc',
-	     'src/EquationTags.cc',
-	     'src/ModelTree.cc',
-	     'src/StaticModel.cc',
-	     'src/DynamicModel.cc',
-	     'src/NumericalConstants.cc',
-	     'src/NumericalInitialization.cc',
-	     'src/Shocks.cc',
-	     'src/SymbolTable.cc',
-	     'src/SymbolList.cc',
-	     'src/ParsingDriver.cc',
-	     'src/DataTree.cc',
-	     'src/ModFile.cc',
-	     'src/ConfigFile.cc',
-	     'src/Statement.cc',
-	     'src/ExprNode.cc',
-	     'src/VariableDependencyGraph.cc',
-	     'src/DynareMain.cc',
-	     'src/MacroExpandModFile.cc',
-	     'src/Bytecode.cc',
-	     'src/ExternalFunctionsTable.cc',
-	     'src/ModelEquationBlock.cc',
-	     'src/WarningConsolidation.cc',
-	     'src/SubModel.cc',
-             'src/macro/Driver.cc',
-	     'src/macro/Environment.cc',
-	     'src/macro/Expressions.cc',
-	     'src/macro/Directives.cc' ]
-
-executable('dynare-preprocessor', main_src, flex_src, flexlexer_h, bison_src,
-           include_directories : incdir, dependencies : boost_dep,
-           link_args : get_option('prefer_static') ? '-static' : '',
-           install : true)
-
-## LaTeX stuff
-
-latexmk = find_program('latexmk')
-
-# We have to set TEXINPUTS because the current directory is not the source
-# directory when latexmk is invoked (and using the -cd option in combination
-# with -outdir/-auxdir does not work in all cases because @OUTDIR@ and
-# @PRIVATE_DIR@ can be relative paths)
-
-# Without the -g flag, latexmk remembers a previous build failure and will refuse
-# to recompile even if the error has been fixed in the TeX source
-
-# The \graphicspath{} command does not compute directories relative to TEXINPUTS,
-# so add these manually
-logos_dir = meson.current_source_dir() + '/doc/logos'
-
-custom_target('macroprocessor.pdf',
-              output : 'macroprocessor.pdf',
-              input : 'doc/macroprocessor/macroprocessor.tex',
-              command : [ latexmk, '-pdf', '-g', '-auxdir=@PRIVATE_DIR@', '@INPUT@'],
-              env : { 'TEXINPUTS': meson.current_source_dir() + '/doc/macroprocessor:' + logos_dir + ':' },
-              install : true,
-              install_dir : 'share/doc/dynare')
-
-custom_target('preprocessor.pdf',
-              output : 'preprocessor.pdf',
-              input : 'doc/preprocessor/preprocessor.tex',
-              command : [ latexmk, '-pdf', '-g', '-auxdir=@PRIVATE_DIR@', '@INPUT@'],
-              env : { 'TEXINPUTS': meson.current_source_dir() + '/doc/preprocessor:' + logos_dir + ':' },
-              install : true,
-              install_dir : 'share/doc/dynare')
+subdir('src')
+subdir('doc')
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..ff1ee552e8d96ebdfee15620bc81c91bbd8d636c
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,64 @@
+boost_dep = dependency('boost')
+
+## Flex stuff
+flex_exe = find_program('flex')
+# The -Ca flag comes from hitting a hard-coded size limit.
+# Partial explanation: https://www.owlfolio.org/possibly-useful/flex-input-scanner-rules-are-too-complicated
+# There is a Debian bug report about this: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=642040
+flex_gen = generator(flex_exe, output : '@BASENAME@.cc',
+                     arguments : ['-Ca', '-o', '@OUTPUT@', '@INPUT@'])
+flex_src = flex_gen.process('macro/Tokenizer.ll', 'DynareFlex.ll')
+# If FlexLexer.h is not found by the compiler, copy it to the build directory
+# (adding an include directory could create problems for cross-compilation, because
+# flex is typically provided by the system of the build machine)
+if not cpp_compiler.has_header('FlexLexer.h')
+  message('FlexLexer.h cannot be found by the compiler, it will be manually copied to the build directory')
+  fs = import('fs')
+  flexlexer_h = fs.copyfile(fs.parent(fs.parent(flex_exe.full_path())) / 'include' / 'FlexLexer.h', 'FlexLexer.h')
+else
+  flexlexer_h = []
+endif
+
+## Bison stuff
+bison_exe = find_program('bison')
+# By convention, all our Bison source files define the api.location.file variable
+# so that the generated location file follows the @BASENAME@Location.hh pattern
+bison_gen = generator(bison_exe, output : ['@BASENAME@.cc', '@BASENAME@.hh', '@BASENAME@Location.hh'],
+                      arguments : ['-W', '-o', '@OUTPUT0@', '@INPUT@'])
+bison_src = bison_gen.process('macro/Parser.yy', 'DynareBison.yy')
+
+preprocessor_incdir = include_directories('.', 'macro')
+
+preprocessor_src = [ 'ComputingTasks.cc',
+	             'EquationTags.cc',
+	             'ModelTree.cc',
+	             'StaticModel.cc',
+	             'DynamicModel.cc',
+	             'NumericalConstants.cc',
+	             'NumericalInitialization.cc',
+	             'Shocks.cc',
+	             'SymbolTable.cc',
+	             'SymbolList.cc',
+	             'ParsingDriver.cc',
+	             'DataTree.cc',
+	             'ModFile.cc',
+	             'ConfigFile.cc',
+	             'Statement.cc',
+	             'ExprNode.cc',
+	             'VariableDependencyGraph.cc',
+	             'DynareMain.cc',
+	             'MacroExpandModFile.cc',
+	             'Bytecode.cc',
+	             'ExternalFunctionsTable.cc',
+	             'ModelEquationBlock.cc',
+	             'WarningConsolidation.cc',
+	             'SubModel.cc',
+                     'macro/Driver.cc',
+	             'macro/Environment.cc',
+	             'macro/Expressions.cc',
+	             'macro/Directives.cc' ]
+
+executable('dynare-preprocessor', preprocessor_src, flex_src, flexlexer_h, bison_src,
+           include_directories : preprocessor_incdir, dependencies : boost_dep,
+           link_args : get_option('prefer_static') ? '-static' : '',
+           install : true)