diff --git a/mex/sources/k_order_perturbation/dynamic_dll.cpp b/mex/sources/k_order_perturbation/dynamic_dll.cpp index 70ec66d9c3e265fdac4ae4ab04a5a549228a15a4..781225f2ef26e781d942a9fea8d4a1ec7604d0ed 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 c5c23657481465f405fdfcd7a54e8fd441ece78f..f2f9bf573aae21ba77a73aabf6f2b44e2d82bb2c 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 b6dc438dd07ef64738ebad1b09f787ec715aa4ce..fed8ed98d1307c32ee64f2e6fead14dc6d24454b 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 e3349675a6e09c328ea11d6bc52010ee2d24977d..eca9e5ae1db983326a5068d421a31035c98fac87 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 118b850482f6d59e3ade0ee2f83b6ec0616ff63d..e7ba4e8ddfa313d2391e8509c1549b660a667cda 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 4ed815f2c11a2946aae3c5860155b432e187070e..2516d69a73644720a149cbaabee68faaa571b0a8 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 0000000000000000000000000000000000000000..7f675cbfc04e93c35cdb4956ff948ea71afbb98a --- /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