Skip to content

Commit

Permalink
BUG: Fix generated sources not being included as dependencies in cyth…
Browse files Browse the repository at this point in the history
…on transpilation
  • Loading branch information
lithomas1 committed Jan 15, 2023
1 parent 58cfd8f commit def41be
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 0 deletions.
14 changes: 14 additions & 0 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,8 @@ def generate_cython_transpile(self, target: build.BuildTarget) -> \

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}')
Expand All @@ -1711,9 +1713,11 @@ def generate_cython_transpile(self, target: build.BuildTarget) -> \
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):
Expand All @@ -1730,10 +1734,20 @@ def generate_cython_transpile(self, target: build.BuildTarget) -> \
[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

Expand Down
1 change: 1 addition & 0 deletions test cases/cython/2 generated sources/includestuff.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include "stuff.pxi"
20 changes: 20 additions & 0 deletions test cases/cython/2 generated sources/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions test cases/cython/2 generated sources/stuff.pxi.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def func():
print("Hello world")
26 changes: 26 additions & 0 deletions unittests/allplatformstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,32 @@ def test_build_by_default(self):
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')
Expand Down

0 comments on commit def41be

Please sign in to comment.