Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
fixes:
- |
Building on macOS inside a conda-build or ``rattler-build`` recipe no longer
fails with ``no OpenMP runtime found on this macOS host`` when the recipe
provides ``llvm-openmp``. The build located ``libomp`` by probing
``$CONDA_PREFIX``, which under those tools names the base installation
rather than the environment being built into, so the ``omp.h`` installed in
the build prefix went unexamined and the build fell through to Homebrew.
``sys.prefix`` and ``sys.base_prefix`` are now consulted as well, after
``CONDA_PREFIX`` and before Homebrew, so an ordinary activated environment
behaves as before.
31 changes: 23 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,16 +774,26 @@ def detect_gpu_toolchain():
print("\nConfiguring CPU backend (_core_cpu)")
if platform.system() == 'Darwin':
# macOS has no system OpenMP, so libomp comes from a package manager.
# Prefer the conda env when it has one: those are the libraries actually
# Prefer an environment that has one: those are the libraries actually
# LOADED at import time (resolved via the python executable's
# @loader_path/../lib), so building against Homebrew's copies instead
# means compiling against different libraries than the process runs on.
conda_prefix = os.environ.get('CONDA_PREFIX')
if conda_prefix and os.path.exists(
os.path.join(conda_prefix, 'include', 'omp.h')):
omp_inc = os.path.join(conda_prefix, 'include')
omp_lib = openblas_lib = os.path.join(conda_prefix, 'lib')
print(f"Darwin: libomp and BLAS from conda env {conda_prefix}")
#
# CONDA_PREFIX names the *activated* environment, which is not always
# the one being built into: conda-build and rattler-build activate their
# own base installation and install into $PREFIX, whose python is the
# interpreter running this script. So fall back to sys.prefix, which
# identifies the environment the extension is actually built for -- the
# same convention _mpi_prefix_from_env_prefix() already uses.
omp_prefix = next(
(p for p in (os.environ.get('CONDA_PREFIX'), sys.prefix,
getattr(sys, 'base_prefix', None))
if p and os.path.exists(os.path.join(p, 'include', 'omp.h'))),
None)
if omp_prefix:
omp_inc = os.path.join(omp_prefix, 'include')
omp_lib = openblas_lib = os.path.join(omp_prefix, 'lib')
print(f"Darwin: libomp and BLAS from env prefix {omp_prefix}")
else:
# Ask brew for its prefix rather than assuming: it is /opt/homebrew
# on Apple silicon and /usr/local on Intel, so either one hardcoded
Expand All @@ -797,8 +807,13 @@ def detect_gpu_toolchain():
if not os.path.exists(os.path.join(omp_inc, 'omp.h')):
# Fail here with the fix, rather than 100 lines later with
# "'omp.h' file not found" from the middle of a compile.
_searched = ', '.join(dict.fromkeys(
[os.path.join(p, 'include')
for p in (os.environ.get('CONDA_PREFIX'), sys.prefix,
getattr(sys, 'base_prefix', None)) if p]
+ [omp_inc]))
print("Error: no OpenMP runtime found on this macOS host.\n"
f" Looked in $CONDA_PREFIX/include and {omp_inc}.\n"
f" Looked in: {_searched}.\n"
" Apple clang ships without OpenMP, so install one:\n"
" conda install -c conda-forge llvm-openmp (preferred)\n"
" brew install libomp")
Expand Down
Loading