diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 5734fa13a8f90bb9207c6640ed732aa946e1a62f..063d2a9805bbc8bd5be9fdf2e530c4eb51bac9bd 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -84,7 +84,7 @@ class ParsingDriver;
 %token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION
 %token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS LAST_OBS SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED
 %token <string> FLOAT_NUMBER DATES
-%token DEFAULT FIXED_POINT FLIP OPT_ALGO
+%token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS
 %token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN
 %token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD
 %token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID HYBRID ONE_SIDED_HP_FILTER
@@ -308,6 +308,7 @@ statement : parameters
           | init2shocks
           | det_cond_forecast
           | var_expectation_model
+          | compilation_setup
           ;
 
 dsample : DSAMPLE INT_NUMBER ';'
@@ -890,6 +891,24 @@ epilogue_equation : NAME { driver.add_epilogue_variable($1); } EQUAL expression
                     { driver.add_epilogue_equal($1, $4); }
                   ;
 
+compilation_setup : COMPILATION_SETUP '(' compilation_setup_options_list ')' ';' { };
+
+compilation_setup_options_list : compilation_setup_options_list COMMA compilation_setup_option
+                               | compilation_setup_option
+                               ;
+
+compilation_setup_option : SUBSTITUTE_FLAGS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_substitute_flags($3); }
+                         | ADD_FLAGS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_add_flags($3); }
+                         | SUBSTITUTE_LIBS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_substitute_libs($3); }
+                         | ADD_LIBS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_add_libs($3); }
+                         | COMPILER EQUAL QUOTED_STRING
+                           { driver.compilation_setup_compiler($3); }
+                         ;
+
 model_options : BLOCK { driver.block(); }
               | o_cutoff
 							| o_mfs
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 747dbd348454d3bec4d69d039bd35e6312903399..989bc71b8e065cf4ea06c43146d6a15898f9991d 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -186,6 +186,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
 <INITIAL>perfect_foresight_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SETUP;}
 <INITIAL>perfect_foresight_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SOLVER;}
 <INITIAL>det_cond_forecast {BEGIN DYNARE_STATEMENT; return token::DET_COND_FORECAST;}
+<INITIAL>compilation_setup {BEGIN DYNARE_STATEMENT; return token::COMPILATION_SETUP;}
 
 <DYNARE_STATEMENT>; {
   if (!sigma_e)
@@ -563,6 +564,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
 <DYNARE_STATEMENT>tolf {return token::TOLF;}
 <DYNARE_STATEMENT>tolx {return token::TOLX;}
 <DYNARE_STATEMENT>opt_algo {return token::OPT_ALGO;}
+<DYNARE_STATEMENT>add_flags {return token::ADD_FLAGS;}
+<DYNARE_STATEMENT>substitute_flags {return token::SUBSTITUTE_FLAGS;}
+<DYNARE_STATEMENT>add_libs {return token::ADD_LIBS;}
+<DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;}
+<DYNARE_STATEMENT>compiler {return token::COMPILER;}
 <DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;}
 <DYNARE_STATEMENT>hessian  {
   yylval->build<string>(yytext);
diff --git a/src/Makefile.am b/src/Makefile.am
index b14f11a048350817962a2d01a6ceae2a707aaa20..24c56e11837e31f03fe3fe5a874931c59869b09c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,8 +68,11 @@ dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.
 dynare_m_LDFLAGS = $(AM_LDFLAGS) $(BOOST_LDFLAGS)
 dynare_m_LDADD = macro/libmacro.a -lstdc++fs
 
+# -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
 DynareFlex.cc: DynareFlex.ll
-	$(LEX) -o DynareFlex.cc DynareFlex.ll
+	$(LEX) -Ca -o DynareFlex.cc DynareFlex.ll
 
 FlexLexer.h:
 	cp $(LEXINC)/FlexLexer.h . || test -f ./FlexLexer.h
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 611310a061c22a8c5096f5d7f76eda577b71691e..113a11f0a5273714a8eaab40c2f2a7ae60130746 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -102,6 +102,11 @@ ModelTree::ModelTree(SymbolTable &symbol_table_arg,
 
 ModelTree::ModelTree(const ModelTree &m) :
   DataTree {m},
+  user_set_add_flags {m.user_set_add_flags},
+  user_set_subst_flags {m.user_set_subst_flags},
+  user_set_add_libs {m.user_set_add_libs},
+  user_set_subst_libs {m.user_set_subst_libs},
+  user_set_compiler {m.user_set_compiler},
   equations_lineno {m.equations_lineno},
   equation_tags {m.equation_tags},
   equation_tags_xref {m.equation_tags_xref},
@@ -157,6 +162,12 @@ ModelTree::operator=(const ModelTree &m)
   cutoff = m.cutoff;
   mfs = m.mfs;
 
+  user_set_add_flags = m.user_set_add_flags;
+  user_set_subst_flags = m.user_set_subst_flags;
+  user_set_add_libs = m.user_set_add_libs;
+  user_set_subst_libs = m.user_set_subst_libs;
+  user_set_compiler = m.user_set_compiler;
+
   copyHelper(m);
 
   return *this;
@@ -2317,7 +2328,7 @@ ModelTree::matlab_arch(const string &mexext)
 }
 
 void
-ModelTree::compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot)
+ModelTree::compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const
 {
   const string opt_flags = "-O3 -g0 --param ira-max-conflict-table-size=1 -fno-forward-propagate -fno-gcse -fno-dce -fno-dse -fno-tree-fre -fno-tree-pre -fno-tree-cselim -fno-tree-dse -fno-tree-dce -fno-tree-pta -fno-gcse-after-reload";
 
@@ -2411,7 +2422,35 @@ ModelTree::compileDll(const string &basename, const string &static_or_dynamic, c
      quotes to be correctly handled. See "cmd /?" for more details. */
   cmd << '"';
 #endif
-  cmd << compiler << " " << opt_flags << " " << flags.str() << " " << main_src << " " << mex_src << " -o " << binary << " " << libs;
+
+  if (user_set_compiler.empty())
+    cmd << compiler << " ";
+  else
+    if (!filesystem::exists(user_set_compiler))
+      {
+        cerr << "Error: The specified compiler '" << user_set_compiler << "' cannot be found on your system" << endl;
+        exit(EXIT_FAILURE);
+      }
+    else
+      cmd << user_set_compiler << " ";
+
+  if (user_set_subst_flags.empty())
+    cmd << opt_flags << " " << flags.str() << " ";
+  else
+    cmd << user_set_subst_flags << " ";
+
+  if (!user_set_add_flags.empty())
+    cmd << user_set_add_flags << " ";
+
+  cmd << main_src << " " << mex_src << " -o " << binary << " ";
+
+  if (user_set_subst_libs.empty())
+    cmd << libs;
+  else
+    cmd << user_set_subst_libs;
+
+  if (!user_set_add_libs.empty())
+    cmd << " " << user_set_add_libs;
 
 #ifdef _WIN32
   cmd << '"';
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 2b5c606df654f453e2db1e546c66b626d8291c2b..a0914aff03020fe2c33bed812f0b613498ce096c 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -64,6 +64,13 @@ class ModelTree : public DataTree
 {
   friend class DynamicModel;
   friend class StaticModel;
+public:
+  // The following 5 variables are set via the `compiler` command
+  string user_set_add_flags;
+  string user_set_subst_flags;
+  string user_set_add_libs;
+  string user_set_subst_libs;
+  string user_set_compiler;
 protected:
   /*
    * ************** BEGIN **************
@@ -324,7 +331,7 @@ private:
   //! Returns the name of the MATLAB architecture given the extension used for MEX files
   static string matlab_arch(const string &mexext);
   //! Compiles the MEX file
-  static void compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot);
+  void compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const;
 
 public:
   ModelTree(SymbolTable &symbol_table_arg,
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index de9b2abb4f75f60ae1667732883fe044db08b265..535790be6f4e98d29db5d4c5d77f0a19529e155b 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -793,6 +793,36 @@ ParsingDriver::mfs(const string &value)
   mod_file->static_model.mfs = val;
 }
 
+void
+ParsingDriver::compilation_setup_substitute_flags(const string & flags)
+{
+  mod_file->dynamic_model.user_set_subst_flags = flags;
+}
+
+void
+ParsingDriver::compilation_setup_add_flags(const string & flags)
+{
+  mod_file->dynamic_model.user_set_add_flags = flags;
+}
+
+void
+ParsingDriver::compilation_setup_substitute_libs(const string & libs)
+{
+  mod_file->dynamic_model.user_set_subst_libs = libs;
+}
+
+void
+ParsingDriver::compilation_setup_add_libs(const string & libs)
+{
+  mod_file->dynamic_model.user_set_add_libs = libs;
+}
+
+void
+ParsingDriver::compilation_setup_compiler(const string & compiler)
+{
+  mod_file->dynamic_model.user_set_compiler = compiler;
+}
+
 void
 ParsingDriver::balanced_growth_test_tol(const string &value)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 06622d164826684c2825f3d1d7e2f5d9f2925ca2..4291952b3fcaac300acb28f462744e1787dc5250 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -358,6 +358,16 @@ public:
   void cutoff(const string &value);
   //! mfs option of model block
   void mfs(const string &value);
+  //! the flags to substitute for the default compiler flags used by `use_dll`
+  void compilation_setup_substitute_flags(const string & flags);
+  //! the flags to add to the default compiler flags used by `use_dll`
+  void compilation_setup_add_flags(const string & flags);
+  //! the libs to substitute for the default compiler libs used by `use_dll`
+  void compilation_setup_substitute_libs(const string & libs);
+  //! the libs to add to the default compiler libs used by `use_dll`
+  void compilation_setup_add_libs(const string & libs);
+  //! the compiler to replace the default compiler used by `use_dll`
+  void compilation_setup_compiler(const string & path);
   //! balanced_growth_test_tol option of model block
   void balanced_growth_test_tol(const string &value);
   //! Sets the FILENAME for the initial value in initval
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 2c82876fb11f070461e1e7068e229ba89e82983b..9b7a0263bb3496dd197c5288369829d27ef9b071 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -195,6 +195,12 @@ StaticModel::StaticModel(const DynamicModel &m) :
   // Convert auxiliary equations
   for (auto aux_eq : m.aux_equations)
     addAuxEquation(aux_eq->toStatic(*this));
+
+  user_set_add_flags = m.user_set_add_flags;
+  user_set_subst_flags = m.user_set_subst_flags;
+  user_set_add_libs = m.user_set_add_libs;
+  user_set_subst_libs = m.user_set_subst_libs;
+  user_set_compiler = m.user_set_compiler;
 }
 
 void