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.issue#70
parent
1c33af4844
commit
4a974bb428
|
@ -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 ¯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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
112
src/ModelTree.cc
112
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue