Skip to content
Snippets Groups Projects

macOS backports for arm64

3 files
+ 58
30
Compare changes
  • Side-by-side
  • Inline

Files

+ 38
26
/*
* Copyright © 2003-2021 Dynare Team
* Copyright © 2003-2023 Dynare Team
*
* This file is part of Dynare.
*
@@ -1903,6 +1903,8 @@ ModelTree::matlab_arch(const string &mexext)
}
else if (mexext == "mexmaci64")
return "maci64";
else if (mexext == "mexmaca64")
return "maca64";
else
{
cerr << "ERROR: 'mexext' option to preprocessor incorrectly set, needed with 'use_dll'" << endl;
@@ -1911,29 +1913,36 @@ ModelTree::matlab_arch(const string &mexext)
}
#ifdef __APPLE__
string
ModelTree::findGccOnMacos()
pair<filesystem::path, bool>
ModelTree::findCompilerOnMacos(const string &mexext)
{
/* Try to find gcc, otherwise use Apple’s clang compiler.
Homebrew binaries are located in /usr/local/bin/ on x86_64 systems and in
/opt/homebrew/bin/ on arm64 systems.
Apple’s clang is located both in /usr/bin/gcc and /usr/bin/clang, it
automatically selects x86_64 or arm64 depending on the compile-time
environment. */
const string macos_gcc_version {"13"};
char dynare_preprocessor_path[PATH_MAX];
uint32_t size = PATH_MAX;
string local_gcc_path;
if (_NSGetExecutablePath(dynare_preprocessor_path, &size) == 0)
{
string s = dynare_preprocessor_path;
local_gcc_path = s.substr(0, s.find_last_of("/")) + "/../.brew/bin/gcc-" + macos_gcc_version;
}
if (filesystem::exists(local_gcc_path))
return local_gcc_path;
else if (string global_gcc_path = "/usr/local/bin/gcc-" + macos_gcc_version;
filesystem::exists(global_gcc_path))
return global_gcc_path;
if (filesystem::path global_gcc_path {"/usr/local/bin/gcc-" + macos_gcc_version};
exists(global_gcc_path) && mexext == "mexmaci64")
return { global_gcc_path, false };
else if (filesystem::path global_gcc_path {"/opt/homebrew/bin/gcc-" + macos_gcc_version};
exists(global_gcc_path) && mexext == "mexmaca64")
return { global_gcc_path, false };
else if (filesystem::path global_clang_path {"/usr/bin/clang"}; exists(global_clang_path))
return { global_clang_path, true };
else
{
cerr << "ERROR: You must install gcc-" << macos_gcc_version
<< " on your system before using the `use_dll` option of Dynare. "
<< "If using MATLAB, you can do this via the Dynare installation package. If using Octave, you should run `brew install gcc-" << macos_gcc_version << "` in a terminal." << endl;
<< "You should install Homebrew";
if (mexext == "mexmaca64")
cerr << " for arm64";
else if (mexext == "mexmaci64")
cerr << " for x86_64";
cerr << " and run `brew install gcc-" << macos_gcc_version << "` in a terminal." << endl;
exit(EXIT_FAILURE);
}
}
@@ -1942,11 +1951,13 @@ ModelTree::findGccOnMacos()
void
ModelTree::compileMEX(const string &basename, const string &funcname, const string &mexext, const vector<filesystem::path> &src_files, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const
{
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";
const string gcc_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" };
const string clang_opt_flags { "-O3 -g0 --param ira-max-conflict-table-size=1 -Wno-unused-command-line-argument" };
filesystem::path compiler;
ostringstream flags;
string libs;
bool is_clang {false};
if (matlabroot.empty())
{
@@ -1960,16 +1971,17 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
compiler = matlabroot / "bin" / "mkoctfile";
flags << "--mex";
#ifdef __APPLE__
/* On macOS, enforce GCC, otherwise Clang will be used, and it does not
accept our custom optimization flags (see dynare#1797) */
string gcc_path = findGccOnMacos();
if (setenv("CC", gcc_path.c_str(), 1) != 0)
/* On macOS, with Octave, enforce our compiler. In particular this is
necessary if we’ve selected GCC; otherwise Clang will be used, and
it does not accept the same optimization flags (see dynare#1797) */
auto [compiler_path, is_clang] { findCompilerOnMacos(mexext) };
if (setenv("CC", compiler_path.c_str(), 1) != 0)
{
cerr << "Can't set CC environment variable" << endl;
exit(EXIT_FAILURE);
}
// We also define CXX, because that is used for linking
if (setenv("CXX", gcc_path.c_str(), 1) != 0)
if (setenv("CXX", compiler_path.c_str(), 1) != 0)
{
cerr << "Can't set CXX environment variable" << endl;
exit(EXIT_FAILURE);
@@ -2011,9 +2023,9 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
}
}
#ifdef __APPLE__
else if (mexext == "mexmaci64")
else if (mexext == "mexmaci64" || mexext == "mexmaca64")
{
compiler = findGccOnMacos();
tie(compiler, is_clang) = findCompilerOnMacos(mexext);
flags << " -fno-common -Wl,-twolevel_namespace -undefined error -bundle";
libs += " -lm";
}
@@ -2049,7 +2061,7 @@ ModelTree::compileMEX(const string &basename, const string &funcname, const stri
cmd << user_set_compiler << " ";
if (user_set_subst_flags.empty())
cmd << opt_flags << " " << flags.str() << " ";
cmd << (is_clang ? clang_opt_flags : gcc_opt_flags) << " " << flags.str() << " ";
else
cmd << user_set_subst_flags << " ";
Loading