Repository: ziglang/zig-pypi Branch: main Commit: b28791143121 Files: 6 Total size: 26.5 KB Directory structure: gitextract_pfxqcxh1/ ├── .github/ │ └── workflows/ │ └── cd.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── README.pypi.md └── make_wheels.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/cd.yml ================================================ name: CD on: workflow_dispatch: inputs: version: description: "The version to build Zig wheels for, use 'latest' for latest release, 'master' for nightly builds" required: true default: "latest" suffix: description: > Suffix to append to the version in the wheel filename, i.e., for dev versions and version specifiers required: false default: "" platforms: description: > Comma-separated list of specific platforms to build wheels for, or use 'all' to build for all supported platforms required: false default: "all" push_to_pypi: description: > Whether to push the built wheels to PyPI. Can be 'true' or 'false', defaults to 'false'. required: true default: "false" permissions: {} jobs: build_wheels: name: Build wheels runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: "3.x" - uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - name: Build wheels for all requested platforms shell: bash env: GITHUB_EVENT_INPUTS_PLATFORMS: ${{ github.event.inputs.platforms }} GITHUB_EVENT_INPUTS_VERSION: ${{ github.event.inputs.version }} GITHUB_EVENT_INPUTS_SUFFIX: ${{ github.event.inputs.suffix }} run: | platforms=${GITHUB_EVENT_INPUTS_PLATFORMS} IFS=',' read -r -a platform_array <<< "$platforms" for platform in "${platform_array[@]}"; do cmd="uv run make_wheels.py --outdir dist/ --version ${GITHUB_EVENT_INPUTS_VERSION} --platform $platform" if [ -n "${GITHUB_EVENT_INPUTS_SUFFIX}" ]; then cmd="$cmd --suffix ${GITHUB_EVENT_INPUTS_SUFFIX}" fi eval "$cmd" done - name: Upload wheel artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: zig_wheels path: dist/*.whl if-no-files-found: error deploy_wheels: name: Deploy wheels needs: [build_wheels] if: >- github.event.inputs.push_to_pypi == 'true' && github.repository == 'ziglang/zig-pypi' environment: pypi runs-on: ubuntu-latest permissions: id-token: write # for OIDC trusted publishing attestations: write # for the GitHub Actions Attestations feature contents: read steps: - name: Download all wheel artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: path: dist/ merge-multiple: true - name: Sanity check wheel artifacts run: ls -R dist/ - name: Generate artifact attestations uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 with: subject-path: dist/* # This will publish the list of wheels inputted to the action to PyPI (set to # off, by default). # The workflow may be triggered multiple times with the `push_to_pypi` input # set to 'true' to publish the wheels for any configurable version (non-dev). - name: Publish wheels to PyPI uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 with: packages-dir: dist/ inspect_wheels: name: Inspect wheels needs: [build_wheels] runs-on: ubuntu-latest steps: - name: Download all built wheel artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: path: dist/ merge-multiple: true - name: Inspect wheel artifacts shell: bash run: | echo -e '## A list of built wheels and their SHA-256 checksums \n' >> $GITHUB_STEP_SUMMARY echo -e '```\n' >> $GITHUB_STEP_SUMMARY for wheel in dist/*.whl; do shasum --algorithm 256 "$wheel" >> $GITHUB_STEP_SUMMARY done echo -e '```\n' >> $GITHUB_STEP_SUMMARY ================================================ FILE: .gitignore ================================================ # Python __pycache__/ *.egg-info /dist *.whl # pdm /.pdm-plugins /.pdm-python /.venv /pdm.lock ================================================ FILE: LICENSE.txt ================================================ The MIT License (Expat) Copyright (c) 2021, whitequark Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ Zig PyPI distribution ===================== This repository contains the script used to repackage the [releases][zigdl] of the [Zig programming language][zig] as [Python binary wheels][wheel]. This document is intended for maintainers; see the [package README][pkgreadme] for rationale and usage instructions. The repackaged artifacts are published as the [ziglang PyPI package][pypi]. [zig]: https://ziglang.org/ [zigdl]: https://ziglang.org/download/ [wheel]: https://github.com/pypa/wheel [pkgreadme]: README.pypi.md [pypi]: https://pypi.org/project/ziglang/ Preparation ----------- The script requires Python 3.9 and later and a [PEP 723][pep723] compatible script runner, such as [`pipx`][pipx], [`pdm`][pdm], [`hatch`][hatch], [`uv`][uv], or similar. Please refer to their documentation for installation instructions. [pep723]: https://peps.python.org/pep-0723/ [pipx]: https://pipx.pypa.io/stable/examples/#pipx-run-examples [pdm]: https://pdm-project.org/en/latest/usage/scripts/#single-file-scripts [hatch]: https://hatch.pypa.io/latest/blog/2024/05/02/hatch-v1100/#python-script-runner/ [uv]: https://docs.astral.sh/uv/#script-support/ Building wheels --------------- Run the repackaging script. Here's an example invocation with [`pdm`][pdm]: ```shell $ pdm run make_wheels.py --help usage: make_wheels.py [-h] [--version VERSION] [--suffix SUFFIX] [--outdir OUTDIR] [--platform {x86_64-windows,x86_64-macos,aarch64-macos,i386-linux,x86-linux,x86_64-linux,aarch64-linux,armv7a-linux}] Repackage official Zig downloads as Python wheels options: -h, --help show this help message and exit --version VERSION version to package, use `latest` for latest release, `master` for nightly build --suffix SUFFIX wheel version suffix --outdir OUTDIR target directory --platform {x86_64-windows,x86_64-macos,aarch64-macos,i386-linux,x86-linux,x86_64-linux,aarch64-linux,armv7a-linux} platform to build for, can be repeated ``` This command will download the Zig release archives for every supported platform and convert them to binary wheels, which are placed under `dist/`. The Zig version and platforms can be passed as arguments. The process of converting release archives to binary wheels is deterministic, and the output of the script should be bit-for-bit identical regardless of the environment and platform it runs under. To this end, it prints the SHA256 hashes of inputs and outputs; the hashes of the inputs will match the ones on the [Zig downloads page][zigdl], and the hashes of the outputs will match the ones on the [PyPI downloads page][pypidl]. [pypidl]: https://pypi.org/project/ziglang/#files Uploading wheels to PyPI ------------------------ Trigger the publishing workflow from this repository manually (requires authorization) with the necessary inputs as mentioned in the [workflow file](.github/workflows/cd.yml) or in the GitHub Actions UI. The wheels are checked with `twine` before they are uploaded. The workflow will upload the wheels to PyPI to make them available for installation. It is possible to trigger it multiple times to upload wheels for different versions or platforms. Verifying the provenance of wheels uploaded to PyPI --------------------------------------------------- To establish build provenance, the workflow generates attestations for the uploaded wheels using the [GitHub Actions Attestations feature](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) when it is run. Please navigate to the [Attestations interface](https://github.com/ziglang/zig-pypi/attestations) to view the attestations for the uploaded wheels. The attestations may be verified via the [GitHub (`gh`) CLI](https://cli.github.com/manual/gh_attestation_verify) or via the [GitHub API](https://docs.github.com/en/rest/users/attestations). License ------- This script is distributed under the terms of the [MIT (Expat) license](LICENSE.txt). Please refer to the [Zig license](https://ziglang.org/download/#license) for the terms of use of the Zig programming language itself, or look in the `.dist-info/licenses/` directory of the built wheels for individual licenses of the bundled components. ================================================ FILE: README.pypi.md ================================================ Zig PyPI distribution ===================== [Zig][] is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software. The [ziglang][pypi] Python package redistributes the Zig toolchain so that it can be used as a dependency of Python projects. [zig]: https://ziglang.org/ [pypi]: https://pypi.org/project/ziglang/ Rationale --------- Although Zig is useful in itself, the Zig toolchain includes a drop-in C and C++ compiler, [`zig cc`][zigcc], based on [clang][]. Unlike clang itself, `zig cc` is standalone: it does not require additional development files to be installed to target any of the platforms it supports. Through `zig cc`, Python code that generates C or C++ code can build it without any external dependencies. [clang]: https://clang.llvm.org/ [zigcc]: https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html Usage ----- To run the Zig toolchain from the command line, use: ```shell python -m ziglang ``` To run the Zig toolchain from a Python program, use `sys.executable` to locate the Python binary to invoke. For example: ```python import sys, subprocess subprocess.call([sys.executable, "-m", "ziglang"]) ``` Binary wrapper -------------- The [ziglang][pypi] Python package installs a binary wrapper for the Zig compiler under the name `python-zig`; the name is different to avoid conflicts with any system-wide or user-wide `zig` binaries that may be already installed. Using with `uv` --------------- The Zig compiler distributed in this Python package can be launched by [uv](https://docs.astral.sh/uv) without installation: ```shell uvx --from ziglang python-zig ``` License ------- The [Zig license](https://github.com/ziglang/zig#license). ================================================ FILE: make_wheels.py ================================================ # /// script # requires-python = "~=3.9" # dependencies = [ # "wheel~=0.41.0", # ] # /// # Additionally, install twine to upload the wheels to PyPI. import argparse import logging import io import os import re import json import hashlib import tarfile import urllib.request from pathlib import Path, PurePath from email.policy import EmailPolicy from email.message import EmailMessage from wheel.wheelfile import WheelFile from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED ZIG_VERSION_INFO_URL = 'https://ziglang.org/download/index.json' ZIG_PYTHON_PLATFORMS = { 'x86_64-windows': 'win_amd64', 'aarch64-windows': 'win_arm64', 'x86-windows': 'win32', 'x86_64-macos': 'macosx_12_0_x86_64', 'aarch64-macos': 'macosx_12_0_arm64', 'i386-linux': 'manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686', # renamed i386 to x86 since v0.11.0, i386 was last supported in v0.10.1 'x86-linux': 'manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686', 'x86_64-linux': 'manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64', 'aarch64-linux': 'manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64', 'armv7a-linux': 'manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l', # renamed armv7a to arm since v0.15.1, armv7a was last supported in v0.14.1 'arm-linux': 'manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l', 'powerpc64le-linux': 'manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le', 's390x-linux': 'manylinux_2_17_s390x.manylinux2014_s390x.musllinux_1_1_s390x', 'riscv64-linux': 'manylinux_2_31_riscv64.musllinux_1_1_riscv64', } _YELLOW = "\033[93m" class ReproducibleWheelFile(WheelFile): def writestr(self, zinfo_or_arcname, data, *args, **kwargs): if isinstance(zinfo_or_arcname, ZipInfo): zinfo = zinfo_or_arcname else: assert isinstance(zinfo_or_arcname, str) zinfo = ZipInfo(zinfo_or_arcname) zinfo.file_size = len(data) zinfo.external_attr = 0o0644 << 16 if zinfo_or_arcname.endswith(".dist-info/RECORD"): zinfo.external_attr = 0o0664 << 16 zinfo.compress_type = ZIP_DEFLATED zinfo.date_time = (1980,1,1,0,0,0) zinfo.create_system = 3 super().writestr(zinfo, data, *args, **kwargs) def make_message(headers, payload=None): msg = EmailMessage(policy=EmailPolicy(max_line_length=0)) for name, value in headers: if isinstance(value, list): for value_part in value: msg[name] = value_part else: msg[name] = value if payload: msg.set_payload(payload) return msg def write_wheel_file(filename, contents): with ReproducibleWheelFile(filename, 'w') as wheel: for member_info, member_source in contents.items(): wheel.writestr(member_info, bytes(member_source)) return filename def write_wheel(out_dir, *, name, version, tag, metadata, description, contents): wheel_name = f'{name}-{version}-{tag}.whl' dist_info = f'{name}-{version}.dist-info' filtered_metadata = [] for header, value in metadata: filtered_metadata.append((header, value)) # The WHEEL file must contain the compatibility tags in their expanded form. # see https://packaging.python.org/en/latest/specifications/binary-distribution-format/#file-contents # see https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#compressed-tag-sets pytag, abitag, platformtag = tag.split("-") expanded_tags = [ "-".join((x, y, z)) for z in platformtag.split(".") for y in abitag.split(".") for x in pytag.split(".") ] return write_wheel_file(os.path.join(out_dir, wheel_name), { **contents, f'{dist_info}/entry_points.txt': make_message([], '[console_scripts]\npython-zig = ziglang.__main__:dummy' ), f'{dist_info}/METADATA': make_message([ ('Metadata-Version', '2.4'), ('Name', name), ('Version', version), *filtered_metadata, ], description), f'{dist_info}/WHEEL': make_message([ ('Wheel-Version', '1.0'), ('Generator', 'ziglang make_wheels.py'), ('Root-Is-Purelib', 'false'), ('Tag', expanded_tags), ]), }) def iter_archive_contents(archive): magic = archive[:4] if magic[:4] == b"\xfd7zX": with tarfile.open(mode="r|xz", fileobj=io.BytesIO(archive)) as tar: for entry in tar: if entry.isreg(): yield entry.name, entry.mode | (1 << 15), tar.extractfile(entry).read() elif magic[:4] == b"PK\x03\x04": with ZipFile(io.BytesIO(archive)) as zip_file: for entry in zip_file.infolist(): if not entry.is_dir(): yield entry.filename, entry.external_attr >> 16, zip_file.read(entry) else: raise RuntimeError("Unsupported archive format") def write_ziglang_wheel(out_dir, *, version, platform, archive): contents = {} contents['ziglang/__init__.py'] = b'' license_files = {} found_license_files = set() potential_extra_licenses = set() # A bunch of standard license file patterns. If a file matches any of # these, we need to add them to required_license_paths and metadata. license_patterns = [ r'COPYING.*', r'COPYRIGHT.*', r'COPYLEFT.*', r'LICEN[CS]E.*', r'LICEN[CS]E-.*', r'LICEN[CS]E\..*', r'PATENTS.*', r'NOTICE.*', r'LEGAL.*', r'AUTHORS.*', r'RIGHT*', r'PERMISSION*', r'THIRD[-_]PARTY[-_]LICENSES?.*', r'EULA*', r'MIT*', r'GPL*', r'AGPL*', r'LGPL*', r'APACHE*', ] license_regex = re.compile('|'.join(f'^{pattern}$' for pattern in license_patterns), re.IGNORECASE) # These file paths MUST remain in sync with the paths in the official # Zig tarballs and with the ones defined below in the metadata. The # script will raise an error if any of these files are not found in # the archive. required_license_paths = [ 'LICENSE', 'lib/libc/glibc/LICENSES', 'lib/libc/mingw/COPYING', 'lib/libc/musl/COPYRIGHT', 'lib/libc/wasi/LICENSE', 'lib/libc/wasi/LICENSE-APACHE', 'lib/libc/wasi/LICENSE-APACHE-LLVM', 'lib/libc/wasi/LICENSE-MIT', 'lib/libc/wasi/libc-bottom-half/cloudlibc/LICENSE', 'lib/libc/wasi/libc-top-half/musl/COPYRIGHT', 'lib/libcxx/LICENSE.TXT', 'lib/libcxxabi/LICENSE.TXT', 'lib/libunwind/LICENSE.TXT', 'lib/libc/freebsd/COPYRIGHT', 'lib/libc/wasi/fts/musl-fts/COPYING', ] excluded_license_paths = [ # not a license text; contains macros that generate license strings 'lib/libc/include/generic-freebsd/sys/copyright.h', ] for entry_name, entry_mode, entry_data in iter_archive_contents(archive): entry_name = '/'.join(entry_name.split('/')[1:]) if not entry_name: continue if entry_name.startswith('doc/') or entry_name in excluded_license_paths: continue # Check for additional license-like files potential_license_filename = PurePath(entry_name).name if license_regex.match(potential_license_filename): potential_extra_licenses.add(entry_name) zip_info = ZipInfo(f'ziglang/{entry_name}') zip_info.external_attr = (entry_mode & 0xFFFF) << 16 contents[zip_info] = entry_data if entry_name in required_license_paths: license_files[entry_name] = entry_data found_license_files.add(entry_name) if entry_name.startswith('zig'): contents['ziglang/__main__.py'] = f'''\ import os, sys argv = [os.path.join(os.path.dirname(__file__), "{entry_name}"), *sys.argv[1:]] if os.name == 'posix': os.execv(argv[0], argv) else: import subprocess; sys.exit(subprocess.call(argv)) def dummy(): """Dummy function for an entrypoint. Zig is executed as a side effect of the import.""" '''.encode('ascii') # 1. Check for missing required licenses paths missing_licenses = set(required_license_paths) - found_license_files if missing_licenses: error_message = ( f"{_YELLOW}The following required license files were not found in the Zig archive: {', '.join(sorted(missing_licenses))} " f"\nThis may indicate a change in Zig's license file structure or an error in the listing of license files and/or paths.{_YELLOW}" ) raise RuntimeError(error_message) # 2. Check for potentially missing license files extra_licenses = potential_extra_licenses - set(required_license_paths) if extra_licenses: error_message = ( f"{_YELLOW}Found additional potential license files in the Zig archive but not included in the metadata: {', '.join(sorted(extra_licenses))} " f"\nPlease consider adding these to the license paths if they should be included.{_YELLOW}" ) raise RuntimeError(error_message) with open('README.pypi.md') as f: description = f.read() dist_info = f'ziglang-{version}.dist-info' for license_path, license_data in license_files.items(): contents[f'{dist_info}/licenses/ziglang/{license_path}'] = license_data return write_wheel(out_dir, name='ziglang', version=version, tag=f'py3-none-{platform}', metadata=[ ('Summary', 'Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.'), ('Description-Content-Type', 'text/markdown'), # The license expression and the file paths MUST remain in sync # with the paths in the official Zig tarballs and with the ones # defined above in the contents. The difference is that these # are prefixed with "ziglang/" to match the paths in the wheel # for metadata compliance. ('License-Expression', 'MIT'), ('License-File', 'ziglang/LICENSE'), ('License-File', 'ziglang/lib/libc/glibc/LICENSES'), ('License-File', 'ziglang/lib/libc/mingw/COPYING'), ('License-File', 'ziglang/lib/libc/musl/COPYRIGHT'), ('License-File', 'ziglang/lib/libc/wasi/LICENSE'), ('License-File', 'ziglang/lib/libc/wasi/LICENSE-APACHE'), ('License-File', 'ziglang/lib/libc/wasi/LICENSE-APACHE-LLVM'), ('License-File', 'ziglang/lib/libc/wasi/LICENSE-MIT'), ('License-File', 'ziglang/lib/libc/wasi/libc-bottom-half/cloudlibc/LICENSE'), ('License-File', 'ziglang/lib/libc/wasi/libc-top-half/musl/COPYRIGHT'), ('License-File', 'ziglang/lib/libcxx/LICENSE.TXT'), ('License-File', 'ziglang/lib/libcxxabi/LICENSE.TXT'), ('License-File', 'ziglang/lib/libunwind/LICENSE.TXT'), ('License-File', 'ziglang/lib/libc/freebsd/COPYRIGHT'), ('Classifier', 'Development Status :: 4 - Beta'), ('Classifier', 'Intended Audience :: Developers'), ('Classifier', 'Topic :: Software Development :: Compilers'), ('Classifier', 'Topic :: Software Development :: Code Generators'), ('Classifier', 'Topic :: Software Development :: Build Tools'), ('Classifier', 'Programming Language :: Zig'), ('Project-URL', 'Homepage, https://ziglang.org'), ('Project-URL', 'Source Code, https://github.com/ziglang/zig-pypi'), ('Project-URL', 'Bug Tracker, https://github.com/ziglang/zig-pypi/issues'), ('Requires-Python', '~=3.5'), ], description=description, contents=contents, ) def fetch_zig_version_info(): with urllib.request.urlopen(ZIG_VERSION_INFO_URL) as request: return json.loads(request.read()) def fetch_and_write_ziglang_wheels( outdir='dist/', zig_version='master', wheel_version_suffix='', platforms=tuple() ): Path(outdir).mkdir(exist_ok=True) if not platforms: platforms = list(ZIG_PYTHON_PLATFORMS) zig_versions_info = fetch_zig_version_info() if zig_version == 'latest': zig_version = [version for version in zig_versions_info if version != 'master'][0] try: zig_version_info = zig_versions_info[zig_version] except KeyError: print(f"Invalid version, valid values: {list(zig_versions_info)}") raise effective_zig_version = zig_version_info.get('version', zig_version) for zig_platform in platforms: python_platform = ZIG_PYTHON_PLATFORMS[zig_platform] if zig_platform not in zig_version_info: print(f"{zig_platform} not present for " f"version {zig_version} / {effective_zig_version}") continue zig_download = zig_version_info[zig_platform] zig_url = zig_download['tarball'] expected_hash = zig_download['shasum'] with urllib.request.urlopen(zig_url) as request: zig_archive = request.read() zig_archive_hash = hashlib.sha256(zig_archive).hexdigest() if zig_archive_hash != expected_hash: raise Exception( f"SHA256 hash mismatch for {zig_download}! expected shasum {expected_hash}") print(f'{hashlib.sha256(zig_archive).hexdigest()} {zig_url}') wheel_version = effective_zig_version.split('+')[0].replace('-', '.') wheel_path = write_ziglang_wheel(outdir, version=wheel_version + wheel_version_suffix, platform=python_platform, archive=zig_archive) with open(wheel_path, 'rb') as wheel: print(f' {hashlib.sha256(wheel.read()).hexdigest()} {wheel_path}') def get_argparser(): supported_platforms = ', '.join(sorted(ZIG_PYTHON_PLATFORMS.keys())) description = (f"Repackage official Zig downloads as Python wheels.\n\n" f"Supported platforms: {supported_platforms}") parser = argparse.ArgumentParser(prog=__file__, description=description, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--version', default='latest', help="version to package, use `latest` for latest release, `master` for nightly build") parser.add_argument('--suffix', default='', help="wheel version suffix") parser.add_argument('--outdir', default='dist/', help="target directory") parser.add_argument('--platform', action='append', default=[], help="platform to build for, use 'all' to build for all supported platforms, can be repeated") return parser def main(): args = get_argparser().parse_args() logging.getLogger("wheel").setLevel(logging.WARNING) platforms = args.platform if 'all' in platforms: platforms = list(ZIG_PYTHON_PLATFORMS.keys()) fetch_and_write_ziglang_wheels(outdir=args.outdir, zig_version=args.version, wheel_version_suffix=args.suffix, platforms=platforms) if __name__ == '__main__': main()