diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index 72d669f4fd0438ad098d873bf547bac0caea16a5..3368a963d536ae92f8d78d448d2265b183c5ee25 100644 --- a/src/ComputingTasks.cc +++ b/src/ComputingTasks.cc @@ -2174,7 +2174,7 @@ PlannerObjectiveStatement::computingPass() void PlannerObjectiveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const { - model_tree.writeStaticFile(basename + ".objective", false, false, false, false); + model_tree.writeStaticFile(basename + ".objective", false, false, false, "", {}, {}, false); } void diff --git a/src/DataTree.cc b/src/DataTree.cc index 78947a0d2401501fa4d5b5ab1ef47fc481c2474e..2b713a81848649f998c49be10b5c645c580719db 100644 --- a/src/DataTree.cc +++ b/src/DataTree.cc @@ -829,51 +829,6 @@ DataTree::writePowerDeriv(ostream &output) const << "}" << endl; } -void -DataTree::writeNormcdfCHeader(ostream &output) const -{ -#if defined(_WIN32) || defined(__CYGWIN32__) - if (isTrinaryOpUsed(TrinaryOpcode::normcdf)) - output << "#ifdef _MSC_VER" << endl - << "double normcdf(double);" << endl - << "#endif" << endl; -#endif -} - -void -DataTree::writeNormcdf(ostream &output) const -{ -#if defined(_WIN32) || defined(__CYGWIN32__) - if (isTrinaryOpUsed(TrinaryOpcode::normcdf)) - output << endl - << "#ifdef _MSC_VER" << endl - << "/*" << endl - << " * Define normcdf for MSVC compiler" << endl - << " */" << endl - << "double normcdf(double x)" << endl - << "{" << endl - << "#if _MSC_VER >= 1700" << endl - << " return 0.5 * erfc(-x * M_SQRT1_2);" << endl - << "#else" << endl - << " // From http://www.johndcook.com/blog/cpp_phi" << endl - << " double a1 = 0.254829592;" << endl - << " double a2 = -0.284496736;" << endl - << " double a3 = 1.421413741;" << endl - << " double a4 = -1.453152027;" << endl - << " double a5 = 1.061405429;" << endl - << " double p = 0.3275911;" << endl - << " int sign = (x < 0) ? -1 : 1;" << endl - << " x = fabs(x)/sqrt(2.0);" << endl - << " // From the Handbook of Mathematical Functions by Abramowitz and Stegun, formula 7.1.26" << endl - << " double t = 1.0/(1.0 + p*x);" << endl - << " double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);" << endl - << " return 0.5*(1.0 + sign*y);" << endl - << "#endif" << endl - << "}" << endl - << "#endif" << endl; -#endif -} - string DataTree::packageDir(const string &package) { diff --git a/src/DataTree.hh b/src/DataTree.hh index bc86662bfcdfb34b09b234f7fe25e04c89527f98..1b3453f50468a94a1c7524d4786eed28282d0339 100644 --- a/src/DataTree.hh +++ b/src/DataTree.hh @@ -276,10 +276,6 @@ public: void writePowerDerivCHeader(ostream &output) const; //! Write getPowerDeriv in C void writePowerDeriv(ostream &output) const; - //! Write the C Header for normcdf when use_dll is used - void writeNormcdfCHeader(ostream &output) const; - //! Write normcdf in C - void writeNormcdf(ostream &output) const; //! Thrown when trying to access an unknown variable by deriv_id class UnknownDerivIDException { diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 81ae7133da33236ae19fddba0c43abc2932d100e..912f261e43fd8c00cd6fad7eda2d0e5595e50e2f 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -27,8 +27,6 @@ #include <iterator> #include <numeric> -#include <boost/filesystem.hpp> - #include "DynamicModel.hh" void @@ -1738,11 +1736,6 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const << " * Warning : this file is generated automatically by Dynare" << endl << " * from model file (.mod)" << endl << " */" << endl -#if defined(_WIN32) || defined(__CYGWIN32__) - << "#ifdef _MSC_VER" << endl - << "#define _USE_MATH_DEFINES" << endl - << "#endif" << endl -#endif << "#include <math.h>" << endl; if (external_functions_table.get_total_number_of_unique_model_block_external_functions()) @@ -1756,7 +1749,6 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const // Write function definition if BinaryOpcode::powerDeriv is used writePowerDerivCHeader(mDynamicModelFile); - writeNormcdfCHeader(mDynamicModelFile); mDynamicModelFile << endl; @@ -1766,7 +1758,6 @@ DynamicModel::writeDynamicCFile(const string &basename, const int order) const mDynamicModelFile << endl; writePowerDeriv(mDynamicModelFile); - writeNormcdf(mDynamicModelFile); mDynamicModelFile.close(); mDynamicMexFile.open(filename_mex, ios::out | ios::binary); @@ -4920,7 +4911,7 @@ DynamicModel::collectBlockVariables() } void -DynamicModel::writeDynamicFile(const string &basename, bool block, bool linear_decomposition, bool bytecode, bool use_dll, int order, bool julia) const +DynamicModel::writeDynamicFile(const string &basename, bool block, bool linear_decomposition, bool bytecode, bool use_dll, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot, int order, bool julia) const { if (block && bytecode) writeModelEquationsCode_Block(basename, map_idx, linear_decomposition); @@ -4933,7 +4924,10 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool linear_d else if (block && !bytecode) writeSparseDynamicMFile(basename); else if (use_dll) - writeDynamicCFile(basename, order); + { + writeDynamicCFile(basename, order); + compileDll(basename, "dynamic", mexext, matlabroot, dynareroot); + } else if (julia) writeDynamicJuliaFile(basename); else diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 9e1b553a10172c6ca689435794f13410929e3105..341221c711f14ad869a67619a3dbb2252d4ecb6a 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -23,6 +23,8 @@ using namespace std; #include <fstream> + +#include <boost/filesystem.hpp> #include <boost/crc.hpp> #include "StaticModel.hh" @@ -359,7 +361,7 @@ public: void Write_Inf_To_Bin_File_Block(const string &basename, const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries, const bool linear_decomposition) const; //! Writes dynamic model file - void writeDynamicFile(const string &basename, bool block, bool linear_decomposition, bool bytecode, bool use_dll, int order, bool julia) const; + void writeDynamicFile(const string &basename, bool block, bool linear_decomposition, bool bytecode, bool use_dll, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot, int order, bool julia) const; //! Writes file containing parameters derivatives void writeParamsDerivativesFile(const string &basename, bool julia) const; diff --git a/src/DynareMain.cc b/src/DynareMain.cc index 3f17bc01355e23c0b4aeaf61382f16c9bd8b26da..6aff26d38809778334acdb6214ffcab42340b1c1 100644 --- a/src/DynareMain.cc +++ b/src/DynareMain.cc @@ -28,6 +28,9 @@ #endif #include <unistd.h> + +#include <boost/filesystem.hpp> + #include "ParsingDriver.hh" #include "ExtendedPreprocessorTypes.hh" #include "ConfigFile.hh" @@ -41,13 +44,10 @@ void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file, WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes, bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode, - LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops -#if defined(_WIN32) || defined(__CYGWIN32__) - , bool cygwin, bool msvc, bool mingw -#endif - , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple - , bool nopreprocessoroutput - ); + LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops, + JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple, + bool nopreprocessoroutput, const string &mexext, const boost::filesystem::path &matlabroot, + const boost::filesystem::path &dynareroot); void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file, bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream ¯o_output); @@ -59,10 +59,8 @@ usage() << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]" << " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=julia]" << " [params_derivs_order=0|1|2] [transform_unary_ops]" -#if defined(_WIN32) || defined(__CYGWIN32__) - << " [cygwin] [msvc] [mingw]" -#endif << " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]" + << " [dll=matlab|octave] [matlabroot=path]" << endl; exit(EXIT_FAILURE); } @@ -99,11 +97,6 @@ main(int argc, char **argv) bool console = false; bool nograph = false; bool nointeractive = false; -#if defined(_WIN32) || defined(__CYGWIN32__) - bool cygwin = false; - bool msvc = false; - bool mingw = false; -#endif string parallel_config_file; bool parallel = false; string cluster_name; @@ -124,6 +117,11 @@ main(int argc, char **argv) bool jsonderivsimple = false; LanguageOutputType language{LanguageOutputType::matlab}; bool nopreprocessoroutput = false; + string mexext; + boost::filesystem::path matlabroot; + boost::filesystem::path dynareroot{argv[0]}; + dynareroot = dynareroot.parent_path(); + dynareroot = dynareroot / ".." / ".."; // Parse options for (int arg = 2; arg < argc; arg++) @@ -180,14 +178,6 @@ main(int argc, char **argv) nograph = true; else if (!strcmp(argv[arg], "nointeractive")) nointeractive = true; -#if defined(_WIN32) || defined(__CYGWIN32__) - else if (!strcmp(argv[arg], "cygwin")) - cygwin = true; - else if (!strcmp(argv[arg], "msvc")) - msvc = true; - else if (!strcmp(argv[arg], "mingw")) - mingw = true; -#endif else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "conffile", 8)) { if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=') @@ -332,6 +322,28 @@ main(int argc, char **argv) usage(); } } + else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "mexext", 6)) + { + string s{argv[arg]}; + if (s.length() <= 7 || s.at(6) != '=') + { + cerr << "Incorrect syntax for mexext option" << endl; + usage(); + } + s.erase(0, 7); + mexext = s; + } + else if (strlen(argv[arg]) >= 10 && !strncmp(argv[arg], "matlabroot", 10)) + { + string s{argv[arg]}; + if (s.length() <= 11 || s.at(10) != '=') + { + cerr << "Incorrect syntax for matlabroot option" << endl; + usage(); + } + s.erase(0, 11); + matlabroot = boost::filesystem::path{s}; + } else { cerr << "Unknown option: " << argv[arg] << endl; @@ -400,12 +412,9 @@ main(int argc, char **argv) main2(macro_output, basename, debug, clear_all, clear_global, no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive, parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace, - compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops -#if defined(_WIN32) || defined(__CYGWIN32__) - , cygwin, msvc, mingw -#endif - , json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput - ); + compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops, + json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput, + mexext, matlabroot, dynareroot); return EXIT_SUCCESS; } diff --git a/src/DynareMain2.cc b/src/DynareMain2.cc index 9958aa42f4b24686e597baa5a62503877082c1dc..3d7b6dc610ce8aa7b715a1775b5d0928bec622cc 100644 --- a/src/DynareMain2.cc +++ b/src/DynareMain2.cc @@ -32,13 +32,10 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file, WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes, bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode, - LanguageOutputType language, int params_derivs_order, bool transform_unary_ops -#if defined(_WIN32) || defined(__CYGWIN32__) - , bool cygwin, bool msvc, bool mingw -#endif - , JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple - , bool nopreprocessoroutput - ) + LanguageOutputType language, int params_derivs_order, bool transform_unary_ops, + JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple, + bool nopreprocessoroutput, const string &mexext, const boost::filesystem::path &matlabroot, + const boost::filesystem::path &dynareroot) { ParsingDriver p(warnings, nostrict); @@ -72,12 +69,8 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear mod_file->writeExternalFiles(basename, output_mode, language, nopreprocessoroutput); else mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph, - nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs -#if defined(_WIN32) || defined(__CYGWIN32__) - , cygwin, msvc, mingw -#endif - , nopreprocessoroutput - ); + nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs, + nopreprocessoroutput, mexext, matlabroot, dynareroot); if (!nopreprocessoroutput) cout << "Preprocessing completed." << endl; diff --git a/src/ModFile.cc b/src/ModFile.cc index 6ff0b55a47e48efb0a3a2d3ecdf981584f15fc3b..9881d8633fa9cf2d772138ce0bb129b5939de4f7 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -789,12 +789,10 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri 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, - bool check_model_changes, bool minimal_workspace, bool compute_xrefs -#if defined(_WIN32) || defined(__CYGWIN32__) - , bool cygwin, bool msvc, bool mingw -#endif - , const bool nopreprocessoroutput - ) const + bool check_model_changes, bool minimal_workspace, bool compute_xrefs, + const bool nopreprocessoroutput, const string &mexext, + const boost::filesystem::path &matlabroot, + const boost::filesystem::path &dynareroot) const { bool hasModelChanged = !dynamic_model.isChecksumMatching(basename, block); if (!check_model_changes) @@ -955,32 +953,6 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo << " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl << "end" << endl; - // 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 << "', " << !check_model_changes << ")" << endl; - else if (cygwin) - // MATLAB/Windows + Cygwin g++ - mOutputFile << "dyn_mex('cygwin', '" << basename << "', " << !check_model_changes << ")" << endl; - else if (mingw) - // MATLAB/Windows + MinGW g++ - mOutputFile << "dyn_mex('mingw', '" << basename << "', " << !check_model_changes << ")" << endl; - else - mOutputFile << "if isoctave" << endl - << " dyn_mex('', '" << basename << "', " << !check_model_changes << ")" << endl - << "else" << endl - << " error('When using the USE_DLL option on Matlab, you must give the ''cygwin'', ''msvc'', or ''mingw'' option to the ''dynare'' command')" << endl - << "end" << endl; -#else - // other configurations - mOutputFile << "dyn_mex('', '" << basename << "', " << !check_model_changes << ")" << endl; -#endif - } - mOutputFile << "M_.orig_eq_nbr = " << mod_file_struct.orig_eq_nbr << ";" << endl << "M_.eq_nbr = " << dynamic_model.equation_number() << ";" << endl << "M_.ramsey_eq_nbr = " << mod_file_struct.ramsey_eq_nbr << ";" << endl @@ -1060,17 +1032,17 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo { if (!no_static) { - static_model.writeStaticFile(basename, block, byte_code, use_dll, false); + static_model.writeStaticFile(basename, block, byte_code, use_dll, mexext, matlabroot, dynareroot, false); static_model.writeParamsDerivativesFile(basename, false); } if (linear_decomposition) { - non_linear_equations_dynamic_model.writeDynamicFile(basename, block, linear_decomposition, byte_code, use_dll, mod_file_struct.order_option, false); + non_linear_equations_dynamic_model.writeDynamicFile(basename, block, linear_decomposition, byte_code, use_dll, mexext, matlabroot, dynareroot, mod_file_struct.order_option, false); non_linear_equations_dynamic_model.writeParamsDerivativesFile(basename, false); } - dynamic_model.writeDynamicFile(basename, block, false, byte_code, use_dll, mod_file_struct.order_option, false); + dynamic_model.writeDynamicFile(basename, block, false, byte_code, use_dll, mexext, matlabroot, dynareroot, mod_file_struct.order_option, false); dynamic_model.writeParamsDerivativesFile(basename, false); } @@ -1189,11 +1161,11 @@ ModFile::writeExternalFilesJulia(const string &basename, FileOutputType output, mod_file_struct.estimation_present, false, true); if (!no_static) { - static_model.writeStaticFile(basename, false, false, false, true); + static_model.writeStaticFile(basename, false, false, false, "", {}, {}, true); static_model.writeParamsDerivativesFile(basename, true); } dynamic_model.writeDynamicFile(basename, block, linear_decomposition, byte_code, use_dll, - mod_file_struct.order_option, true); + "", {}, {}, mod_file_struct.order_option, true); dynamic_model.writeParamsDerivativesFile(basename, true); } steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present, true); diff --git a/src/ModFile.hh b/src/ModFile.hh index 04e8cdbe59a787696c2ea26cf131ae47d2260d77..22a27a4c04eb7aa183168494ce64d786c5cb6826 100644 --- a/src/ModFile.hh +++ b/src/ModFile.hh @@ -162,12 +162,8 @@ public: */ 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, bool minimal_workspace, bool compute_xrefs -#if defined(_WIN32) || defined(__CYGWIN32__) - , bool cygwin, bool msvc, bool mingw -#endif - , const bool nopreprocessoroutput - ) const; + bool check_model_changes, bool minimal_workspace, bool compute_xrefs, + const bool nopreprocessoroutput, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot) const; void writeExternalFiles(const string &basename, FileOutputType output, LanguageOutputType language, const bool nopreprocessoroutput) const; void writeExternalFilesJulia(const string &basename, FileOutputType output, const bool nopreprocessoroutput) const; diff --git a/src/ModelTree.cc b/src/ModelTree.cc index a5fa1196acd187377c35efeebd61636037950f99..4e3d29593aac4d9d5984904b6a89657b8e126339 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -2308,3 +2308,115 @@ ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const } output << endl << "]" << endl; } + +string +ModelTree::matlab_arch(const string &mexext) +{ + if (mexext == "mexglx") + return "glnx86"; + else if (mexext == "mexa64") + return "glnxa64"; + if (mexext == "mexw32") + return "win32"; + else if (mexext == "mexw64") + return "win64"; + else if (mexext == "mexmaci") + return "maci"; + else if (mexext == "mexmaci64") + return "maci64"; + else + { + cerr << "ERROR: 'mexext' option to preprocessor incorrectly set, needed with 'use_dll'" << endl; + exit(EXIT_FAILURE); + } +} + +void +ModelTree::compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot) +{ + 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"; + + boost::filesystem::path compiler; + ostringstream flags; + string libs; + + if (mexext == "mex") + { + // Octave + compiler = matlabroot / "bin" / "mkoctfile"; + flags << "--mex"; + } + else + { + // MATLAB + compiler = "gcc"; + string arch = matlab_arch(mexext); + auto include_dir = matlabroot / "extern" / "include"; + flags << "-I " << include_dir; + auto bin_dir = matlabroot / "bin" / arch; + flags << " -L " << bin_dir; + flags << " -fexceptions -DNDEBUG"; + libs = "-lmex -lmx -lmat -lmwlapack -lmwblas"; + if (mexext == "mexglx" || mexext == "mexa64") + { + // GNU/Linux + flags << " -D_GNU_SOURCE -fPIC -pthread" + << " -shared -Wl,--no-undefined -Wl,-rpath-link," << bin_dir; + libs += " -lm -lstdc++"; + + if (mexext == "mexglx") + flags << " -D_FILE_OFFSET_BITS=64 -m32"; + else + flags << " -fno-omit-frame-pointer"; + } + else if (mexext == "mexw32" || mexext == "mexw64") + { + // Windows + flags << " -static-libgcc -static-libstdc++ -shared"; + // Put the MinGW environment shipped with Dynare in the path + boost::filesystem::path mingwpath = dynareroot / (string{"mingw"} + (mexext == "mexw32" ? "32" : "64")) / "bin"; + string newpath = "PATH=" + mingwpath.string() + ';' + string{getenv("PATH")}; + if (putenv(const_cast<char *>(newpath.c_str())) != 0) + { + cerr << "Can't set PATH" << endl; + exit(EXIT_FAILURE); + } + } + else + { + // macOS + string archs = (mexext == "maci" ? "i386" : "x86_64"); + flags << " -fno-common -arch " << archs << " -mmacosx-version-min=10.7 -Wl,-twolevel_namespace -undefined error -bundle"; + libs += " -lm -lstdc++"; + } + } + + auto model_dir = boost::filesystem::path{basename} / "model" / "src"; + boost::filesystem::path main_src{model_dir / (static_or_dynamic + ".c")}, + mex_src{model_dir / (static_or_dynamic + "_mex.c")}; + + boost::filesystem::path mex_dir{"+" + basename}; + boost::filesystem::path binary{mex_dir / (static_or_dynamic + "." + mexext)}; + + ostringstream cmd; + +#ifdef _WIN32 + /* On Windows, system() hands the command over to "cmd.exe /C". We need to + enclose the whole command line within double quotes if we want the inner + 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; + +#ifdef _WIN32 + cmd << '"'; +#endif + + cout << "Compiling " << static_or_dynamic << " MEX..." << endl << cmd.str() << endl; + + if (system(cmd.str().c_str())) + { + cerr << "Compilation failed" << endl; + exit(EXIT_FAILURE); + } +} diff --git a/src/ModelTree.hh b/src/ModelTree.hh index e335e5d7fef39ed83c7146b3bc31781deab095e2..ccf27a40a6d6ab4404f0ea214ed9c17b4ae0bb54 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -29,6 +29,8 @@ using namespace std; #include <ostream> #include <array> +#include <boost/filesystem.hpp> + #include "DataTree.hh" #include "ExtendedPreprocessorTypes.hh" @@ -338,6 +340,10 @@ private: /*! Copies all the structures that contain ExprNode*, by the converting the pointers into their equivalent in the new tree */ void copyHelper(const ModelTree &m); + //! 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 boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot); public: ModelTree(SymbolTable &symbol_table_arg, diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 549dfe0bd4ff4a24717abf447159982efdd6e347..80851ee9c9014d994ee898d87392c68dd9f3a08e 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -25,8 +25,6 @@ #include <cerrno> #include <algorithm> -#include <boost/filesystem.hpp> - #include "StaticModel.hh" #include "DynamicModel.hh" @@ -2061,11 +2059,6 @@ StaticModel::writeStaticCFile(const string &basename) const << " * Warning : this file is generated automatically by Dynare" << endl << " * from model file (.mod)" << endl << endl << " */" << endl -#if defined(_WIN32) || defined(__CYGWIN32__) - << "#ifdef _MSC_VER" << endl - << "#define _USE_MATH_DEFINES" << endl - << "#endif" << endl -#endif << "#include <math.h>" << endl; if (external_functions_table.get_total_number_of_unique_model_block_external_functions()) @@ -2079,7 +2072,6 @@ StaticModel::writeStaticCFile(const string &basename) const // Write function definition if BinaryOpcode::powerDeriv is used writePowerDerivCHeader(output); - writeNormcdfCHeader(output); output << endl; @@ -2089,7 +2081,6 @@ StaticModel::writeStaticCFile(const string &basename) const output << endl; writePowerDeriv(output); - writeNormcdf(output); output.close(); output.open(filename_mex, ios::out | ios::binary); @@ -2174,7 +2165,7 @@ StaticModel::writeStaticJuliaFile(const string &basename) const } void -StaticModel::writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, bool julia) const +StaticModel::writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot, bool julia) const { if (block && bytecode) writeModelEquationsCode_Block(basename, map_idx, map_idx2); @@ -2186,7 +2177,10 @@ StaticModel::writeStaticFile(const string &basename, bool block, bool bytecode, writeStaticBlockMFSFile(basename); } else if (use_dll) - writeStaticCFile(basename); + { + writeStaticCFile(basename); + compileDll(basename, "static", mexext, matlabroot, dynareroot); + } else if (julia) writeStaticJuliaFile(basename); else diff --git a/src/StaticModel.hh b/src/StaticModel.hh index b7d6aba30c0f17802de89c5af121a7e51b3cde34..28d4ad87c9d0691bcc31225e1a59864a3e7285f0 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -24,6 +24,8 @@ using namespace std; #include <fstream> +#include <boost/filesystem.hpp> + #include "ModelTree.hh" class DynamicModel; @@ -201,7 +203,7 @@ public: int &u_count_int, bool &file_open) const; //! Writes static model file - void writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, bool julia) const; + void writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot, bool julia) const; //! Write JSON Output (used by PlannerObjectiveStatement) void writeJsonOutput(ostream &output) const;