diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index eacd9ca..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: build - -on: - push: - -jobs: - build_win32: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: ilammy/msvc-dev-cmd@v1 - - name: Compile - shell: bash - run: | - cd pocketpy - python cmake_build.py Release -DPK_ENABLE_DETERMINISM=OFF - cd ../ - cmake -B build -DCMAKE_BUILD_TYPE=Release - cmake --build build --config Release - - uses: actions/upload-artifact@v4 - with: - name: windows - path: build/Release/numpy.dll - build_linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Compile and Test - run: | - cd pocketpy - python cmake_build.py Release -DPK_ENABLE_DETERMINISM=OFF - cd ../ - cmake -B build -DCMAKE_BUILD_TYPE=Release - cmake --build build --config Release - - uses: actions/upload-artifact@v4 - with: - name: linux - path: build/libnumpy.so - \ No newline at end of file diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml new file mode 100644 index 0000000..b7b33d1 --- /dev/null +++ b/.github/workflows/pip.yml @@ -0,0 +1,30 @@ +name: "Pip" + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +jobs: + build: + name: Build with Pip + runs-on: ${{ matrix.platform }} + strategy: + fail-fast: false + matrix: + platform: [macos-latest, ubuntu-latest] + python-version: ["3.9", "3.11"] + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Build and install + run: pip install --verbose . diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 0000000..4e84c7f --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,93 @@ +name: Wheels + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + release: + types: + - published + +env: + FORCE_COLOR: 3 + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build_sdist: + name: Build SDist + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Build SDist + run: pipx run build --sdist + + - name: Check metadata + run: pipx run twine check dist/* + + - uses: actions/upload-artifact@v4 + with: + name: cibw-sdist + path: dist/*.tar.gz + + + build_wheels: + name: Wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, ubuntu-24.04-arm, macos-14] + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - uses: pypa/cibuildwheel@v3.3.1 + env: + CIBW_ARCHS_MACOS: universal2 + CIBW_SKIP: "pp* *musllinux* *_i686 cp314t-win*" + CIBW_TEST_SKIP: "*" + CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=10.14 + + - name: Verify clean directory + run: git diff --exit-code + shell: bash + + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }} + path: wheelhouse/*.whl + + + upload_all: + name: Upload if release + needs: [build_wheels, build_sdist] + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + environment: pypi + permissions: + id-token: write + + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - uses: actions/download-artifact@v4 + with: + pattern: cibw-* + merge-multiple: true + path: dist + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.pypi_password }} diff --git a/.gitignore b/.gitignore index db32b02..50cb3f0 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ build/ .cache profiler_report.json +__pycache__/ +*.pyc +dist diff --git a/CMakeLists.txt b/CMakeLists.txt index e383430..d524d09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,17 @@ -cmake_minimum_required(VERSION 3.10) -project(numpy) +cmake_minimum_required(VERSION 3.15...3.26) + +if(NOT DEFINED SKBUILD_PROJECT_NAME) + set(SKBUILD_PROJECT_NAME "pocket_numpy") +endif() +if(NOT DEFINED PROJECT_VERSION) + set(PROJECT_VERSION "dev") +endif() + +# https://scikit-build-core.readthedocs.io/en/latest/cmakelists.html#accessing-information +project( + ${SKBUILD_PROJECT_NAME} + VERSION ${SKBUILD_PROJECT_VERSION} + LANGUAGES CXX) # Set C++ standard set(CMAKE_CXX_STANDARD 17) @@ -10,6 +22,11 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) +# std::visit requires macOS 10.14+ +if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.14") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum macOS deployment version" FORCE) +endif() + # set(CMAKE_BUILD_TYPE "Debug") if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) @@ -51,14 +68,25 @@ if(NOT SHOW_XTENSOR_WARNINGS) endif() # Create numpy static library -add_library(${PROJECT_NAME} STATIC src/numpy.cpp) +add_library(numpy STATIC src/numpy.cpp) # Define PY_DYNAMIC_MODULE for numpy -target_compile_definitions(${PROJECT_NAME} PRIVATE PY_DYNAMIC_MODULE) +target_compile_definitions(numpy PRIVATE PY_DYNAMIC_MODULE) # Link numpy with pocketpy -target_link_libraries(${PROJECT_NAME} PUBLIC pocketpy) +target_link_libraries(numpy PUBLIC pocketpy) add_executable(pocketpy_cli src/main.cpp) set_target_properties(pocketpy_cli PROPERTIES OUTPUT_NAME pocketpy) -target_link_libraries(pocketpy_cli ${PROJECT_NAME}) \ No newline at end of file +set_target_properties(pocketpy_cli PROPERTIES SUFFIX ".exe") +target_link_libraries(pocketpy_cli numpy) +install(TARGETS pocketpy_cli DESTINATION ${PROJECT_NAME}) + +# https://scikit-build-core.readthedocs.io/en/latest/getting_started.html +find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) +find_package(pybind11 CONFIG REQUIRED) + +python_add_library(_core MODULE src/pybind.cpp WITH_SOABI) +target_link_libraries(_core PRIVATE pybind11::headers) +target_compile_definitions(_core PRIVATE VERSION_INFO=${PROJECT_VERSION}) +install(TARGETS _core DESTINATION ${PROJECT_NAME}) \ No newline at end of file diff --git a/Makefile b/Makefile index 8b63c47..04bc3e1 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,28 @@ +PROJECT_SOURCE_DIR ?= $(abspath ./) +PROJECT_NAME ?= $(shell basename $(PROJECT_SOURCE_DIR)) +NUM_JOB ?= 8 + all: @echo nothing special .PHONY: all clean: - rm -rf build + rm -rf build dist .PHONY: clean +PYTHON ?= python3 build: - cmake -B build -DCMAKE_BUILD_TYPE=Release - cmake --build build --config Release -.PHONY: build + $(PYTHON) -m pip install scikit_build_core pyproject_metadata pathspec pybind11 + CMAKE_BUILD_PARALLEL_LEVEL=$(NUM_JOB) $(PYTHON) -m pip install --no-build-isolation -Ceditable.rebuild=true -Cbuild-dir=build -ve. +python_install: + $(PYTHON) -m pip install . --verbose +python_wheel: + $(PYTHON) -m pip wheel . -w build --verbose +python_sdist: + $(PYTHON) -m build --sdist +test_install: + python3 -m pip install dist/pocket_numpy-*.tar.gz --force-reinstall +.PHONY: build python_install python_wheel python_sdist test_install test: - build/test_numpy tests/test_numpy.py + build/pocketpy.exe tests/test_numpy.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..208d607 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,44 @@ +[build-system] +requires = ["scikit-build-core>=0.3.3", "pybind11"] +build-backend = "scikit_build_core.build" + +[project] +name = "pocket_numpy" +version = "0.0.1" +description = "pocketpy with numpy" +readme = "README.md" +authors = [ + { name = "tzx", email = "dvorak4tzx@gmail.com" }, +] +requires-python = ">=3.8" +classifiers = [ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] + +[project.urls] +Homepage = "https://github.com/cubao/xtensor-numpy" + +[project.optional-dependencies] +test = ["pytest"] + +[tool.scikit-build] +wheel.expand-macos-universal-tags = true + +[tool.pytest.ini_options] +minversion = "6.0" +testpaths = ["tests"] + +[tool.cibuildwheel] +test-command = "pytest {project}/tests" +test-extras = ["test"] +test-skip = ["*universal2:arm64"] +build-verbosity = 1 diff --git a/src/main.cpp b/src/main.cpp index d0ad3c8..9ef055b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,11 @@ int main(int argc, char** argv) { const char* arg2 = NULL; for(int i = 1; i < argc; i++) { + if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + printf("Usage: pocketpy [--profile] [--debug] [--compile] filename\n"); + printf(" pocketpy --help\n"); + return 1; + } if(strcmp(argv[i], "--profile") == 0) { profile = true; continue; diff --git a/src/pocket_numpy/__init__.py b/src/pocket_numpy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pocket_numpy/__main__.py b/src/pocket_numpy/__main__.py new file mode 100644 index 0000000..4dbb095 --- /dev/null +++ b/src/pocket_numpy/__main__.py @@ -0,0 +1,9 @@ +import sys +import subprocess +from pathlib import Path + + +if __name__ == '__main__': + exe = f'{Path(__file__).parent}/pocketpy.exe' + args = sys.argv[1:] + sys.exit(subprocess.call([exe, *args])) diff --git a/src/pybind.cpp b/src/pybind.cpp new file mode 100644 index 0000000..06d3502 --- /dev/null +++ b/src/pybind.cpp @@ -0,0 +1,24 @@ +#include + +#define STRINGIFY(x) #x +#define MACRO_STRINGIFY(x) STRINGIFY(x) + +PYBIND11_MODULE(_core, m) +{ + m.doc() = R"pbdoc( + pocketpy with numpy + ------------------- + + credits: + - https://github.com/pocketpy/pocketpy + - https://github.com/pocketpy/xtensor-numpy + )pbdoc"; + + // TODO, bind pocketpy repl, debugging, profiling, etc. + +#ifdef VERSION_INFO + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); +#else + m.attr("__version__") = "dev"; +#endif +} \ No newline at end of file