Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions gyp/.github/workflows/python_tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# TODO: Enable os: windows-latest
# TODO: Enable pytest --doctest-modules

name: Python_tests
Expand All @@ -8,17 +7,28 @@ on:
workflow_dispatch:

jobs:
Python_lint:
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@v6
- name: Lint with ruff # See pyproject.toml for settings
uses: astral-sh/ruff-action@v3
- run: ruff format --check --diff

Python_tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 5
matrix:
os: [macos-15-intel, macos-latest, ubuntu-latest] # , windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
os: [macos-15-intel, macos-latest, ubuntu-latest, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
include:
- os: macos-26
python-version: 3.x
- os: ubuntu-24.04-arm # Ubuntu on ARM
python-version: 3.x
- os: windows-11-arm # Windows on ARM
python-version: 3.x
steps:
- uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -32,9 +42,6 @@ jobs:
python -m pip install --upgrade pip
pip install --editable ".[dev]"
- run: ./gyp -V && ./gyp --version && gyp -V && gyp --version
- name: Lint with ruff # See pyproject.toml for settings
uses: astral-sh/ruff-action@v3
- run: ruff format --check --diff
- name: Test with pytest # See pyproject.toml for settings
run: pytest
# - name: Run doctests with pytest
Expand Down
8 changes: 4 additions & 4 deletions gyp/.github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Build a binary wheel and a source tarball
run: pipx run build
- name: Store the distribution packages
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: python-package-distributions
path: dist/
Expand All @@ -48,7 +48,7 @@ jobs:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: python-package-distributions
path: dist/
Expand All @@ -68,12 +68,12 @@ jobs:
id-token: write # IMPORTANT: mandatory for sigstore
steps:
- name: Download all the dists
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: python-package-distributions
path: dist/
- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v3.2.0
uses: sigstore/gh-action-sigstore-python@v3.3.0
with:
inputs: >-
./dist/*.tar.gz
Expand Down
4 changes: 4 additions & 0 deletions gyp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,7 @@ static

test/fixtures/out
*.actual
*.sln
*.vcproj
!test/fixtures/expected-win32/**/*.sln
!test/fixtures/expected-win32/**/*.vcproj
2 changes: 1 addition & 1 deletion gyp/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.21.1"
".": "0.22.1"
}
19 changes: 19 additions & 0 deletions gyp/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## [0.22.1](https://github.com/nodejs/gyp-next/compare/v0.22.0...v0.22.1) (2026-04-21)


### Bug Fixes

* use floor division when escaping command-line arguments ([#338](https://github.com/nodejs/gyp-next/issues/338)) ([cadca24](https://github.com/nodejs/gyp-next/commit/cadca2416dc13e117e035ad6dd2b471a86d0430f))

## [0.22.0](https://github.com/nodejs/gyp-next/compare/v0.21.1...v0.22.0) (2026-04-02)


### Features

* Windows ARM64 target architecture support ([#331](https://github.com/nodejs/gyp-next/issues/331)) ([652a346](https://github.com/nodejs/gyp-next/commit/652a346bbd3b077a4b08a3c37d48100ce200758a))


### Bug Fixes

* drop deprecated Python module pkg_resources ([#333](https://github.com/nodejs/gyp-next/issues/333)) ([5b180d5](https://github.com/nodejs/gyp-next/commit/5b180d52d03aff062bdea1ad0209b82271c7eb4a))

## [0.21.1](https://github.com/nodejs/gyp-next/compare/v0.21.0...v0.21.1) (2026-01-24)


Expand Down
14 changes: 11 additions & 3 deletions gyp/pylib/gyp/MSVSVersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def DefaultToolset(self):
def _SetupScriptInternal(self, target_arch):
"""Returns a command (with arguments) to be used to set up the
environment."""
assert target_arch in ("x86", "x64"), "target_arch not supported"
assert target_arch in ("x86", "x64", "arm64"), "target_arch not supported"
# If WindowsSDKDir is set and SetEnv.Cmd exists then we are using the
# depot_tools build tools and should run SetEnv.Cmd to set up the
# environment. The check for WindowsSDKDir alone is not sufficient because
Expand All @@ -109,8 +109,16 @@ def _SetupScriptInternal(self, target_arch):
)

# Always use a native executable, cross-compiling if necessary.
host_arch = "amd64" if is_host_arch_x64 else "x86"
msvc_target_arch = "amd64" if target_arch == "x64" else "x86"
host_arch = (
"amd64"
if is_host_arch_x64
else (
"arm64"
if os.environ.get("PROCESSOR_ARCHITECTURE") == "ARM64"
else "x86"
)
)
msvc_target_arch = {"x64": "amd64"}.get(target_arch, target_arch)
arg = host_arch
if host_arch != msvc_target_arch:
arg += "_" + msvc_target_arch
Expand Down
5 changes: 2 additions & 3 deletions gyp/pylib/gyp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import shlex
import sys
import traceback
from importlib.metadata import version

import gyp.input
from gyp.common import GypError
Expand Down Expand Up @@ -491,9 +492,7 @@ def gyp_main(args):

options, build_files_arg = parser.parse_args(args)
if options.version:
import pkg_resources # noqa: PLC0415

print(f"v{pkg_resources.get_distribution('gyp-next').version}")
print(f"v{version('gyp-next')}")
return 0
build_files = build_files_arg

Expand Down
2 changes: 1 addition & 1 deletion gyp/pylib/gyp/generator/msvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ def _EscapeCommandLineArgumentForMSBuild(s):
"""Escapes a Windows command-line argument for use by MSBuild."""

def _Replace(match):
return (len(match.group(1)) / 2 * 4) * "\\" + '\\"'
return (len(match.group(1)) // 2 * 4) * "\\" + '\\"'

# Escape all quotes so that they are interpreted literally.
s = quote_replacer_regex2.sub(_Replace, s)
Expand Down
3 changes: 2 additions & 1 deletion gyp/pylib/gyp/generator/ninja.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def __init__(
if flavor == "win":
# See docstring of msvs_emulation.GenerateEnvironmentFiles().
self.win_env = {}
for arch in ("x86", "x64"):
for arch in ("x86", "x64", "arm64"):
self.win_env[arch] = "environment." + arch

# Relative path from build output dir to base dir.
Expand Down Expand Up @@ -2339,6 +2339,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name
master_ninja.variable("rc", "rc.exe")
master_ninja.variable("ml_x86", "ml.exe")
master_ninja.variable("ml_x64", "ml64.exe")
master_ninja.variable("ml_arm64", "armasm64.exe")
master_ninja.variable("mt", "mt.exe")
else:
master_ninja.variable("ld", CommandWithWrapper("LINK", wrappers, ld))
Expand Down
42 changes: 26 additions & 16 deletions gyp/pylib/gyp/generator/ninja_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,36 @@
from pathlib import Path

from gyp.generator import ninja
from gyp.MSVSVersion import SelectVisualStudioVersion


def _has_visual_studio():
"""Check if Visual Studio can be detected by gyp's registry-based detection."""
if not sys.platform.startswith("win"):
return False
try:
SelectVisualStudioVersion("auto", allow_fallback=False)
return True
except ValueError:
return False


class TestPrefixesAndSuffixes(unittest.TestCase):
@unittest.skipUnless(
_has_visual_studio(),
"requires Windows with a Visual Studio installation detected via the registry",
)
def test_BinaryNamesWindows(self):
# These cannot run on non-Windows as they require a VS installation to
# correctly handle variable expansion.
if sys.platform.startswith("win"):
writer = ninja.NinjaWriter(
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
)
spec = {"target_name": "wee"}
self.assertTrue(
writer.ComputeOutputFileName(spec, "executable").endswith(".exe")
)
self.assertTrue(
writer.ComputeOutputFileName(spec, "shared_library").endswith(".dll")
)
self.assertTrue(
writer.ComputeOutputFileName(spec, "static_library").endswith(".lib")
)
writer = ninja.NinjaWriter(
"foo", "wee", ".", ".", "build.ninja", ".", "build.ninja", "win"
)
spec = {"target_name": "wee"}
for key, ext in {
"executable": ".exe",
"shared_library": ".dll",
"static_library": ".lib",
}.items():
self.assertTrue(writer.ComputeOutputFileName(spec, key).endswith(ext))

def test_BinaryNamesLinux(self):
writer = ninja.NinjaWriter(
Expand Down
2 changes: 1 addition & 1 deletion gyp/pylib/gyp/mac_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ def _FindProvisioningProfile(self, profile, bundle_identifier):
# If the user has multiple provisioning profiles installed that can be
# used for ${bundle_identifier}, pick the most specific one (ie. the
# provisioning profile whose pattern is the longest).
selected_key = max(valid_provisioning_profiles, key=lambda v: len(v))
selected_key = max(valid_provisioning_profiles, key=len)
return valid_provisioning_profiles[selected_key]

def _LoadProvisioningProfile(self, profile_path):
Expand Down
2 changes: 1 addition & 1 deletion gyp/pylib/gyp/msvs_emulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ def GenerateEnvironmentFiles(
meet your requirement (e.g. for custom toolchains), you can pass
"-G ninja_use_custom_environment_files" to the gyp to suppress file
generation and use custom environment files prepared by yourself."""
archs = ("x86", "x64")
archs = ("x86", "x64", "arm64")
if generator_flags.get("ninja_use_custom_environment_files", 0):
cl_paths = {}
for arch in archs:
Expand Down
23 changes: 3 additions & 20 deletions gyp/pylib/packaging/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,10 @@
from . import requirements, specifiers, utils, version as version_module

T = typing.TypeVar("T")
if sys.version_info[:2] >= (3, 8): # pragma: no cover
from typing import Literal, TypedDict
else: # pragma: no cover
if typing.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict
else:
try:
from typing_extensions import Literal, TypedDict
except ImportError:

class Literal:
def __init_subclass__(*_args, **_kwargs):
pass

class TypedDict:
def __init_subclass__(*_args, **_kwargs):
pass

from typing import Literal, TypedDict

try:
ExceptionGroup
ExceptionGroup # Added in Python 3.11+
except NameError: # pragma: no cover

class ExceptionGroup(Exception): # noqa: N818
Expand Down Expand Up @@ -504,7 +487,7 @@ def __set_name__(self, _owner: "Metadata", name: str) -> None:
self.raw_name = _RAW_TO_EMAIL_MAPPING[name]

def __get__(self, instance: "Metadata", _owner: Type["Metadata"]) -> T:
# With Python 3.8, the caching can be replaced with functools.cached_property().
# With Python 3.8+, the caching can be replaced with functools.cached_property().
# No need to check the cache as attribute lookup will resolve into the
# instance's __dict__ before __get__ is called.
cache = instance.__dict__
Expand Down
16 changes: 2 additions & 14 deletions gyp/pylib/packaging/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,8 @@ def _normalize_string(string: str) -> str:
def _abi3_applies(python_version: PythonVersion) -> bool:
"""
Determine if the Python version supports abi3.

PEP 384 was first implemented in Python 3.2.
"""
return len(python_version) > 1 and tuple(python_version) >= (3, 2)
return len(python_version) > 1


def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> List[str]:
Expand All @@ -146,17 +144,7 @@ def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> List[str]:
has_ext = "_d.pyd" in EXTENSION_SUFFIXES
if with_debug or (with_debug is None and (has_refcount or has_ext)):
debug = "d"
if py_version < (3, 8):
with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
if with_pymalloc or with_pymalloc is None:
pymalloc = "m"
if py_version < (3, 3):
unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
if unicode_size == 4 or (
unicode_size is None and sys.maxunicode == 0x10FFFF
):
ucs4 = "u"
elif debug:
if debug:
# Debug builds can also load "normal" extension modules.
# We can also assume no UCS-4 or pymalloc requirement.
abis.append(f"cp{version}")
Expand Down
8 changes: 5 additions & 3 deletions gyp/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"

[project]
name = "gyp-next"
version = "0.21.1"
version = "0.22.1"
authors = [
{ name="Node.js contributors", email="ryzokuken@disroot.org" },
]
description = "A fork of the GYP build system for use in the Node.js projects"
readme = "README.md"
license = { file="LICENSE" }
requires-python = ">=3.8"
requires-python = ">=3.9"
dependencies = ["packaging>=24.0", "setuptools>=69.5.1"]
classifiers = [
"Development Status :: 3 - Alpha",
Expand All @@ -21,10 +21,12 @@ classifiers = [
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"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.optional-dependencies]
Expand Down
Loading