Skip to content

Commit

Permalink
Merge pull request #74 from pypr/use-config-file
Browse files Browse the repository at this point in the history
Add a common configuration file for options.
  • Loading branch information
prabhuramachandran committed Jan 5, 2021
2 parents d752f60 + 543cbca commit 6b569f0
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 6 deletions.
35 changes: 33 additions & 2 deletions compyle/ext_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@
logger = logging.getLogger(__name__)


def get_config_file_opts():
'''A global configuration file is used to configure build options
for compyle and other packages. This is located in:
~/.compyle/config.py
The file can contain arbitrary Python that is exec'd. The variables defined
here specify the compile and link args. For example, one may set:
OMP_CFLAGS = ['-fopenmp']
OMP_LINK = ['-fopenmp']
Will use these instead of the defaults that are automatically determined.
These must be lists.
'''
fname = expanduser(join('~', '.compyle', 'config.py'))
opts = {}
if exists(fname):
with open(fname) as fp:
exec(compile(fp.read(), fname, 'exec'), opts)
opts.pop('__builtins__', None)
return opts


CONFIG_OPTS = get_config_file_opts()


def get_platform_dir():
return 'py{version}-{platform_dir}'.format(
version=sys.version[:3], platform_dir=get_platform()
Expand Down Expand Up @@ -62,6 +90,9 @@ def get_openmp_flags():
This returns two lists, [extra_compile_args], [extra_link_args]
"""
if 'OMP_CFLAGS' in CONFIG_OPTS or 'OMP_LINK' in CONFIG_OPTS:
return CONFIG_OPTS['OMP_CFLAGS'], CONFIG_OPTS['OMP_LINK']

if sys.platform == 'win32':
return ['/openmp'], []
elif sys.platform == 'darwin':
Expand Down Expand Up @@ -91,8 +122,8 @@ def __init__(self, src, extension='pyx', root=None, verbose=False,
Do not specify the '.' (defaults to 'pyx').
root : str: root of directory to store code and modules in.
If not set it defaults to "~/.cpy/source/<platform-directory>".
where <platform-directory> is platform specific.
If not set it defaults to "~/.compyle/source/<platform-dir>".
where <platform-dir> is platform specific.
verbose : Bool : Print messages for convenience.
Expand Down
54 changes: 52 additions & 2 deletions compyle/tests/test_ext_module.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from contextlib import contextmanager
from distutils.sysconfig import get_config_var
from io import open as io_open
import os
from os.path import join, exists
Expand All @@ -15,7 +14,10 @@
except ImportError:
import mock

from ..ext_module import get_md5, ExtModule, get_ext_extension, get_unicode
import compyle.ext_module

from ..ext_module import (get_md5, ExtModule, get_ext_extension, get_unicode,
get_config_file_opts, get_openmp_flags)


def _check_write_source(root):
Expand Down Expand Up @@ -48,6 +50,54 @@ def _check_compile(root):
return m.call_count


def test_get_config_file_opts():
# Given
cfg = dedent('''
OMP_CFLAGS = ['-fxxx']
OMP_LINK = ['-fyyy']
''')
m = mock.mock_open(read_data=cfg)
with mock.patch('compyle.ext_module.open', m), \
mock.patch('compyle.ext_module.exists') as mock_exists:
# When
mock_exists.return_value = False
opts = get_config_file_opts()
print(opts)

# Then
assert 'OMP_CFLAGS' not in opts
assert 'OMP_LINK' not in opts

# When
mock_exists.return_value = True
opts = get_config_file_opts()

# Then
assert opts['OMP_CFLAGS'] == ['-fxxx']
assert opts['OMP_LINK'] == ['-fyyy']


def test_get_openmp_flags():
# Given/When
f = get_openmp_flags()

# Then
assert f[0] != ['-fxxx']
assert f[1] != ['-fyyy']
assert len(f[0]) > 0

# Given
m = dict(OMP_CFLAGS=['-fxxx'], OMP_LINK=['-fyyy'])

with mock.patch.object(compyle.ext_module, 'CONFIG_OPTS', m):
# When
f = get_openmp_flags()

# Then
assert f[0] == ['-fxxx']
assert f[1] == ['-fyyy']


class TestMiscExtMod(TestCase):
def test_md5(self):
data = "hello world"
Expand Down
38 changes: 36 additions & 2 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ deployment target and the current version of XCode that you have installed is
not compatible with that. By setting the environment variable you allow
compyle to use a newer version. If this works, it is a good idea to set this
in your default environment (``.bashrc`` for bash shells) so you do not have
to do this every time.
to do this every time. You may also do this in the compyle configuration file,
see :ref:`config`.



Expand Down Expand Up @@ -135,7 +136,8 @@ installed, otherwise the important header files are not available. See
`how-to-install-xcode-command-line-tools
<https://stackoverflow.com/questions/9329243/how-to-install-xcode-command-line-tools>`_
for more details. You may also want to set these environment variables in your
``.bashrc`` so you don't have to do this every time.
``.bashrc`` so you don't have to do this every time. You may also do this in
the compyle configuration file, see :ref:`config`.

Once you do this, compyle will automatically use this version of GCC and will
also work with OpenMP. Note that on some preliminary benchmarks, GCC's OpenMP
Expand Down Expand Up @@ -171,3 +173,35 @@ If you want to use OpenCL support, you will need to install the ``pyopencl``
package (``conda install -c conda-forge pyopencl`` or ``pip install
pyopencl``). For CUDA Support, you will need to install ``pycuda`` and
``cupy``. Of course this assumes you have the required hardware for this.


.. _config:

Using the configuration file
-----------------------------

Instead of setting environment variables and build options on the shell you
can have them setup using a simple configuration file.

The file is located in ``~/.compyle/config.py``. Here ``~`` is your home
directory which on Linux is ``/home/username``, on MacOS ``/Users/username``
and on Windows the location is likely ``\Users\username``. This file is
executed and certain options may be set there.

For example if you wish to set the environment variables ``CC`` and ``CXX``
you could do this in the ``config.py``::

import os

os.environ['CC'] = 'gcc-9'
os.environ['CXX'] = 'g++-9'

If you are using an atypical compiler like icc, Cray, or PGI, you can set
these up here too. You may also setup custom OpenMP related flags. For
example, on a Cray system you may do the following::

OMP_CFLAGS = ['-homp']
OMP_LINK = ['-homp']

The ``OMP_CFLAGS`` and ``OMP_LINK`` parameters should be lists. Other packages
like pyzoltan or pysph may also use this file for customizations.

0 comments on commit 6b569f0

Please sign in to comment.