diff --git a/tests/packages/link-library-in-subproject/foo/__init__.py b/tests/packages/link-library-in-subproject/foo/__init__.py new file mode 100644 index 00000000..58482491 --- /dev/null +++ b/tests/packages/link-library-in-subproject/foo/__init__.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2024 The meson-python developers +# +# SPDX-License-Identifier: MIT + +from ._example import example_sum + + +__all__ = ['example_sum'] diff --git a/tests/packages/link-library-in-subproject/foo/_examplemod.c b/tests/packages/link-library-in-subproject/foo/_examplemod.c new file mode 100644 index 00000000..d6955699 --- /dev/null +++ b/tests/packages/link-library-in-subproject/foo/_examplemod.c @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2022 The meson-python developers +// +// SPDX-License-Identifier: MIT + +#include + +#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); +} diff --git a/tests/packages/link-library-in-subproject/foo/meson.build b/tests/packages/link-library-in-subproject/foo/meson.build new file mode 100644 index 00000000..a171be52 --- /dev/null +++ b/tests/packages/link-library-in-subproject/foo/meson.build @@ -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', +) diff --git a/tests/packages/link-library-in-subproject/meson.build b/tests/packages/link-library-in-subproject/meson.build new file mode 100644 index 00000000..eaa82951 --- /dev/null +++ b/tests/packages/link-library-in-subproject/meson.build @@ -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') diff --git a/tests/packages/link-library-in-subproject/pyproject.toml b/tests/packages/link-library-in-subproject/pyproject.toml new file mode 100644 index 00000000..212bb3d1 --- /dev/null +++ b/tests/packages/link-library-in-subproject/pyproject.toml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2022 The meson-python developers +# +# SPDX-License-Identifier: MIT + +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] + +[project] +name = 'link-library-in-subproject' +version = '1.2.3' + +[tool.meson-python.args] +setup = ['--default-library=static'] +install = ['--skip-subprojects'] diff --git a/tests/packages/link-library-in-subproject/subprojects/bar/bar_dll.h b/tests/packages/link-library-in-subproject/subprojects/bar/bar_dll.h new file mode 100644 index 00000000..61a6d7bc --- /dev/null +++ b/tests/packages/link-library-in-subproject/subprojects/bar/bar_dll.h @@ -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 diff --git a/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.c b/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.c new file mode 100644 index 00000000..7efb3667 --- /dev/null +++ b/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.c @@ -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; +} diff --git a/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.h b/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.h new file mode 100644 index 00000000..c0f9e5ec --- /dev/null +++ b/tests/packages/link-library-in-subproject/subprojects/bar/examplelib.h @@ -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); diff --git a/tests/packages/link-library-in-subproject/subprojects/bar/meson.build b/tests/packages/link-library-in-subproject/subprojects/bar/meson.build new file mode 100644 index 00000000..503257bc --- /dev/null +++ b/tests/packages/link-library-in-subproject/subprojects/bar/meson.build @@ -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: '.', +) diff --git a/tests/test_wheel.py b/tests/test_wheel.py index a663d15b..5b3f679d 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -169,6 +169,13 @@ def test_sharedlib_in_package(venv, wheel_sharedlib_in_package): assert int(output) == 42 +@pytest.mark.skipif(MESON_VERSION < (1, 3, 0), reason='Meson version too old') +def test_link_library_in_subproject(venv, wheel_link_library_in_subproject): + venv.pip('install', wheel_link_library_in_subproject) + output = venv.python('-c', 'import foo; print(foo.example_sum(3, 6))') + assert int(output) == 9 + + @pytest.mark.skipif(sys.platform not in {'linux', 'darwin', 'sunos5'}, reason='Not supported on this platform') def test_rpath(wheel_link_against_local_lib, tmp_path): artifact = wheel.wheelfile.WheelFile(wheel_link_against_local_lib)