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
55 changes: 17 additions & 38 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ jobs:
- '3.13'
meson:
-
pyproject_metadata:
dependencies:
-
hatchling:
-
include:
- os: ubuntu-latest
python: 'pypy-3.9'
- os: ubuntu-latest
python: 'pypy-3.10'
python: 'pypy-3.11'
- os: ubuntu-latest
python: '3.8'
- os: ubuntu-latest
Expand All @@ -88,6 +88,8 @@ jobs:
# Test with older supported Meson version. Meson up to
# version 1.2.3 requires distutils, which has been removed
# from the stdlib in Python 3.12, thus test with Pythn 3.11.
# To avoid having too many CI jobs, combine this with tests
# with the minimum version of other dependencies.
- os: ubuntu-latest
python: '3.11'
meson: '~=0.64.0'
Expand All @@ -109,6 +111,15 @@ jobs:
- os: ubuntu-latest
python: '3.12'
meson: '~=1.5.0'
dependencies: 'packaging==23.2 pyproject-metadata==0.9.0'
- os: ubuntu-latest
python: '3.12'
meson: '~=1.6.0'
dependencies: 'pyproject-metadata==0.9.0'
- os: ubuntu-latest
python: '3.12'
meson: '~=1.7.0'
dependencies: 'packaging==23.2'
# Test with Meson master branch.
- os: ubuntu-latest
python: '3.12'
Expand Down Expand Up @@ -153,14 +164,14 @@ jobs:
run: python -m pip install "meson ${{ matrix.meson }}"
if: ${{ matrix.meson }}

- name: Install pyproject-metadata
run: python -m pip install "pyproject-metadata ${{ matrix.pyproject_metadata }}"
if: ${{ matrix.pyproject_metadata }}

- name: Install hatchling
run: python -m pip install "hatchling ${{ matrix.hatchling }}"
if: ${{ matrix.hatchling }}

- name: Install dependencies
run: python -m pip install ${{ matrix.dependencies }}
if: ${{ matrix.dependencies }}

- name: Install
shell: bash
working-directory: dist
Expand Down Expand Up @@ -303,38 +314,6 @@ jobs:
run: python -m pytest --showlocals -vv
shell: C:\cygwin\bin\env.exe CYGWIN_NOWINPATH=1 CHERE_INVOKING=1 C:\cygwin\bin\bash.exe -leo pipefail -o igncr {0}

# pyston:
# runs-on: ubuntu-20.04
# strategy:
# fail-fast: false
# matrix:
# python:
# - '3.8'
# meson:
# -

# steps:
# - name: Checkout
# uses: actions/checkout@v4

# - name: Install pyston
# run: |
# wget https://github.com/pyston/pyston/releases/download/pyston_2.3.5/pyston_2.3.5_20.04_amd64.deb
# sudo apt install $(pwd)/pyston_2.3.5_20.04_amd64.deb

# - name: Install Ninja
# run: sudo apt-get install ninja-build

# - name: Install Meson
# run: python -m pip install "meson ${{ matrix.meson }}"
# if: ${{ matrix.meson }}

# - name: Install
# run: pyston -m pip install .[test]

# - name: Run tests
# run: pyston -m pytest --showlocals -vv

homebrew:
needs: [build]
runs-on: macos-latest
Expand Down
24 changes: 21 additions & 3 deletions src/hatch_meson/_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,8 @@ def _get_macosx_platform_tag() -> str:
# Override the macOS version if one is provided via the
# MACOSX_DEPLOYMENT_TARGET environment variable.
try:
version = tuple(
map(int, os.environ.get("MACOSX_DEPLOYMENT_TARGET", "").split("."))
)[:2]
parts = os.environ.get("MACOSX_DEPLOYMENT_TARGET", "").split(".")[:2]
version = tuple(map(int, parts + ["0"] * (2 - len(parts))))
except ValueError:
version = tuple(map(int, ver.split(".")))[:2]

Expand Down Expand Up @@ -164,10 +163,29 @@ def _get_macosx_platform_tag() -> str:
return f"macosx_{major}_{minor}_{arch}"


def _get_ios_platform_tag() -> str:
# Override the iOS version if one is provided via the
# IPHONEOS_DEPLOYMENT_TARGET environment variable.
try:
parts = os.environ.get("IPHONEOS_DEPLOYMENT_TARGET", "").split(".")[:2]
version = tuple(map(int, parts + ["0"] * (2 - len(parts))))
except ValueError:
version = tuple(map(int, platform.ios_ver().release.split(".")))[:2] # type: ignore[attr-defined]

# Although _multiarch is an internal implementation detail, it's a core part
# of how CPython is implemented on iOS; this attribute is also relied upon
# by `packaging` as part of tag determiniation.
multiarch = sys.implementation._multiarch.replace("-", "_")

return f"ios_{version[0]}_{version[1]}_{multiarch}"


def get_platform_tag() -> str:
platform = sysconfig.get_platform()
if platform.startswith("macosx"):
return _get_macosx_platform_tag()
if platform.startswith("ios"):
return _get_ios_platform_tag()
if _32_BIT_INTERPRETER:
# 32-bit Python running on a 64-bit kernel.
if platform == "linux-x86_64":
Expand Down
31 changes: 31 additions & 0 deletions src/hatch_meson/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ def _create_macos_crossfile(crossfile_path: pathlib.Path) -> bool:
cpp = ['c++', '-arch', {arch!r}]
objc = ['cc', '-arch', {arch!r}]
objcpp = ['c++', '-arch', {arch!r}]
strip = ['strip', '-arch', {arch!r}]
[host_machine]
system = 'darwin'
cpu = {arch!r}
Expand All @@ -696,4 +697,34 @@ def _create_macos_crossfile(crossfile_path: pathlib.Path) -> bool:
crossfile_path.write_text(cross_file_data, encoding="utf-8")
return True

# Support iOS targets. iOS does not have native build tools and always
# requires cross compilation: synthesize the appropriate cross file.
elif sysconfig.get_platform().startswith("ios-"):
ios_ver = platform.ios_ver() # type: ignore[attr-defined]

arch = platform.machine()
family = "aarch64" if arch == "arm64" else arch
subsystem = "ios-simulator" if ios_ver.is_simulator else "ios"

cross_file_data = textwrap.dedent(
f"""
[binaries]
ar = '{arch}-apple-{subsystem}-ar'
c = '{arch}-apple-{subsystem}-clang'
cpp = '{arch}-apple-{subsystem}-clang++'
objc = '{arch}-apple-{subsystem}-clang'
objcpp = '{arch}-apple-{subsystem}-clang++'
strip = '{arch}-apple-{subsystem}-strip'

[host_machine]
system = 'ios'
subsystem = {subsystem!r}
cpu = {arch!r}
cpu_family = {family!r}
endian = 'little'
"""
)
crossfile_path.write_text(cross_file_data, encoding="utf-8")
return True

return False
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,12 @@ def disable_pip_version_check():
mpatch = pytest.MonkeyPatch()
yield mpatch.setenv("PIP_DISABLE_PIP_VERSION_CHECK", "1")
mpatch.undo()


@pytest.fixture(autouse=True, scope="session")
def cleanenv():
# Cannot use the 'monkeypatch' fixture because of scope mismatch.
mpatch = pytest.MonkeyPatch()
# $MACOSX_DEPLOYMENT_TARGET affects the computation of the platform tag on macOS.
yield mpatch.delenv("MACOSX_DEPLOYMENT_TARGET", raising=False)
mpatch.undo()
8 changes: 8 additions & 0 deletions tests/packages/link-library-in-subproject/foo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: 2024 The meson-python developers
#
# SPDX-License-Identifier: MIT

from ._example import example_sum


__all__ = ["example_sum"]
37 changes: 37 additions & 0 deletions tests/packages/link-library-in-subproject/foo/_examplemod.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2022 The meson-python developers
//
// SPDX-License-Identifier: MIT

#include <Python.h>

#include "examplelib.h"

static PyObject* example_sum(PyObject* self, PyObject *args)
{
int a, b;
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL;
}

long result = sum(a, b);

return PyLong_FromLong(result);
}

static PyMethodDef methods[] = {
{"example_sum", (PyCFunction)example_sum, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL},
};

static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"_example",
NULL,
-1,
methods,
};

PyMODINIT_FUNC PyInit__example(void)
{
return PyModule_Create(&module);
}
16 changes: 16 additions & 0 deletions tests/packages/link-library-in-subproject/foo/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2022 The meson-python developers
#
# SPDX-License-Identifier: MIT

py.extension_module(
'_example',
'_examplemod.c',
dependencies: bar_dep,
install: true,
subdir: 'foo',
)

py.install_sources(
['__init__.py'],
subdir: 'foo',
)
17 changes: 17 additions & 0 deletions tests/packages/link-library-in-subproject/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2022 The meson-python developers
#
# SPDX-License-Identifier: MIT

project(
'link-library-in-subproject',
'c',
version: '1.0.0',
meson_version: '>=1.2.0',
)

py = import('python').find_installation(pure: false)

bar_proj = subproject('bar')
bar_dep = bar_proj.get_variable('bar_dep')

subdir('foo')
15 changes: 15 additions & 0 deletions tests/packages/link-library-in-subproject/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2022 The meson-python developers
#
# SPDX-License-Identifier: MIT

[build-system]
build-backend = "hatchling.build"
requires = ["hatch-meson"]

[project]
name = 'link-library-in-subproject'
version = '1.2.3'

[tool.hatch.build.hooks.meson.args]
setup = ['--default-library=static']
install = ['--skip-subprojects']
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2024 The meson-python developers
//
// SPDX-License-Identifier: MIT

#pragma once

// When building the `examplelib` DLL, this macro expands to `__declspec(dllexport)`
// so we can annotate symbols appropriately as being exported. When used in
// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
// that consumers know the symbol is defined inside the DLL. In all other cases,
// the macro expands to nothing.
// Note: BAR_DLL_{EX,IM}PORTS are set in meson.build
#if defined(BAR_DLL_EXPORTS)
#define BAR_DLL __declspec(dllexport)
#elif defined(BAR_DLL_IMPORTS)
#define BAR_DLL __declspec(dllimport)
#else
#define BAR_DLL
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2022 The meson-python developers
//
// SPDX-License-Identifier: MIT

#include "bar_dll.h"

BAR_DLL int sum(int a, int b) {
return a + b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2022 The meson-python developers
//
// SPDX-License-Identifier: MIT

#include "bar_dll.h"

BAR_DLL int sum(int a, int b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: 2022 The meson-python developers
#
# SPDX-License-Identifier: MIT

project('bar', 'c', version: '1.2.3', meson_version: '>= 1.3.0')

if get_option('default_library') == 'shared' and meson.get_compiler('c').get_id() in ['msvc', 'clang-cl', 'intel-cl']
export_dll_args = ['-DBAR_DLL_EXPORTS']
import_dll_args = ['-DBAR_DLL_IMPORTS']
else
export_dll_args = []
import_dll_args = []
endif

example_lib = library(
'examplelib',
'examplelib.c',
c_shared_args: export_dll_args,
install: true,
)

# A second library that we don't link from `foo`. If we install the subproject,
# this second library also ends up in the wheel. To prevent that, we need to
# skip installing this `bar` subproject, and statically link `example_lib`.
unwanted_lib = library(
'unwantedlib',
'examplelib.c',
c_shared_args: export_dll_args,
install: true,
)

bar_dep = declare_dependency(
compile_args: import_dll_args,
link_with: example_lib,
include_directories: '.',
)
9 changes: 9 additions & 0 deletions tests/packages/sharedlib-in-package/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: 2022 The meson-python developers
#
# SPDX-License-Identifier: MIT

project('sharedlib-in-package', 'c', version: '1.0.0')

py = import('python').find_installation(pure: false)

subdir('mypkg')
Loading
Loading