From d5010bcb01a642007dcb368aac6aae12613c18a6 Mon Sep 17 00:00:00 2001 From: Ritvik Rao Date: Mon, 29 Apr 2024 16:11:27 -0500 Subject: [PATCH 1/7] fixing build issues on mac contains a workaround to fix the path to the libcharm shared library in the c_object_store library --- charm4py/charmlib/charmlib_ctypes.py | 12 +++- docs/install.rst | 97 +++++++++++++++------------- setup.py | 36 ++++++++++- 3 files changed, 96 insertions(+), 49 deletions(-) diff --git a/charm4py/charmlib/charmlib_ctypes.py b/charm4py/charmlib/charmlib_ctypes.py index 206bb444..72f8fadf 100644 --- a/charm4py/charmlib/charmlib_ctypes.py +++ b/charm4py/charmlib/charmlib_ctypes.py @@ -5,6 +5,7 @@ import sys import os import time +import platform if sys.version_info < (3, 0, 0): import cPickle else: @@ -108,6 +109,7 @@ def __init__(self, charm, opts, libcharm_path): self.chareNames = [] self.charm = charm self.opts = opts + self.system = platform.system().lower() self.init(libcharm_path) self.ReducerType = ReducerTypes.in_dll(self.lib, "charm_reducers") self.times = [0.0] * 3 # track time in [charm reduction callbacks, custom reduction, outgoing object migration] @@ -609,9 +611,15 @@ def init(self, libcharm_path): p = os.environ.get('LIBCHARM_PATH') if p is not None: libcharm_path = p if libcharm_path is not None: - self.lib = ctypes.CDLL(os.path.join(libcharm_path, 'libcharm.so')) + if self.system == 'darwin': + self.lib = ctypes.CDLL(os.path.join(libcharm_path, 'libcharm.dylib')) + else: + self.lib = ctypes.CDLL(os.path.join(libcharm_path, 'libcharm.so')) else: - self.lib = ctypes.CDLL('libcharm.so') + if self.system == 'darwin': + self.lib = ctypes.CDLL('libcharm.dylib') + else: + self.lib = ctypes.CDLL('libcharm.so') else: self.lib = ctypes.CDLL(os.path.join(libcharm_path, 'charm.dll')) diff --git a/docs/install.rst b/docs/install.rst index d23bff84..0717d630 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -15,53 +15,56 @@ CPython (most common implementation) and PyPy_. .. _PyPy: http://pypy.org -pip ---- - -To install on regular Linux, macOS and Windows machines, do:: +Manually building the Charm++ shared library +-------------------------------------------- - $ pip3 install charm4py +Use this to build Charm4py binaries manually, instead of downloading prebuilt libraries from pip. +This is needed when building Charm++ for specialized machine/network layers +other than TCP and MPI (e.g. Cray XC/XE). -.. note:: +Before installing, you need the following prerequisites: + - CPython: numpy, greenlet and cython (``pip3 install 'numpy>=1.10.0' cython greenlet``) + - PyPy: none - This option uses Charm++'s TCP layer as the communication layer. - If you want a faster communication layer (e.g. MPI), see "Install from - source" below. +The first step is to clone the Charm4py repository from Git:: - pip >= 8.0 is recommended to simplify the install and avoid building Charm4py or - any dependencies from sources. + $ git clone https://github.com/UIUC-PPL/charm4py + $ cd charm4py - Note that a 64-bit version of Python is required to install and run Charm4py. +Next, create a folder called charm_src in the charm4py repo, and then clone the Charm++ repo +into that folder:: + $ mkdir charm_src && cd charm_src + $ git clone https://github.com/UIUC-PPL/charm -Install from source -------------------- +Once this is done, there are two ways to build Charm4py. The first way is to change back up +into the Charm4Py directory and run the install script:: + + $ cd .. + $ python3 setup.py install [--mpi] -.. note:: - This is not required if installing from a binary wheel with pip. +The optional flag ``--mpi``, when enabled, will build the +Charm++ library with the MPI communication layer (MPI headers and libraries +need to be installed on the system). After this, Charm4Py will be built. -Prerequisites: - - CPython: numpy, greenlet and cython (``pip3 install 'numpy>=1.10.0' cython greenlet``) - - PyPy: none +The other option is to manually build Charm++ before building Charm4py. To do this, change to +the charm directory and run the following build command:: + + $ cd charm + $ ./build charm4py -j --with-production -To build the latest *stable* release, do:: +Then, return to the charm4py directory and run setup.py:: - $ pip3 install [--install-option="--mpi"] charm4py --no-binary charm4py + $ cd ../.. + $ python3 setup.py install [--mpi] -Or download the source distribution from PyPI, uncompress and run -``python3 setup.py install [--mpi]``. -The optional flag ``--mpi``, when enabled, will build the -Charm++ library with the MPI communication layer (MPI headers and libraries -need to be installed on the system). +After building, you can run Charm4py examples. One example you can try is +array_hello.py, which can be run as follows:: -To build the latest *development* version, download Charm4py and Charm++ source code -and run setup:: + $ cd examples/hello + $ python -m charmrun.start +p2 array_hello.py - $ git clone https://github.com/UIUC-PPL/charm4py - $ cd charm4py - $ git clone https://github.com/UIUC-PPL/charm charm_src/charm - $ python3 setup.py install [--mpi] .. note:: @@ -72,25 +75,27 @@ and run setup:: to manually build the Charm++ library (see below). -Manually building the Charm++ shared library --------------------------------------------- +pip +--- -This is needed when building Charm++ for specialized machine/network layers -other than TCP and MPI (e.g. Cray XC/XE). +This option installs prebuilt Charm4Py binaries from pip. The prebuilt pip libraries +were built with Python 3.7. -Before running ``python3 setup.py`` in the steps above, enter the Charm++ source code -directory (``charm_src/charm``), and manually build the Charm++ library. The build -command syntax is:: +To install on regular Linux, macOS and Windows machines, do:: - $ ./build charm4py -j --with-production + $ pip3 install charm4py -where ```` varies based on the system and communication layer, and ```` -is the number of processes to use for compiling. -For help in choosing the correct ````, please refer to the Charm++ manual_ -and the README in Charm++'s root directory. +.. note:: + + This option uses Charm++'s TCP layer as the communication layer. + If you want a faster communication layer (e.g. MPI), see "Install from + source" below. + + pip >= 8.0 is recommended to simplify the install and avoid building Charm4py or + any dependencies from sources. + + Note that a 64-bit version of Python is required to install and run Charm4py. -After the library has been built, continue with ``python3 setup.py install`` in the -Charm4py source root directory. .. _manual: https://charm.readthedocs.io/en/latest/charm++/manual.html#installing-charm diff --git a/setup.py b/setup.py index db3e9e22..bf1fda44 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ import sys import os +import re import shutil import platform import subprocess @@ -8,6 +9,7 @@ from setuptools.command.build_py import build_py from setuptools.command.install import install from distutils.errors import DistutilsSetupError +from distutils.command.install_lib import install_lib as _install_lib from distutils import log import distutils @@ -17,6 +19,7 @@ build_mpi = False + def get_build_machine(): machine = platform.machine() if machine == 'arm64' or machine == 'aarch64': @@ -53,6 +56,7 @@ def get_build_triple(build_mpi): os.environ['ARCHFLAGS'] = f'-arch {machine}' libcharm_filename = 'libcharm.dylib' charmrun_filename = 'charmrun' + os.environ['CPPFLAGS'] = f'-Wno-error=implicit-function-declaration' #needed because this error will cause builds to fail if the Clang compiler is version 15.0.0 or newer (it is only a warning on older builds) else: # Linux libcharm_filename = 'libcharm.so' charmrun_filename = 'charmrun' @@ -185,6 +189,7 @@ def build_libcharm(charm_src_dir, build_dir): for output_dir in lib_output_dirs: log.info('copying ' + os.path.relpath(lib_src_path) + ' to ' + os.path.relpath(output_dir)) shutil.copy(lib_src_path, output_dir) + # ---- copy charmrun ---- charmrun_src_path = os.path.join(charm_src_dir, 'charm', 'bin', charmrun_filename) @@ -257,6 +262,34 @@ def run(self): build_libcharm(os.path.join(os.getcwd(), 'charm_src'), self.build_lib) super(custom_build_ext, self).run() +def batch_rename(src, dst, src_dir_fd=None, dst_dir_fd=None): + os.rename(src, dst, + src_dir_fd=src_dir_fd, + dst_dir_fd=dst_dir_fd) + if "c_object_store" in src and system == "darwin": + direc = src.rsplit('/', 1) + install_name_command = "install_name_tool -change lib/libcharm.dylib " + install_name_command += direc[0] + install_name_command += "/.libs/libcharm.dylib " + install_name_command += direc[0] + install_name_command += "/c_object_store.so" + log.info(install_name_command) + os.system(install_name_command) + return dst + +class _renameInstalled(_install_lib): + def __init__(self, *args, **kwargs): + _install_lib.__init__(self, *args, **kwargs) + + def install(self): + log.info("Renaming libraries") + outfiles = _install_lib.install(self) + matcher = re.compile('\.([^.]+)\.so$') + renames = [batch_rename(file, re.sub(matcher, '.so', file)) + for file in outfiles] + return renames + + extensions = [] py_impl = platform.python_implementation() @@ -369,6 +402,7 @@ def run(self): ext_modules=extensions, cmdclass = {'build_py': custom_build_py, 'build_ext': custom_build_ext, - 'install': custom_install}, + 'install': custom_install, + 'install_lib': _renameInstalled,}, **additional_setup_keywords ) From fdae6409f5399619e7abf7fc0cd72c2e9c27cba7 Mon Sep 17 00:00:00 2001 From: Ritvik Rao Date: Wed, 1 May 2024 10:13:10 -0500 Subject: [PATCH 2/7] get directory name with os command --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index bf1fda44..e316ebd0 100644 --- a/setup.py +++ b/setup.py @@ -267,11 +267,11 @@ def batch_rename(src, dst, src_dir_fd=None, dst_dir_fd=None): src_dir_fd=src_dir_fd, dst_dir_fd=dst_dir_fd) if "c_object_store" in src and system == "darwin": - direc = src.rsplit('/', 1) + direc = os.path.dirname(src) install_name_command = "install_name_tool -change lib/libcharm.dylib " - install_name_command += direc[0] + install_name_command += direc install_name_command += "/.libs/libcharm.dylib " - install_name_command += direc[0] + install_name_command += direc install_name_command += "/c_object_store.so" log.info(install_name_command) os.system(install_name_command) From 8c58a7962a5efc7ac13604ee3f0d98927c8ce70d Mon Sep 17 00:00:00 2001 From: Ritvik Rao Date: Wed, 1 May 2024 10:55:28 -0500 Subject: [PATCH 3/7] environment append --- setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e316ebd0..b26c415a 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,11 @@ def get_build_triple(build_mpi): os.environ['ARCHFLAGS'] = f'-arch {machine}' libcharm_filename = 'libcharm.dylib' charmrun_filename = 'charmrun' - os.environ['CPPFLAGS'] = f'-Wno-error=implicit-function-declaration' #needed because this error will cause builds to fail if the Clang compiler is version 15.0.0 or newer (it is only a warning on older builds) + env = os.environ.get('CPPFLAGS') + if env: + os.environ['CPPFLAGS'] += f'-Wno-error=implicit-function-declaration' #needed because this error will cause builds to fail if the Clang compiler is version 15.0.0 or newer (it is only a warning on older builds) + else: + os.environ['CPPFLAGS'] = f'-Wno-error=implicit-function-declaration' else: # Linux libcharm_filename = 'libcharm.so' charmrun_filename = 'charmrun' From 9fc7adb22eda27027ad8b767bad110f4dd193e19 Mon Sep 17 00:00:00 2001 From: Ritvik Rao Date: Wed, 1 May 2024 11:01:29 -0500 Subject: [PATCH 4/7] cppflags if statement --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b26c415a..51f0c5c6 100644 --- a/setup.py +++ b/setup.py @@ -56,8 +56,7 @@ def get_build_triple(build_mpi): os.environ['ARCHFLAGS'] = f'-arch {machine}' libcharm_filename = 'libcharm.dylib' charmrun_filename = 'charmrun' - env = os.environ.get('CPPFLAGS') - if env: + if 'CPPFLAGS' in os.environ: os.environ['CPPFLAGS'] += f'-Wno-error=implicit-function-declaration' #needed because this error will cause builds to fail if the Clang compiler is version 15.0.0 or newer (it is only a warning on older builds) else: os.environ['CPPFLAGS'] = f'-Wno-error=implicit-function-declaration' From 6e05db9889dea0f479bf54a56c2f9e0baf554844 Mon Sep 17 00:00:00 2001 From: ritvikrao Date: Wed, 1 May 2024 11:09:44 -0500 Subject: [PATCH 5/7] minor cppflag change Co-authored-by: Matthias Diener --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 51f0c5c6..0ad06df8 100644 --- a/setup.py +++ b/setup.py @@ -57,9 +57,9 @@ def get_build_triple(build_mpi): libcharm_filename = 'libcharm.dylib' charmrun_filename = 'charmrun' if 'CPPFLAGS' in os.environ: - os.environ['CPPFLAGS'] += f'-Wno-error=implicit-function-declaration' #needed because this error will cause builds to fail if the Clang compiler is version 15.0.0 or newer (it is only a warning on older builds) + os.environ['CPPFLAGS'] += ' -Wno-error=implicit-function-declaration' # needed because some functions used by charm4py are not exported by charm. else: - os.environ['CPPFLAGS'] = f'-Wno-error=implicit-function-declaration' + os.environ['CPPFLAGS'] = '-Wno-error=implicit-function-declaration ' else: # Linux libcharm_filename = 'libcharm.so' charmrun_filename = 'charmrun' From 5ec1568a1a0281226b1896b1654f22b34c1e5ee6 Mon Sep 17 00:00:00 2001 From: mayantaylor Date: Thu, 2 May 2024 21:52:59 -0500 Subject: [PATCH 6/7] changing clang -arch flag for arm --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0ad06df8..5dc09742 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def get_build_machine(): machine = platform.machine() if machine == 'arm64' or machine == 'aarch64': - return 'arm8' + return 'arm64' return machine From 8e70d8de04822f58269f6924e2876d23bb2efb2c Mon Sep 17 00:00:00 2001 From: Ritvik Rao Date: Fri, 3 May 2024 11:10:32 -0500 Subject: [PATCH 7/7] no renaming --- setup.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/setup.py b/setup.py index 5dc09742..e48ce670 100644 --- a/setup.py +++ b/setup.py @@ -265,21 +265,6 @@ def run(self): build_libcharm(os.path.join(os.getcwd(), 'charm_src'), self.build_lib) super(custom_build_ext, self).run() -def batch_rename(src, dst, src_dir_fd=None, dst_dir_fd=None): - os.rename(src, dst, - src_dir_fd=src_dir_fd, - dst_dir_fd=dst_dir_fd) - if "c_object_store" in src and system == "darwin": - direc = os.path.dirname(src) - install_name_command = "install_name_tool -change lib/libcharm.dylib " - install_name_command += direc - install_name_command += "/.libs/libcharm.dylib " - install_name_command += direc - install_name_command += "/c_object_store.so" - log.info(install_name_command) - os.system(install_name_command) - return dst - class _renameInstalled(_install_lib): def __init__(self, *args, **kwargs): _install_lib.__init__(self, *args, **kwargs) @@ -287,10 +272,26 @@ def __init__(self, *args, **kwargs): def install(self): log.info("Renaming libraries") outfiles = _install_lib.install(self) - matcher = re.compile('\.([^.]+)\.so$') - renames = [batch_rename(file, re.sub(matcher, '.so', file)) - for file in outfiles] - return renames + for file in outfiles: + if "c_object_store" in file and system == "darwin": + direc = os.path.dirname(file) + install_name_command = "install_name_tool -change lib/libcharm.dylib " + install_name_command += direc + install_name_command += "/.libs/libcharm.dylib " + install_name_command += direc + install_name_command += "/c_object_store.*.so" + log.info(install_name_command) + os.system(install_name_command) + elif "charmlib_cython" in file and system == "darwin": + direc = os.path.dirname(file) + install_name_command = "install_name_tool -change lib/libcharm.dylib " + install_name_command += direc + install_name_command += "/.libs/libcharm.dylib " + install_name_command += direc + install_name_command += "/charmlib_cython.*.so" + log.info(install_name_command) + os.system(install_name_command) + return outfiles