From 530e314786cd0d0824c06c27e653b23ecddca3f6 Mon Sep 17 00:00:00 2001
From: Michel Juillard <michel.juillard@mjui.fr>
Date: Sun, 10 May 2015 20:29:03 +0200
Subject: [PATCH] adding dynare command line option 'fast' in order not to
 recompile MEX files if the lists of variables and the equations haven't
 changed between two runs of the same model file.

---
 doc/dynare.texi             |  5 +++++
 preprocessor/DynareMain.cc  |  9 ++++++---
 preprocessor/DynareMain2.cc |  9 +++++----
 preprocessor/ModFile.cc     | 16 ++++++++++------
 preprocessor/ModFile.hh     |  3 ++-
 5 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/doc/dynare.texi b/doc/dynare.texi
index 2635b82522..158850bd19 100644
--- a/doc/dynare.texi
+++ b/doc/dynare.texi
@@ -851,6 +851,11 @@ Allows Dynare to issue a warning and continue processing when
 @item there are more endogenous variables than equations
 @item an undeclared symbol is assigned in @code{initval} or @code{endval}
 @end enumerate
+
+@item fast
+Only useful with model option @code{use_dll}. Don't recompile the MEX
+files when running again the same model file and the lists of variables
+and the equations haven't changed.
 @end table
 
 @outputhead
diff --git a/preprocessor/DynareMain.cc b/preprocessor/DynareMain.cc
index 19d773b8be..9320a4afd8 100644
--- a/preprocessor/DynareMain.cc
+++ b/preprocessor/DynareMain.cc
@@ -38,7 +38,7 @@
 void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global, bool no_tmp_terms, bool no_log, bool no_warn,
            bool warn_uninit, bool console, bool nograph, bool nointeractive,
            bool parallel, const string &parallel_config_file, const string &cluster_name, bool parallel_slave_open_mode,
-           bool parallel_test, bool nostrict, FileOutputType output_mode, LanguageOutputType lang
+           bool parallel_test, bool nostrict, bool check_model_changes, FileOutputType output_mode, LanguageOutputType lang
 #if defined(_WIN32) || defined(__CYGWIN32__)
            , bool cygwin, bool msvc
 #endif
@@ -49,7 +49,7 @@ usage()
 {
   cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [nolog] [warn_uninit]"
        << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test] "
-       << " [-D<variable>[=<value>]] [nostrict] [output=dynamic|first|second|third] [language=C|C++]"
+       << " [-D<variable>[=<value>]] [nostrict] [fast] [output=dynamic|first|second|third] [language=C|C++]"
 #if defined(_WIN32) || defined(__CYGWIN32__)
        << " [cygwin] [msvc]"
 #endif
@@ -97,6 +97,7 @@ main(int argc, char **argv)
   bool parallel_slave_open_mode = false;
   bool parallel_test = false;
   bool nostrict = false;
+  bool check_model_changes = false;
   map<string, string> defines;
   FileOutputType output_mode = none;
   LanguageOutputType language = matlab;
@@ -165,6 +166,8 @@ main(int argc, char **argv)
         parallel_test = true;
       else if (!strcmp(argv[arg], "nostrict"))
         nostrict = true;
+      else if (!strcmp(argv[arg], "fast"))
+        check_model_changes = true;
       else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8))
         {
           parallel = true;
@@ -285,7 +288,7 @@ main(int argc, char **argv)
 
   // Do the rest
   main2(macro_output, basename, debug, clear_all, clear_global, no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
-        parallel, parallel_config_file, cluster_name, parallel_slave_open_mode, parallel_test, nostrict, output_mode, language
+        parallel, parallel_config_file, cluster_name, parallel_slave_open_mode, parallel_test, nostrict, check_model_changes, output_mode, language
 #if defined(_WIN32) || defined(__CYGWIN32__)
         , cygwin, msvc
 #endif
diff --git a/preprocessor/DynareMain2.cc b/preprocessor/DynareMain2.cc
index 376dd20a90..fe1c694272 100644
--- a/preprocessor/DynareMain2.cc
+++ b/preprocessor/DynareMain2.cc
@@ -27,7 +27,7 @@
 void
 main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global, bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console, bool nograph, bool nointeractive,
       bool parallel, const string &parallel_config_file, const string &cluster_name, bool parallel_slave_open_mode,
-      bool parallel_test, bool nostrict, FileOutputType output_mode, LanguageOutputType language
+      bool parallel_test, bool nostrict, bool check_model_changes, FileOutputType output_mode, LanguageOutputType language
 #if defined(_WIN32) || defined(__CYGWIN32__)
       , bool cygwin, bool msvc
 #endif
@@ -60,11 +60,12 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear
   if (output_mode != none)
     mod_file->writeExternalFiles(basename, output_mode, language);
   else
-    mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph, nointeractive, config_file
+    mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph,
+			       nointeractive, config_file, check_model_changes
 #if defined(_WIN32) || defined(__CYGWIN32__)
-                             , cygwin, msvc
+			       , cygwin, msvc
 #endif
-                             );
+			       );
 
   delete mod_file;
 
diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc
index 9f8f73f562..c6b7ca8357 100644
--- a/preprocessor/ModFile.cc
+++ b/preprocessor/ModFile.cc
@@ -526,7 +526,8 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output)
 }
 
 void
-ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn, bool console, bool nograph, bool nointeractive, const ConfigFile &config_file
+ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn, bool console, bool nograph,
+			  bool nointeractive, const ConfigFile &config_file, bool check_model_changes
 #if defined(_WIN32) || defined(__CYGWIN32__)
                           , bool cygwin, bool msvc
 #endif
@@ -650,7 +651,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
                 << "end" << endl;
 
   bool hasModelChanged = !dynamic_model.isChecksumMatching(basename);
-      
+  if (!check_model_changes)
+    hasModelChanged = true;
+  
   if (hasModelChanged)
     {
       // Erase possible remnants of previous runs
@@ -700,20 +703,21 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
 #endif
 
   // Compile the dynamic MEX file for use_dll option
+  // When check_model_changes is true, don't force compile if MEX is fresher than source
   if (use_dll)
     {
 #if defined(_WIN32) || defined(__CYGWIN32__)
       if (msvc)
         // MATLAB/Windows + Microsoft Visual C++
-	mOutputFile << "dyn_mex('msvc', '" << basename << ", 1)" <<  endl;
+	mOutputFile << "dyn_mex('msvc', '" << basename << "', " << !check_model_changes << ")" <<  endl;
       else if (cygwin)
         // MATLAB/Windows + Cygwin g++
-	mOutputFile << "dyn_mex('cygwin', '" << basename << "', 1)" << endl;
+	mOutputFile << "dyn_mex('cygwin', '" << basename << "', " << !check_model_changes << ")" << endl;
       else
         mOutputFile << "    error('When using the USE_DLL option, you must give either ''cygwin'' or ''msvc'' option to the ''dynare'' command')" << endl;
 #else
-	// other configurations
-	mOutputFile << "dyn_mex('', '" << basename << "', 1)" << endl;
+      // other configurations
+      mOutputFile << "dyn_mex('', '" << basename << "', " << !check_model_changes << ")" << endl;
 #endif
     }
 
diff --git a/preprocessor/ModFile.hh b/preprocessor/ModFile.hh
index 0a384931b2..bf36366856 100644
--- a/preprocessor/ModFile.hh
+++ b/preprocessor/ModFile.hh
@@ -145,7 +145,8 @@ public:
     \param cygwin Should the MEX command of use_dll be adapted for Cygwin?
     \param msvc Should the MEX command of use_dll be adapted for MSVC?
   */
-  void writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn, bool console, bool nograph, bool nointeractive, const ConfigFile &config_file
+  void writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn,
+			bool console, bool nograph, bool nointeractive, const ConfigFile &config_file, bool check_model_changes
 #if defined(_WIN32) || defined(__CYGWIN32__)
                         , bool cygwin, bool msvc
 #endif
-- 
GitLab