Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
44 changes: 39 additions & 5 deletions extension_helpers/_openmp_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
import datetime
import tempfile
import subprocess
import textwrap

from setuptools.command.build_ext import customize_compiler, get_config_var, new_compiler

from ._setup_helpers import get_compiler
from ._setup_helpers import check_apple_clang, get_compiler

__all__ = ['add_openmp_flags_if_available']

Expand Down Expand Up @@ -134,8 +135,41 @@ def get_openmp_flags():
link_flags.append('-L' + lib_path)
link_flags.append('-Wl,-rpath,' + lib_path)

compile_flags.append('-fopenmp')
link_flags.append('-fopenmp')
if not check_apple_clang():
compile_flags.append('-fopenmp')
link_flags.append('-fopenmp')
else:
msg = textwrap.dedent(
"""\
You are using Apple Clang compiler.

Your system should be prepared:
1. You should have specfically installed OpenMP,
for instance by running `brew install libomp`.
2. OpenMP source and library should be findable by the compiler.

By default, OpenMP source and library will be looked in
`/usr/local/opt/libomp/include` and `/usr/local/opt/libomp/lib`
respectively.

To use specific OpenMP source and library paths, you can setup
the following environment variables `CFLAGS` and `LDFLAGS`
before any compilation/installation, e.g.
```
export CFLAGS="-I/usr/local/opt/libomp/include"
export LDFLAGS="-L/usr/local/opt/libomp/lib"
```
"""
)
log.warn(msg)
compile_flags.append('-Xpreprocessor -fopenmp')
if not 'CFLAG' in os.environ and \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be CFLAGS (and LDFLAGS below)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks! I fixed it in 094b820

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be CFLAGS (and LDFLAGS below)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks! I fixed it in 094b820

os.path.isdir('/usr/local/opt/libomp/include'):
compile_flags.append('-I/usr/local/opt/libomp/include')
link_flags.append('-lomp')
if not 'LDFLAG' in os.environ and \
os.path.isdir('/usr/local/opt/libomp/lib'):
link_flags.append('-L/usr/local/opt/libomp/lib')

return {'compiler_flags': compile_flags, 'linker_flags': link_flags}

Expand Down Expand Up @@ -189,12 +223,12 @@ def check_openmp_support(openmp_flags=None):

# Compile, test program
ccompiler.compile(['test_openmp.c'], output_dir='objects',
extra_postargs=compile_flags)
extra_preargs=compile_flags)

# Link test program
objects = glob.glob(os.path.join('objects', '*' + ccompiler.obj_extension))
ccompiler.link_executable(objects, 'test_openmp',
extra_postargs=link_flags)
extra_preargs=link_flags)

# Run test program
output = subprocess.check_output('./test_openmp')
Expand Down
28 changes: 27 additions & 1 deletion extension_helpers/_setup_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from collections import defaultdict

from setuptools import Extension, find_packages
from setuptools.command.build_ext import new_compiler
from setuptools.command.build_ext import customize_compiler,new_compiler

from ._utils import import_file, walk_skip_hidden

Expand All @@ -36,6 +36,32 @@ def get_compiler():
return new_compiler().compiler_type


def check_apple_clang():
"""
Detemines if compiler that will be used to build extension modules is
'Apple Clang' (which requires a specific management of OpenMP compilation
and linking flags).

In addition, it may require that you install `libomp` (e.g. with
`brew install libomp`).

Returns
-------
apple_clang : bool
Indicator whether current compiler is 'Apple Clang'.
"""
try:
ccompiler = new_compiler()
customize_compiler(ccompiler)
compiler_version = subprocess.run(
[ccompiler.compiler[0], "--version"], capture_output=True
)
apple_clang = "Apple clang" in str(compiler_version.stdout)
except Exception:
apple_clang = False
return apple_clang


def get_extensions(srcdir='.'):
"""
Collect all extensions from Cython files and ``setup_package.py`` files.
Expand Down
5 changes: 4 additions & 1 deletion extension_helpers/tests/test_setup_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import pytest

from .._setup_helpers import get_compiler, get_extensions
from .._setup_helpers import check_apple_clang, get_compiler, get_extensions
from . import cleanup_import, run_setup

extension_helpers_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) # noqa
Expand All @@ -27,6 +27,9 @@ def teardown_module(module):
def test_get_compiler():
assert get_compiler() in POSSIBLE_COMPILERS

def test_check_apple_clang():
assert check_apple_clang() in [True, False]


def _extension_test_package(tmpdir, request, extension_type='c',
include_numpy=False):
Expand Down