diff --git a/doc/changelog.rst b/doc/changelog.rst index 6ba963cc0..36d28e160 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -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 @@ -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_) @@ -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 diff --git a/setup.py b/setup.py index 477c86ee9..90493eefd 100644 --- a/setup.py +++ b/setup.py @@ -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() @@ -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) @@ -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'), ]