Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions mesonbuild/compilers/mixins/apple.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,30 @@ def openmp_flags(self, env: Environment) -> T.List[str]:
"""
m = env.machines[self.for_machine]
assert m is not None, 'for mypy'
if m.cpu_family.startswith('x86'):
root = '/usr/local'
else:
root = '/opt/homebrew'

# Try to detect Homebrew prefix dynamically
root = env.get_homebrew_prefix(self.for_machine)
if root is None:
# Fallback to hardcoded defaults if brew is not available
if m.cpu_family.startswith('x86'):
root = '/usr/local'
else:
root = '/opt/homebrew'

return self.__BASE_OMP_FLAGS + [f'-I{root}/opt/libomp/include']

def openmp_link_flags(self, env: Environment) -> T.List[str]:
m = env.machines[self.for_machine]
assert m is not None, 'for mypy'
if m.cpu_family.startswith('x86'):
root = '/usr/local'
else:
root = '/opt/homebrew'

# Try to detect Homebrew prefix dynamically
root = env.get_homebrew_prefix(self.for_machine)
if root is None:
# Fallback to hardcoded defaults if brew is not available
if m.cpu_family.startswith('x86'):
root = '/usr/local'
else:
root = '/opt/homebrew'

link = self.find_library('omp', env, [f'{root}/opt/libomp/lib'])
if not link:
Expand Down
41 changes: 41 additions & 0 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import itertools
import os, re
import shutil
import typing as T
import collections

Expand Down Expand Up @@ -229,6 +230,46 @@ def __init__(self, source_dir: str, build_dir: T.Optional[str], cmd_options: cmd
self.default_cmake = ['cmake']
self.default_pkgconfig = ['pkg-config']
self.wrap_resolver: T.Optional['Resolver'] = None
# Use a sentinel to distinguish between "not yet checked" and "checked but not found"
self._homebrew_prefix_cache: PerMachine[T.Union[str, None, type(...)]] = PerMachine(..., ...)

def get_homebrew_prefix(self, for_machine: MachineChoice) -> T.Optional[str]:
"""Get the Homebrew prefix for the given machine.

This calls 'brew --prefix' once per machine and caches the result.
Returns None if brew is not found or fails.
"""
# Check if we've already computed this
cached = self._homebrew_prefix_cache[for_machine]
if cached is not ...:
return cached if cached is not None else None

# Only relevant for Darwin systems
if not self.machines[for_machine].is_darwin():
self._homebrew_prefix_cache[for_machine] = None
return None

brew_exe = shutil.which('brew')
if brew_exe is None:
mlog.debug('Homebrew not found in PATH')
self._homebrew_prefix_cache[for_machine] = None
return None

try:
p, out, err = Popen_safe([brew_exe, '--prefix'])
if p.returncode == 0:
prefix = out.strip()
mlog.debug(f'Detected Homebrew prefix: {prefix}')
self._homebrew_prefix_cache[for_machine] = prefix
return prefix
else:
mlog.debug(f'brew --prefix failed: {err}')
self._homebrew_prefix_cache[for_machine] = None
return None
except Exception as e:
mlog.debug(f'Failed to detect Homebrew prefix: {e}')
self._homebrew_prefix_cache[for_machine] = None
return None

def mfilestr2key(self, machine_file_string: str, section: T.Optional[str], section_subproject: T.Optional[str], machine: MachineChoice) -> OptionKey:
key = OptionKey.from_string(machine_file_string)
Expand Down
Loading