diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 946b366..f00a249 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -15,12 +15,13 @@ concurrency: cancel-in-progress: true jobs: - build_macos_wheels: - name: macOS (${{ matrix.os }}) + build_wheels: + name: Wheels (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ macos-13, macos-14 ] + os: [ macos-13, macos-14, windows-2022 ] steps: - uses: actions/checkout@v4 @@ -39,8 +40,9 @@ jobs: runs-on: ubuntu-latest name: Linux (${{ matrix.arch }}, ${{ matrix.tag }}) strategy: + fail-fast: false matrix: - arch: [ x86_64, i686, aarch64, ppc64le, s390x ] + arch: [ x86_64, i686, aarch64, ppc64le ] tag: [ manylinux, musllinux ] # TODO(charlie): Fails to compile, root cause is unexplored. exclude: @@ -85,7 +87,7 @@ jobs: test_macos_11: name: Test macOS 11 runs-on: macos-11 - needs: build_macos_wheels + needs: build_wheels steps: - uses: actions/checkout@v4 @@ -101,7 +103,7 @@ jobs: run: python -m whisper_cpp -h upload_pypi: - needs: [ build_macos_wheels, build_linux_wheels, build_sdist ] + needs: [ build_wheels, build_linux_wheels, build_sdist ] runs-on: ubuntu-latest environment: pypi permissions: diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5ecae6a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.28...3.29) +project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX) + +set(WHISPER_BUILD_EXAMPLES + ON + CACHE BOOL "" FORCE) + +include(FetchContent) +FetchContent_Declare( + whisper-cpp + URL https://github.com/ggerganov/whisper.cpp/archive/refs/tags/v1.5.5.zip + URL_HASH MD5=7262e27c619a0e51e5e2892e429d7481 + EXCLUDE_FROM_ALL) +FetchContent_MakeAvailable(whisper-cpp) + +set_target_properties(main PROPERTIES OUTPUT_NAME whisper-cpp EXCLUDE_FROM_ALL + FALSE) + +install(TARGETS main RUNTIME DESTINATION "${SKBUILD_SCRIPTS_DIR}") diff --git a/hatch_build.py b/hatch_build.py deleted file mode 100644 index a8e7297..0000000 --- a/hatch_build.py +++ /dev/null @@ -1,91 +0,0 @@ -import os -import shutil -import subprocess -import urllib.request -import zipfile -from typing import Any - -from hatchling.builders.hooks.plugin.interface import BuildHookInterface - -EXE = ".exe" if os.name == "nt" else "" - -WHISPER_CPP_VERSION = "1.5.5" -WHISPER_CPP_ZIP_URL = ( - f"https://github.com/ggerganov/whisper.cpp/archive/refs/tags/v{WHISPER_CPP_VERSION}.zip" -) -WHISPER_DIR = f"whisper.cpp-{WHISPER_CPP_VERSION}" - - -class WhisperCppBuildHook(BuildHookInterface): - PLUGIN_NAME = "whisper-cpp" - - def initialize(self, version: str, build_data: dict[str, Any]) -> None: - if not os.path.exists(f"{WHISPER_DIR}/main{EXE}"): - - def download_and_unzip(url, extract_to="."): - """ - Downloads a ZIP file from a URL and unzips it into the given directory. - - Args: - url (str): The URL of the zip file to download. - extract_to (str): The directory to extract the files into. - """ - # Download the file from `url` and save it locally under `file_name` - file_name = url.split("/")[-1] - urllib.request.urlretrieve(url, file_name) - - # Unzip the file - with zipfile.ZipFile(file_name, "r") as zip_ref: - zip_ref.extractall(extract_to) - - # Clean up the downloaded zip file - os.remove(file_name) - - # Remove the existing whisper-cpp directory, if it exists - shutil.rmtree(WHISPER_DIR, ignore_errors=True) - - # Download the latest whisper-cpp release from GitHub. - download_and_unzip(WHISPER_CPP_ZIP_URL, extract_to=".") - - # Run make to build the whisper-cpp library. - subprocess.check_call(["make"], cwd=WHISPER_DIR) - - build_data["shared_scripts"] = {f"{WHISPER_DIR}/main{EXE}": f"whisper-cpp{EXE}"} - build_data["tag"] = self._infer_tag() - - def _infer_tag(self) -> str: - """Infer the appropriate wheel tag. - - Based on Hatchling's own `get_best_matching_tag` as of v1.24.2, with the - primary difference being that the plugin generates an ABI and version-agnostic - wheel tag, modifying _only_ the platform tag to include the architecture. - """ - import sys - - from packaging.tags import sys_tags - - tag = next( - iter( - tag - for tag in sys_tags() - if "manylinux" not in tag.platform and "musllinux" not in tag.platform - ) - ) - tag_platform = tag.platform - - # On macOS, set the version based on `MACOSX_DEPLOYMENT_TARGET`. - if sys.platform == "darwin": - macosx_deployment_target = os.environ.get("MACOSX_DEPLOYMENT_TARGET") - if macosx_deployment_target: - # Extract the architecture from, e.g., `macosx_14_0_arm64`. - if tag_platform.endswith("_arm64"): - tag_arch = "arm64" - elif tag_platform.endswith("_x86_64"): - tag_arch = "x86_64" - else: - raise ValueError(f"Unknown macOS arch: {tag_platform}") - - # Reconstruct the platform tag with the architecture. - tag_platform = f"macosx_{macosx_deployment_target.replace('.', '_')}_{tag_arch}" - - return f"py3-none-{tag_platform}" diff --git a/pyproject.toml b/pyproject.toml index abfecf9..624b575 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +requires = ["scikit-build-core"] +build-backend = "scikit_build_core.build" [project] name = "whisper.cpp-cli" @@ -12,11 +12,12 @@ requires-python = ">=3.7" license = { file = "LICENSE" } dependencies = [] -[tool.hatch.build.targets.wheel] -packages = ["whisper_cpp"] - -[tool.hatch.build.hooks.custom] -path = "hatch_build.py" +[tool.scikit-build] +minimum-version = "0.9" +cmake.define.BUILD_SHARED_LIBS = false +cmake.version = ">=3.28" +wheel.packages = ["whisper_cpp"] +wheel.py-api = "py3" [tool.ruff] line-length = 100 @@ -29,11 +30,5 @@ test-command = [ "whisper-cpp -h", "python -m whisper_cpp -h", ] - -[[tool.cibuildwheel.overrides]] -select = "*-macosx_x86_64" environment.MACOSX_DEPLOYMENT_TARGET = "10.12" -[[tool.cibuildwheel.overrides]] -select = "*-macosx_arm64" -environment.MACOSX_DEPLOYMENT_TARGET = "11.0"