diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4fb3f7d..ba891a1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,13 +20,12 @@ jobs: python-version: '3.10' - name: Build and Install run: | - ${Python3_EXECUTABLE} -m pip install pybind11 - ${Python3_EXECUTABLE} -m pip install pytest - ${Python3_EXECUTABLE} -m pip install numpy - ${Python3_EXECUTABLE} -m pip install --verbose . + python3 -m pip install pybind11 + python3 -m pip install pytest + python3 -m pip install --verbose . - name: Test run: | source .venv/bin/activate export LD_LIBRARY_PATH="/opt/drake/lib:$LD_LIBRARY_PATH" - ${Python3_EXECUTABLE} -m pytest + python3 -m pytest diff --git a/CMakeLists.txt b/CMakeLists.txt index ae15e5d..09aba60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,31 +11,6 @@ project( VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES CXX) - -if (NOT SKBUILD) - message(WARNING "\ - This CMake file is meant to be executed using 'scikit-build'. Running - it directly will almost certainly not produce the desired result. If - you are a user trying to install this package, please use the command - below, which will install all necessary build dependencies, compile - the package in an isolated environment, and then install it. - ===================================================================== - $ pip install . - ===================================================================== - If you are a software developer, and this is your own package, then - it is usually much more efficient to install the build dependencies - in your environment once and use the following command that avoids - a costly creation of a new virtual environment at every compilation: - ===================================================================== - $ pip install nanobind scikit-build-core[pyproject] - $ pip install --no-build-isolation -ve . - ===================================================================== - You may optionally add -Ceditable.rebuild=true to auto-rebuild when - the package is imported. Otherwise, you need to re-run the above - after editing C++ files.") -endif() - - include(CTest) find_package(drake CONFIG REQUIRED) diff --git a/pyproject.toml b/pyproject.toml index a6878c1..07e2826 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,11 @@ [build-system] -requires = ["scikit-build-core>=0.3.3", "pybind11"] -build-backend = "scikit_build_core.build" +requires = [ + "setuptools>=42", + "wheel", + "ninja", + "cmake>=3.12", +] +build-backend = "setuptools.build_meta" [project] name = "drake_extension" @@ -21,11 +26,6 @@ test = ["pytest"] [project.urls] Homepage = "https://github.com/MAminSFV/drake_extension" - -[tool.scikit-build] -wheel.expand-macos-universal-tags = true - - [tool.pytest.ini_options] minversion = "6.0" addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"] @@ -42,6 +42,7 @@ testpaths = ["tests"] build-frontend = "build[uv]" test-command = "pytest {project}/tests" test-extras = ["test"] +before-build = "rm -rf {project}/build" [tool.cibuildwheel.pyodide] environment.CFLAGS = "-fexceptions" @@ -50,6 +51,7 @@ build-frontend = {name = "build", args = ["--exports", "whole_archive"]} [tool.ruff] src = ["src"] +target-version = "py310" [tool.ruff.lint] extend-select = [ diff --git a/scripts/setup_ubuntu b/scripts/setup_ubuntu index 0a0f575..7a3976c 100644 --- a/scripts/setup_ubuntu +++ b/scripts/setup_ubuntu @@ -12,8 +12,7 @@ apt-get install --no-install-recommends -y $(cat < None: + super().__init__(name, sources=[]) + self.sourcedir = os.fspath(Path(sourcedir).resolve()) + + +class CMakeBuild(build_ext): + def build_extension(self, ext: CMakeExtension) -> None: + # Must be in this form due to bug in .resolve() only fixed in Python 3.10+ + ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name) + extdir = ext_fullpath.parent.resolve() + + # Using this requires trailing slash for auto-detection & inclusion of + # auxiliary "native" libs + + debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug + cfg = "Debug" if debug else "Release" + + # CMake lets you override the generator - we need to check this. + # Can be set with Conda-Build, for example. + cmake_generator = os.environ.get("CMAKE_GENERATOR", "") + + # Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON + # EXAMPLE_VERSION_INFO shows you how to pass a value into the C++ code + # from Python. + cmake_args = [ + f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", + f"-DPYTHON_EXECUTABLE={sys.executable}", + f"-DCMAKE_BUILD_TYPE={cfg}", # not used on MSVC, but no harm + ] + build_args = [] + # Adding CMake arguments set as environment variable + # (needed e.g. to build for ARM OSx on conda-forge) + if "CMAKE_ARGS" in os.environ: + cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item] + + # In this example, we pass in the version to C++. You might not need to. + cmake_args += [f"-DEXAMPLE_VERSION_INFO={self.distribution.get_version()}"] + + if self.compiler.compiler_type != "msvc": + # Using Ninja-build since it a) is available as a wheel and b) + # multithreads automatically. MSVC would require all variables be + # exported for Ninja to pick it up, which is a little tricky to do. + # Users can override the generator with CMAKE_GENERATOR in CMake + # 3.15+. + if not cmake_generator or cmake_generator == "Ninja": + try: + import ninja + + ninja_executable_path = Path(ninja.BIN_DIR) / "ninja" + cmake_args += [ + "-GNinja", + f"-DCMAKE_MAKE_PROGRAM:FILEPATH={ninja_executable_path}", + ] + except ImportError: + pass + + if sys.platform.startswith("darwin"): + # Cross-compile support for macOS - respect ARCHFLAGS if set + archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", "")) + if archs: + cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))] + + # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level + # across all generators. + if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: + # self.parallel is a Python 3 only way to set parallel jobs by hand + # using -j in the build_ext call, not supported by pip or PyPA-build. + if hasattr(self, "parallel") and self.parallel: + # CMake 3.12+ only. + build_args += [f"-j{self.parallel}"] + + build_temp = Path(self.build_temp) / ext.name + if not build_temp.exists(): + build_temp.mkdir(parents=True) + + subprocess.run( + ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True + ) + subprocess.run( + ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True + ) + + +# The information here can also be placed in setup.cfg - better separation of +# logic and declaration, and simpler if you include description/version in a file. +setup( + name="drake_extension", + version="0.0.1", + author="M. Amin Safavi", + author_email="safavi.m.amin@gmail.com", + description="A test project using pybind11 and Drake", + long_description="", + ext_modules=[CMakeExtension("drake_extension")], + cmdclass={"build_ext": CMakeBuild}, + zip_safe=False, + extras_require={"test": ["pytest>=6.0"]}, + python_requires=">=3.10", +) diff --git a/tests/test_simple_adder.py b/tests/test_simple_adder.py index 4078c9c..cbaf730 100644 --- a/tests/test_simple_adder.py +++ b/tests/test_simple_adder.py @@ -1,5 +1,5 @@ -import numpy as np -#from drake_extension import SimpleAdder +#import numpy as np +from drake_extension import SimpleAdder from pydrake.systems.analysis import Simulator from pydrake.systems.framework import (