Verified Commit 4a974bb4 authored by Sébastien Villemot's avatar Sébastien Villemot
Browse files

The preprocessor now compiles the MEX when use_dll is specified

New options "mexext" and "matlabroot" are introduced, so that the preprocessor
knows where to find MATLAB and which architecture to compile for.

Only recent gcc is now supported. A set of optimization flags is used so that
compilation goes reasonably fast on large models.

Consequently, options "msvc", "mingw" and "cygwin" have been removed.
parent 1c33af48
Pipeline #259 passed with stage
in 1 minute and 40 seconds
......@@ -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
......
......@@ -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)
{
......
......@@ -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
{
......
......@@ -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
......
......@@ -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;
......
......@@ -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 &macro_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;
}
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
}
}
......@@ -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,
......
......@@ -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
......
......@@ -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;
......