aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Li <47963215+lithomas1@users.noreply.github.com>2022-11-04 18:19:44 -0400
committerEli Schwartz <eschwartz93@gmail.com>2023-01-15 16:59:47 -0500
commit9b999ddc874cfba34c3d1c67f75aba037389e65f (patch)
tree076c7f0175030ff4cff14ef535a1f222d8558d9f
parent58cfd8fc2c6f1ec871f227e99ae4ed06eb95d92d (diff)
downloadmeson-9b999ddc874cfba34c3d1c67f75aba037389e65f.zip
meson-9b999ddc874cfba34c3d1c67f75aba037389e65f.tar.gz
meson-9b999ddc874cfba34c3d1c67f75aba037389e65f.tar.bz2
BUG: Fix generated sources not being included as dependencies in cython transpilation
-rw-r--r--mesonbuild/backend/ninjabackend.py14
-rw-r--r--test cases/cython/2 generated sources/includestuff.pyx1
-rw-r--r--test cases/cython/2 generated sources/meson.build20
-rw-r--r--test cases/cython/2 generated sources/stuff.pxi.in2
-rw-r--r--unittests/allplatformstests.py26
5 files changed, 63 insertions, 0 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 3c8bb81..a83913d 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1698,6 +1698,8 @@ class NinjaBackend(backends.Backend):
ext = target.get_option(OptionKey('language', machine=target.for_machine, lang='cython'))
+ pyx_sources = [] # Keep track of sources we're adding to build
+
for src in target.get_sources():
if src.endswith('.pyx'):
output = os.path.join(self.get_target_private_dir(target), f'{src}.{ext}')
@@ -1711,9 +1713,11 @@ class NinjaBackend(backends.Backend):
self.add_build(element)
# TODO: introspection?
cython_sources.append(output)
+ pyx_sources.append(element)
else:
static_sources[src.rel_to_builddir(self.build_to_src)] = src
+ header_deps = [] # Keep track of generated headers for those sources
for gen in target.get_generated_sources():
for ssrc in gen.get_outputs():
if isinstance(gen, GeneratedList):
@@ -1730,10 +1734,20 @@ class NinjaBackend(backends.Backend):
[ssrc])
element.add_item('ARGS', args)
self.add_build(element)
+ pyx_sources.append(element)
# TODO: introspection?
cython_sources.append(output)
else:
generated_sources[ssrc] = mesonlib.File.from_built_file(gen.get_subdir(), ssrc)
+ # Following logic in L883-900 where we determine whether to add generated source
+ # as a header(order-only) dep to the .so compilation rule
+ if not self.environment.is_source(ssrc) and \
+ not self.environment.is_object(ssrc) and \
+ not self.environment.is_library(ssrc) and \
+ not modules.is_module_library(ssrc):
+ header_deps.append(ssrc)
+ for source in pyx_sources:
+ source.add_orderdep(header_deps)
return static_sources, generated_sources, cython_sources
diff --git a/test cases/cython/2 generated sources/includestuff.pyx b/test cases/cython/2 generated sources/includestuff.pyx
new file mode 100644
index 0000000..83f881b
--- /dev/null
+++ b/test cases/cython/2 generated sources/includestuff.pyx
@@ -0,0 +1 @@
+include "stuff.pxi"
diff --git a/test cases/cython/2 generated sources/meson.build b/test cases/cython/2 generated sources/meson.build
index cfe6260..cffddd3 100644
--- a/test cases/cython/2 generated sources/meson.build
+++ b/test cases/cython/2 generated sources/meson.build
@@ -6,6 +6,7 @@ project(
py_mod = import('python')
py3 = py_mod.find_installation('python3')
py3_dep = py3.dependency(required : false)
+fs = import('fs')
if not py3_dep.found()
error('MESON_SKIP_TEST: Python library not found.')
endif
@@ -70,6 +71,25 @@ test(
env : ['PYTHONPATH=' + meson.current_build_dir()]
)
+stuff_pxi = fs.copyfile(
+ 'stuff.pxi.in',
+ 'stuff.pxi'
+)
+
+# Need to copy the cython source to the build directory
+# since meson can only generate the .pxi there
+includestuff_pyx = fs.copyfile(
+ 'includestuff.pyx'
+)
+
+stuff_pxi_dep = declare_dependency(sources: stuff_pxi)
+
+includestuff_ext = py3.extension_module(
+ 'includestuff',
+ includestuff_pyx,
+ dependencies: stuff_pxi_dep
+)
+
subdir('libdir')
test(
diff --git a/test cases/cython/2 generated sources/stuff.pxi.in b/test cases/cython/2 generated sources/stuff.pxi.in
new file mode 100644
index 0000000..6417cbc
--- /dev/null
+++ b/test cases/cython/2 generated sources/stuff.pxi.in
@@ -0,0 +1,2 @@
+def func():
+ print("Hello world")
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 8b78590..351f79d 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -833,6 +833,32 @@ class AllPlatformTests(BasePlatformTests):
self.build(target=('barprog' + exe_suffix))
self.assertPathExists(exe2)
+ def test_build_generated_pyx_directly(self):
+ # Check that the transpile stage also includes
+ # dependencies for the compilation stage as dependencies
+ testdir = os.path.join("test cases/cython", '2 generated sources')
+ env = get_fake_env(testdir, self.builddir, self.prefix)
+ try:
+ detect_compiler_for(env, "cython", MachineChoice.HOST)
+ except EnvironmentException:
+ raise SkipTest("Cython is not installed")
+ self.init(testdir)
+ # Need to get the full target name of the pyx.c target
+ # (which is unfortunately not provided by introspection :( )
+ # We'll need to dig into the generated sources
+ targets = self.introspect('--targets')
+ name = None
+ for target in targets:
+ for target_sources in target["target_sources"]:
+ for generated_source in target_sources["generated_sources"]:
+ if "includestuff.pyx.c" in generated_source:
+ name = generated_source
+ break
+ # Split the path (we only want the includestuff.cpython-blahblahblah)
+ name = os.path.normpath(name).split("/")[-2:]
+ name = "/".join(name) # Glue list into a string
+ self.build(target=name)
+
def test_internal_include_order(self):
if mesonbuild.environment.detect_msys2_arch() and ('MESON_RSP_THRESHOLD' in os.environ):
raise SkipTest('Test does not yet support gcc rsp files on msys2')