Skip to content
Snippets Groups Projects
Verified Commit 1fc3d5fe authored by Willi Mutschler's avatar Willi Mutschler Committed by Sébastien Villemot
Browse files

macOS: use clang if GCC is not available for use_dll

parent e1e1a753
No related branches found
No related tags found
No related merge requests found
Pipeline #8801 passed
...@@ -1613,34 +1613,40 @@ ModelTree::matlab_arch(const string &mexext) ...@@ -1613,34 +1613,40 @@ ModelTree::matlab_arch(const string &mexext)
} }
#ifdef __APPLE__ #ifdef __APPLE__
filesystem::path
ModelTree::findGccOnMacos(const string &mexext) 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 switches between x86_64 and arm64
const string macos_gcc_version {"13"}; const string macos_gcc_version {"13"};
char dynare_preprocessor_path[PATH_MAX];
uint32_t size = PATH_MAX;
filesystem::path 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 user did not choose to install gcc locally via the pkg-installer then we need to find GNU gcc if (filesystem::path global_gcc_path {"/usr/local/bin/gcc-" + macos_gcc_version};
// homebrew binaries are located in /usr/local/bin/ on x86_64 systems and in /opt/homebrew/bin/ on arm64 systems exists(global_gcc_path) && mexext == "mexmaci64")
if (exists(local_gcc_path)) return { global_gcc_path, false };
return local_gcc_path;
else if (filesystem::path global_gcc_path {"/usr/local/bin/gcc-" + macos_gcc_version};
exists(global_gcc_path) && mexext == "mexmaci64")
return global_gcc_path;
else if (filesystem::path global_gcc_path {"/opt/homebrew/bin/gcc-" + macos_gcc_version}; else if (filesystem::path global_gcc_path {"/opt/homebrew/bin/gcc-" + macos_gcc_version};
exists(global_gcc_path) && mexext == "mexmaca64") exists(global_gcc_path) && mexext == "mexmaca64")
return global_gcc_path; 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 else
{ {
const string brew_message {
[&mexext]()
{
if (mexext == "mexmaca64")
return "Homebrew for arm64";
else if (mexext == "mexmaci64")
return "Homebrew for x86_64";
else
return "Homebrew"; // Fallback message if mexext doesn't match
}()
};
cerr << "ERROR: You must install gcc-" << macos_gcc_version cerr << "ERROR: You must install gcc-" << macos_gcc_version
<< " on your system before using the `use_dll` option of Dynare. " << " 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 " << brew_message << " and run `brew install gcc-" << macos_gcc_version << "` in a terminal." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -1651,7 +1657,9 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b ...@@ -1651,7 +1657,9 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
{ {
assert(!mex_compilation_workers.empty()); assert(!mex_compilation_workers.empty());
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" };
string opt_flags { gcc_opt_flags }; // Will be modified if we end up using Clang
filesystem::path compiler; filesystem::path compiler;
ostringstream flags; ostringstream flags;
...@@ -1692,7 +1700,9 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b ...@@ -1692,7 +1700,9 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
#ifdef __APPLE__ #ifdef __APPLE__
else if (mexext == "mexmaci64" || mexext == "mexmaca64") else if (mexext == "mexmaci64" || mexext == "mexmaca64")
{ {
compiler = findGccOnMacos(mexext); auto [compiler, is_clang] = findCompilerOnMacos(mexext);
if (is_clang)
opt_flags = clang_opt_flags;
flags << " -fno-common -Wl,-twolevel_namespace -undefined error -bundle"; flags << " -fno-common -Wl,-twolevel_namespace -undefined error -bundle";
libs += " -lm"; libs += " -lm";
} }
...@@ -1970,16 +1980,17 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers, const filesystem::pat ...@@ -1970,16 +1980,17 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers, const filesystem::pat
#ifdef __APPLE__ #ifdef __APPLE__
else if (mexext == "mex") else if (mexext == "mex")
{ {
/* On macOS, with Octave, enforce GCC, otherwise Clang will be used, and /* 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 our custom optimization flags (see dynare#1797) */ it does not accept our custom optimization flags (see dynare#1797) */
filesystem::path gcc_path {findGccOnMacos(mexext)}; auto [compiler_path, is_clang] { findCompilerOnMacos(mexext) };
if (setenv("CC", gcc_path.c_str(), 1) != 0) if (setenv("CC", compiler_path.c_str(), 1) != 0)
{ {
cerr << "Can't set CC environment variable" << endl; cerr << "Can't set CC environment variable" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// We also define CXX, because that is used for linking // 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; cerr << "Can't set CXX environment variable" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
......
...@@ -594,8 +594,9 @@ private: ...@@ -594,8 +594,9 @@ private:
//! Returns the name of the MATLAB architecture given the extension used for MEX files //! Returns the name of the MATLAB architecture given the extension used for MEX files
static string matlab_arch(const string &mexext); static string matlab_arch(const string &mexext);
#ifdef __APPLE__ #ifdef __APPLE__
//! Finds a suitable GCC compiler on macOS /* Finds a suitable compiler on macOS.
static filesystem::path findGccOnMacos(const string &mexext); The boolean is false if this is GCC and true if this is Clang */
static pair<filesystem::path, bool> findCompilerOnMacos(const string &mexext);
#endif #endif
/* Compiles a MEX file (if link=true) or an object file to be linked later /* Compiles a MEX file (if link=true) or an object file to be linked later
into a MEX file (if link=false). The compilation is done in separate into a MEX file (if link=false). The compilation is done in separate
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment