From fb8406ef0a423e2c76fe1a67cdf637718319c619 Mon Sep 17 00:00:00 2001
From: sebastien <sebastien@ac1d8469-bf42-47a9-8791-bf33cf982152>
Date: Fri, 11 Dec 2009 14:46:21 +0000
Subject: [PATCH] USE_DLL option now works with MSVC + Added new options for
 Windows to 'dynare' command, to select the compiler: 'cygwin' and 'msvc' +
 Added the mexopts.bat for Cygwin in the SVN

git-svn-id: https://www.dynare.org/svn/dynare/trunk@3223 ac1d8469-bf42-47a9-8791-bf33cf982152
---
 .../k_order_perturbation/dynamic_dll.cpp      |  6 ++-
 preprocessor/DynareMain.cc                    | 28 +++++++++--
 preprocessor/DynareMain2.cc                   | 15 ++++--
 preprocessor/ModFile.cc                       | 35 ++++++++++----
 preprocessor/ModFile.hh                       |  7 ++-
 windows/dynare.nsi                            |  2 +-
 windows/mexopts.bat                           | 46 +++++++++++++++++++
 7 files changed, 119 insertions(+), 20 deletions(-)
 create mode 100644 windows/mexopts.bat

diff --git a/mex/sources/k_order_perturbation/dynamic_dll.cpp b/mex/sources/k_order_perturbation/dynamic_dll.cpp
index 70ec66d9c3..781225f2ef 100644
--- a/mex/sources/k_order_perturbation/dynamic_dll.cpp
+++ b/mex/sources/k_order_perturbation/dynamic_dll.cpp
@@ -44,7 +44,10 @@ DynamicModelDLL::DynamicModelDLL(const string &modName, const int y_length, cons
         throw 1;
       Dynamic = (DynamicFn)GetProcAddress(dynamicHinstance, "Dynamic");
       if (Dynamic == NULL)
-	throw 2;
+	{
+	  FreeLibrary(dynamicHinstance); // Free the library
+	  throw 2;
+	}
 #else // Linux or Mac
       dynamicHinstance = dlopen(fName.c_str(), RTLD_NOW);
       if ((dynamicHinstance == NULL) || dlerror())
@@ -55,6 +58,7 @@ DynamicModelDLL::DynamicModelDLL(const string &modName, const int y_length, cons
       Dynamic = (DynamicFn) dlsym(dynamicHinstance, "Dynamic");
       if ((Dynamic  == NULL) || dlerror())
         {
+	  dlclose(dynamicHinstance); // Free the library
           cerr << dlerror() << endl;
           throw 2;
         }
diff --git a/preprocessor/DynareMain.cc b/preprocessor/DynareMain.cc
index c5c2365748..f2f9bf573a 100644
--- a/preprocessor/DynareMain.cc
+++ b/preprocessor/DynareMain.cc
@@ -34,12 +34,20 @@ using namespace std;
    Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
    included simultaneously (because of Bison limitations).
 */
-void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit);
+void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit
+#if defined(_WIN32) || defined(__CYGWIN32__)
+	   , bool cygwin, bool msvc
+#endif
+	   );
 
 void
 usage()
 {
-  cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [warn_uninit]" << endl;
+  cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [warn_uninit]"
+#if defined(_WIN32) || defined(__CYGWIN32__)
+       << " [cygwin] [msvc]"
+#endif
+       << endl;
   exit(EXIT_FAILURE);
 }
 
@@ -60,6 +68,10 @@ main(int argc, char** argv)
   bool only_macro = false;
   bool no_line_macro = false;
   bool warn_uninit = false;
+#if defined(_WIN32) || defined(__CYGWIN32__)
+  bool cygwin = false;
+  bool msvc = false;
+#endif
 
   // Parse options
   for (int arg = 2; arg < argc; arg++)
@@ -89,6 +101,12 @@ main(int argc, char** argv)
         no_tmp_terms = true;
       else if (!strcmp(argv[arg], "warn_uninit"))
         warn_uninit = true;
+#if defined(_WIN32) || defined(__CYGWIN32__)
+      else if (!strcmp(argv[arg], "cygwin"))
+        cygwin = true;
+      else if (!strcmp(argv[arg], "msvc"))
+        msvc = true;
+#endif
       else
         {
           cerr << "Unknown option: " << argv[arg] << endl;
@@ -128,7 +146,11 @@ main(int argc, char** argv)
     return EXIT_SUCCESS;
 
   // Do the rest
-  main2(macro_output, basename, debug, clear_all, no_tmp_terms, warn_uninit);
+  main2(macro_output, basename, debug, clear_all, no_tmp_terms, warn_uninit,
+#if defined(_WIN32) || defined(__CYGWIN32__)
+	cygwin, msvc
+#endif
+	);
 
   return EXIT_SUCCESS;
 }
diff --git a/preprocessor/DynareMain2.cc b/preprocessor/DynareMain2.cc
index b6dc438dd0..fed8ed98d1 100644
--- a/preprocessor/DynareMain2.cc
+++ b/preprocessor/DynareMain2.cc
@@ -25,8 +25,11 @@ using namespace std;
 #include "ModFile.hh"
 
 void
-main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms,
-      bool warn_uninit)
+main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit
+#if defined(_WIN32) || defined(__CYGWIN32__)
+      , bool cygwin, bool msvc
+#endif
+      )
 {
   ParsingDriver p;
 
@@ -46,10 +49,14 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tm
   mod_file->computingPass(no_tmp_terms);
 
   // Write outputs
-  mod_file->writeOutputFiles(basename, clear_all);
+  mod_file->writeOutputFiles(basename, clear_all
+#if defined(_WIN32) || defined(__CYGWIN32__)
+			     , cygwin, msvc
+#endif
+			     );
 
   delete mod_file;
 
   cout << "Preprocessing completed." << endl
-       << "Starting Matlab computing ..." << endl;
+       << "Starting MATLAB/Octave computing." << endl;
 }
diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc
index e3349675a6..eca9e5ae1d 100644
--- a/preprocessor/ModFile.cc
+++ b/preprocessor/ModFile.cc
@@ -225,7 +225,11 @@ ModFile::computingPass(bool no_tmp_terms)
 }
 
 void
-ModFile::writeOutputFiles(const string &basename, bool clear_all) const
+ModFile::writeOutputFiles(const string &basename, bool clear_all
+#if defined(_WIN32) || defined(__CYGWIN32__)
+			  , bool cygwin, bool msvc
+#endif
+) const
 {
   ofstream mOutputFile;
   bool dynamic_model_needed = mod_file_struct.simul_present || mod_file_struct.check_present || mod_file_struct.stoch_simul_present
@@ -302,15 +306,26 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all) const
 
   // Compile the dynamic MEX file for use_dll option
   if (use_dll)
-    mOutputFile << "if ~exist('OCTAVE_VERSION')" << endl
-                << "  if ispc" << endl
-                << "    eval('mex -O LINKER=''echo EXPORTS > mex.def & echo mexFunction  >> mex.def & echo Dynamic >> mex.def & gcc-3'' LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_dynamic.c')" << endl // This command is enclosed in an eval(), because otherwise it will make Octave fail
-                << "  else" << endl
-                << "    eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_dynamic.c')" << endl // This command is enclosed in an eval(), because otherwise it will make Octave fail
-                << "  end" << endl
-                << "else" << endl
-                << "  mex "  << basename << "_dynamic.c" << endl
-                << "end" << endl;
+    {
+      mOutputFile << "if ~exist('OCTAVE_VERSION')" << endl;
+      // Some mex commands are enclosed in an eval(), because otherwise it will make Octave fail
+#if defined(_WIN32) || defined(__CYGWIN32__)
+      if (msvc)
+	mOutputFile << "    eval('mex -O LINKFLAGS=\"$LINKFLAGS /export:Dynamic\" " << basename << "_dynamic.c')" << endl; // MATLAB/Windows + Microsoft Visual C++
+      else if (cygwin)
+	mOutputFile << "    eval('mex -O PRELINK_CMDS1=\"echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Dynamic >> mex.def\" " << basename << "_dynamic.c')" << endl;  // MATLAB/Windows + Cygwin g++
+      else
+	{
+	  cerr << "ERROR: When using the USE_DLL option, you must give either 'cygwin' or 'msvc' option to the 'dynare' command" << endl;
+	  exit(EXIT_FAILURE);
+	}
+#else
+      mOutputFile << "    eval('mex -O LDFLAGS=\"-pthread -shared -Wl,--no-undefined\" " << basename << "_dynamic.c')" << endl; // MATLAB/Linux|Mac
+#endif
+      mOutputFile << "else" << endl
+		  << "    mex "  << basename << "_dynamic.c" << endl // Octave
+		  << "end" << endl;
+    }
 
   // Add path for block option with M-files
   if (block && !byte_code)
diff --git a/preprocessor/ModFile.hh b/preprocessor/ModFile.hh
index 118b850482..e7ba4e8ddf 100644
--- a/preprocessor/ModFile.hh
+++ b/preprocessor/ModFile.hh
@@ -91,8 +91,13 @@ public:
   /*!
     \param basename The base name used for writing output files. Should be the name of the mod file without its extension
     \param clear_all Should a "clear all" instruction be written to output ?
+    \param msvc Should the MEX command of use_dll be adapted for MSVC?
   */
-  void writeOutputFiles(const string &basename, bool clear_all) const;
+  void writeOutputFiles(const string &basename, bool clear_all
+#if defined(_WIN32) || defined(__CYGWIN32__)
+			, bool cygwin, bool msvc
+#endif
+			) const;
 };
 
 #endif // ! MOD_FILE_HH
diff --git a/windows/dynare.nsi b/windows/dynare.nsi
index 4ed815f2c1..2516d69a73 100644
--- a/windows/dynare.nsi
+++ b/windows/dynare.nsi
@@ -58,7 +58,7 @@ Section "Dynare core (preprocessor and M-files)"
  SectionIn RO
 !insertmacro DETERMINE_CONTEXT
  SetOutPath $INSTDIR
- File README.txt ..\license.txt
+ File README.txt mexopts.bat ..\license.txt
 
  SetOutPath $INSTDIR\matlab
  File /r ..\matlab\*.m
diff --git a/windows/mexopts.bat b/windows/mexopts.bat
new file mode 100644
index 0000000000..7f675cbfc0
--- /dev/null
+++ b/windows/mexopts.bat
@@ -0,0 +1,46 @@
+@echo off
+rem
+rem    Compile and link options used for building MEX-files
+rem    using Cygwin.
+rem
+rem    This file makes the assumption that you installed Cygwin in
+rem    C:\CYGWIN, and that you install gcc-mingw package.
+rem
+rem    This file should be copied to:
+rem    C:\Documents and Settings\<Username>\Application Data\MathWorks\MATLAB\<MATLAB version>\
+rem
+rem    Initial version by Michel Juillard, revised by Sebastien Villemot
+rem
+
+rem ********************************************************************
+rem General parameters
+rem ********************************************************************
+
+set MATLAB=%MATLAB%
+set PATH=%PATH%;c:\cygwin\bin
+
+rem ********************************************************************
+rem Compiler parameters
+rem ********************************************************************
+set COMPILER=gcc-3
+set COMPFLAGS=-c -mno-cygwin -I"%MATLAB%\extern\include"
+set OPTIMFLAGS=-O3
+set DEBUGFLAGS=-g -Wall
+set NAME_OBJECT=-o
+set MW_TARGET_ARCH=win32
+
+rem ********************************************************************
+rem Linker parameters
+rem ********************************************************************
+set LIBLOC="%MATLAB%"\extern\lib\win32\microsoft\\
+set PRELINK_CMDS1=echo EXPORTS > mex.def & echo mexFunction >> mex.def
+set LINKER=gcc-3
+set LINKFLAGS= -mno-cygwin -shared mex.def
+set LINKFLAGSPOST= %LIBLOC%libmex.lib %LIBLOC%libmx.lib %LIBLOC%libmwlapack.lib %LIBLOC%libmwblas.lib -lstdc++
+set LINKOPTIMFLAGS=-O3
+set LINKDEBUGFLAGS= -g -Wall
+set LINK_FILE=
+set LINK_LIB=
+set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"
+set RSP_FILE_INDICATOR=@
+set POSTLINK_CMDS1=del mex.def
-- 
GitLab