From e87ef819a4b636ce2b90cb90400d35c14e66a749 Mon Sep 17 00:00:00 2001 From: Christophe Guillon <christophe.guillon@inria.fr> Date: Mon, 8 Jul 2024 16:19:56 +0200 Subject: [PATCH] [Setup] Use symlinks in editable mode post install In editable mode, post installation of files use symlinks instead of copy. This allow to the either rebuild with pip or directly with the build backend, for instance: - make -C build install - ninja -C build install # with Ninja backend --- README.md | 8 ++++++++ setup.py | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6ff9ec438..246472888 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,14 @@ After changes in a python file, no action is required, for changes in .cpp/.h fi pip install --no-build-isolation -v -e . ``` +Or simply use the build backend (generated files in the `build/` directory have been symlinked +during the first editable install): +```bash +make -C build install -j $(nproc) +# or for instance with ninja backend +ninja -C build install +``` + In this mode, the C++ compilation build system is located in the local `build/` directory. Refer to the doc string in `setup.py`for more details on editable mode. diff --git a/setup.py b/setup.py index e88e10ef5..110118531 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ Development Status :: 2 - Pre-Alpha """ import shutil -import pathlib +from pathlib import Path import subprocess import multiprocessing @@ -57,7 +57,7 @@ from setuptools import setup, Extension from setuptools import find_packages from setuptools.command.build_ext import build_ext -SETUP_DIR = pathlib.Path(__file__).parent +SETUP_DIR = Path(__file__).parent def parse_requirements(): with open(SETUP_DIR / "requirements.txt", "r") as inf: @@ -90,19 +90,28 @@ class CMakeBuild(build_ext): else: self.editable_mode = False + def _post_install_copy(self, fname, dst_dir): + Path(dst_dir).mkdir(parents=True, exist_ok=True) + dst_file = Path(dst_dir) / Path(fname).name + if not self.editable_mode: + shutil.copy(str(fname), str(dst_file)) + else: + dst_file.unlink(missing_ok=True) + os.symlink(str(fname), str(dst_file)) + def run(self): # This lists the number of processors available on the machine # The compilation will use half of them # Note that for ninja backend this is not necessary max_jobs = str(ceil(multiprocessing.cpu_count() / 2)) - cwd = pathlib.Path().absolute() + cwd = Path().absolute() build_temp = cwd / "build" if not build_temp.exists(): build_temp.mkdir(parents=True, exist_ok=True) - build_lib = pathlib.Path(self.build_lib) + build_lib = Path(self.build_lib) if not build_lib.exists(): build_lib.mkdir(parents=True, exist_ok=True) @@ -135,11 +144,11 @@ class CMakeBuild(build_ext): if ((file.endswith('.so') or file.endswith('.pyd')) and root != str(aidge_package) and not root.startswith(str(build_lib))): - currentFile = pathlib.Path(root) / file - shutil.copy(str(currentFile), str(aidge_package)) + currentFile = Path(root) / file + self._post_install_copy(currentFile, aidge_package) # Copy version.txt in aidge_package - shutil.copy(str(SETUP_DIR / "version.txt"), str(aidge_package)) + self._post_install_copy(SETUP_DIR / "version.txt", str(aidge_package)) if __name__ == '__main__': -- GitLab