Skip to content

Commit

Permalink
Streamline setup.py with new build interface (CrayLabs#359)
Browse files Browse the repository at this point in the history
Update setup.py to interact with the new build interface
[ committed by @billschereriii ]
[ reviewed by @MattToast  ]
  • Loading branch information
billschereriii authored and ashao committed Jul 6, 2023
1 parent c8bcc91 commit ea4227a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 56 deletions.
3 changes: 3 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ To be released at some future point in time

Description

- Updated setup.py to work with the new build system
- Remove unneeded method from Python SRObject class
- Fixed a memory leak in the C layer
- Remove debug output in pybind layer
Expand All @@ -25,6 +26,7 @@ Description

Detailed Notes

- Streamlined setup.py to simplify Python install (PR359)
- Remove from_pybind() from Python SRObject class as it's not needed and didn't work properly anyway (PR358_)
- Fixed memory leaked from the C layer when calling get_string_option() (PR357_)
- Remove debug output in pybind layer associated with put_dataset (PR352_)
Expand All @@ -48,6 +50,7 @@ users need not import `iso_c_binding` in their own applications (PR340_)
- New pip-install target in Makefile will be a dependency of the lib target going forward so that users don't have to manually pip install SmartRedis in the future (PR330_)
- Added ConfigOptions class and API, which will form the backbone of multiDB support (PR303_)

.. _PR359: https://github.com/CrayLabs/SmartRedis/pull/359
.. _PR358: https://github.com/CrayLabs/SmartRedis/pull/358
.. _PR357: https://github.com/CrayLabs/SmartRedis/pull/357
.. _PR352: https://github.com/CrayLabs/SmartRedis/pull/352
Expand Down
108 changes: 52 additions & 56 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext
from distutils.version import LooseVersion

# get number of processors
NPROC = mp.cpu_count()
Expand All @@ -50,65 +49,72 @@ def cmake(self):
cmake_cmd = shutil.which("cmake")
return cmake_cmd

@property
def make(self):
"""Find and use installed cmake"""
make_cmd = shutil.which("make")
return make_cmd

def run(self):
# Validate dependencies
check_prereq("cmake")
check_prereq("make")
check_prereq("gcc")
check_prereq("g++")

# Set up parameters
source_directory = Path(__file__).parent.resolve()
build_directory = Path(self.build_temp).resolve()
cmake_args = [
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(build_directory),
'-DPYTHON_EXECUTABLE=' + sys.executable,
'-DSR_PYTHON=ON'
]

cfg = 'Debug' if self.debug else 'Release'
build_args = ['--config', cfg]
build_args += ['--', f'-j{str(NPROC)}']
self.build_args = build_args

cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]

# setup build environment
# Setup build environment
env = os.environ.copy()
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(
env.get('CXXFLAGS', ''),
self.distribution.get_version())

# make tmp dir
if not build_directory.is_dir():
os.makedirs(self.build_temp)

# make install dir
setup_path = Path(os.path.abspath(os.path.dirname(__file__))).resolve()
install_directory = setup_path.joinpath("install")
if not install_directory.is_dir():
os.makedirs(install_directory)

print('-'*10, 'Building C dependencies', '-'*40)
make_cmd = shutil.which("make")

# build dependencies
subprocess.check_call([f"{make_cmd} deps"],
cwd=setup_path,
shell=True)

# run cmake prep step
print('-'*10, 'Running CMake prepare', '-'*40)
subprocess.check_call([self.cmake, setup_path] + cmake_args,
cwd=build_directory,
env=env)


print('-'*10, 'Building extensions', '-'*40)
cmake_cmd = [self.cmake, '--build', '.'] + self.build_args
subprocess.check_call(cmake_cmd,
cwd=build_directory)

shutil.copytree(setup_path.joinpath("install"),
build_directory.joinpath("install"))
# Build dependencies
print('-'*10, 'Building third-party dependencies', '-'*40)
subprocess.check_call(
[self.make, "deps"],
cwd=source_directory,
shell=False
)

# Run CMake config step
print('-'*10, 'Configuring build', '-'*40)
config_args = [
'-S.',
f'-B{str(build_directory)}',
'-DSR_BUILD=' + cfg,
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(build_directory),
'-DPYTHON_EXECUTABLE=' + sys.executable,
'-DSR_PYTHON=ON',
]
subprocess.check_call(
[self.cmake] + config_args,
cwd=source_directory,
env=env
)

# Run CMake build step
print('-'*10, 'Building library', '-'*40)
build_args = [
'--build',
str(build_directory),
'--',
f'-j{str(NPROC)}'
]
subprocess.check_call(
[self.cmake] + build_args,
cwd=build_directory,
env=env
)

# Move from build temp to final position
# (Note that we skip the CMake install step because
# we configured the library to be built directly into the
# build directory)
for ext in self.extensions:
self.move_output(ext)

Expand All @@ -122,23 +128,13 @@ def move_output(self, ext):
self.copy_file(source_path, dest_path)

# check that certain dependencies are installed
# TODO: Check versions for compatible versions
def check_prereq(command):
try:
out = subprocess.check_output([command, '--version'])
_ = subprocess.check_output([command, '--version'])
except OSError:
raise RuntimeError(
f"{command} must be installed to build SmartRedis")

# update existing env var
def update_env_var(var, new):
try:
value = os.environ[var]
value = ":".join((value, str(new)))
return value
except KeyError:
return new

ext_modules = [
CMakeExtension('smartredisPy'),
]
Expand Down

0 comments on commit ea4227a

Please sign in to comment.