From 15e3432d2333fce98ac6ed54b5372b05970e0c34 Mon Sep 17 00:00:00 2001
From: Willi Mutschler <willi@mutschler.eu>
Date: Tue, 11 Jul 2023 22:12:03 +0200
Subject: [PATCH] macOS: use clang if GCC is not available for use_dll

Related to Dynare/dynare#1893 and Dynare/dynare#1894
---
 src/ModelTree.cc | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 681d8a37..4061a162 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -1617,30 +1617,31 @@ filesystem::path
 ModelTree::findGccOnMacos(const string &mexext)
 {
   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
+  // try to find gcc, otherwise use Apple's clang compiler in /usr/bin/gcc
   // homebrew binaries are located in /usr/local/bin/ on x86_64 systems and in /opt/homebrew/bin/ on arm64 systems
-  if (exists(local_gcc_path))
-    return local_gcc_path;
-  else if (filesystem::path global_gcc_path {"/usr/local/bin/gcc-" + macos_gcc_version};
+  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};
            exists(global_gcc_path) && mexext == "mexmaca64")
     return global_gcc_path;
+  else if (filesystem::path global_gcc_path {"/usr/bin/gcc"};
+           exists(global_gcc_path) && (mexext == "mexmaca64" || mexext == "mexmaci64"))
+    return global_gcc_path;
   else
     {
+      std::string brew_message;
+      if (mexext == "mexmaca64") {
+          brew_message = "Homebrew for arm64";
+      } else if (mexext == "mexmaci64") {
+          brew_message = "Homebrew for x86_64";
+      } else {
+          brew_message = "Homebrew";  // Fallback message if mexext doesn't match
+      }
       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 " << brew_message << " and run `brew install gcc-" << macos_gcc_version << "` in a terminal." << endl;
       exit(EXIT_FAILURE);
     }
 }
@@ -1650,8 +1651,8 @@ filesystem::path
 ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_basename, const string &mexext, const vector<filesystem::path> &input_files, const filesystem::path &matlabroot, bool link) const
 {
   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";
+  // flags for gcc, might change if we switch to clang
+  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";
 
   filesystem::path compiler;
   ostringstream flags;
@@ -1693,6 +1694,10 @@ ModelTree::compileMEX(const filesystem::path &output_dir, const string &output_b
       else if (mexext == "mexmaci64" || mexext == "mexmaca64")
         {
           compiler = findGccOnMacos(mexext);
+          if (compiler == "/usr/bin/gcc") // change flags for clang
+          {
+            opt_flags = "-O3 -g0 --param ira-max-conflict-table-size=1 -Wno-unused-command-line-argument";
+          }
           flags << " -fno-common -Wl,-twolevel_namespace -undefined error -bundle";
           libs += " -lm";
         }
-- 
GitLab