diff --git a/meta/classes-recipe/cython.bbclass b/meta/classes-recipe/cython.bbclass
index 53b84f5f5eb..dd9fc732bcb 100644
--- a/meta/classes-recipe/cython.bbclass
+++ b/meta/classes-recipe/cython.bbclass
@@ -1,8 +1,5 @@
 DEPENDS:append = " python3-cython-native"
 
-# Remap the build paths that appear in generated .c code
-export CYTHON_PREFIX_MAP = "${S}=${TARGET_DBGSRC_DIR} ${B}=${TARGET_DBGSRC_DIR}"
-
 do_compile[postfuncs] = "strip_cython_metadata"
 strip_cython_metadata() {
     # Remove the Cython Metadata headers that we don't need after the build, and
diff --git a/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch b/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch
new file mode 100644
index 00000000000..bbafc294163
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch
@@ -0,0 +1,73 @@
+From 9b5f3b09f76899eba510c2d8f3ed2b0f752a4d1b Mon Sep 17 00:00:00 2001
+From: Oscar Benjamin <oscar.j.benjamin@gmail.com>
+Date: Sat, 24 Aug 2024 08:30:31 +0100
+Subject: [PATCH] Output import-relative paths in generated C code. (GH-6341)
+
+When cython is run on a file that is not in the current working directory,
+it outputs filepaths that are either absolute or are basenames.
+It is not good to output absolute paths in the generated C code and
+basenames mess up coverage measurement.
+
+Upstream-Status: Backport [20bceea6b19ffc2f65b9fba2e4f737f09e5a2b20]
+Signed-off-by: Ross Burton <ross.burton@arm.com>
+---
+ Cython/Compiler/ExprNodes.py  | 8 +++++++-
+ Cython/Compiler/ModuleNode.py | 9 ++++++---
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
+index a6bb1688e..0fbb15368 100644
+--- a/Cython/Compiler/ExprNodes.py
++++ b/Cython/Compiler/ExprNodes.py
+@@ -21,6 +21,7 @@ import re
+ import sys
+ import copy
+ import os.path
++import pathlib
+ import operator
+ 
+ from .Errors import (
+@@ -10072,7 +10073,12 @@ class CodeObjectNode(ExprNode):
+         func_name = code.get_py_string_const(
+             func.name, identifier=True, is_str=False, unicode_value=func.name)
+         # FIXME: better way to get the module file path at module init time? Encoding to use?
+-        file_path = StringEncoding.bytes_literal(func.pos[0].get_filenametable_entry().encode('utf8'), 'utf8')
++        file_path = func.pos[0].get_filenametable_entry()
++        if os.path.isabs(file_path):
++            file_path = func.pos[0].get_description()
++        # Always use / as separator
++        file_path = pathlib.Path(file_path).as_posix()
++        file_path = StringEncoding.bytes_literal(file_path.encode('utf-8'), 'utf8')
+         file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True)
+ 
+         # This combination makes CPython create a new dict for "frame.f_locals" (see GH #1836).
+diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
+index 43c6b5f07..8c29d6db7 100644
+--- a/Cython/Compiler/ModuleNode.py
++++ b/Cython/Compiler/ModuleNode.py
+@@ -13,6 +13,7 @@ from collections import defaultdict
+ import json
+ import operator
+ import os
++import pathlib
+ import re
+ import sys
+ 
+@@ -944,9 +945,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+             for source_desc in code.globalstate.filename_list:
+                 file_path = source_desc.get_filenametable_entry()
+                 if isabs(file_path):
+-                    file_path = basename(file_path)  # never include absolute paths
+-                escaped_filename = file_path.replace("\\", "\\\\").replace('"', r'\"')
+-                escaped_filename = as_encoded_filename(escaped_filename)
++                    # never include absolute paths
++                    file_path = source_desc.get_description()
++                # Always use / as separator
++                file_path = pathlib.Path(file_path).as_posix()
++                escaped_filename = as_encoded_filename(file_path)
+                 code.putln('%s,' % escaped_filename.as_c_string_literal())
+         else:
+             # Some C compilers don't like an empty array
+-- 
+2.34.1
+
diff --git a/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch b/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch
deleted file mode 100644
index adc9463ffa7..00000000000
--- a/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-From 4d1b7911372561b22e03c7f2b4ec807502b5b9c1 Mon Sep 17 00:00:00 2001
-From: Ross Burton <ross.burton@arm.com>
-Date: Mon, 4 Nov 2024 15:36:39 +0000
-Subject: [PATCH] WIP prefix map
-
-Upstream-Status: Inappropriate
-Signed-off-by: Ross Burton <ross.burton@arm.com>
----
- Cython/Compiler/CmdLine.py  | 9 ++++++++-
- Cython/Compiler/Main.py     | 9 +++++----
- Cython/Compiler/Options.py  | 1 +
- Cython/Compiler/Parsing.py  | 1 +
- Cython/Compiler/Scanning.py | 9 +++++++--
- 5 files changed, 22 insertions(+), 7 deletions(-)
-
-diff --git a/Cython/Compiler/CmdLine.py b/Cython/Compiler/CmdLine.py
-index 776636c..f5a7c79 100644
---- a/Cython/Compiler/CmdLine.py
-+++ b/Cython/Compiler/CmdLine.py
-@@ -74,6 +74,12 @@ class SetAnnotateCoverageAction(Action):
-         namespace.annotate = True
-         namespace.annotate_coverage_xml = values
- 
-+class SetPrefixMapAction(Action):
-+    def __call__(self, parser, namespace, values, option_string=None):
-+        mappings = getattr(namespace, self.dest, {})
-+        k, v = values.split("=", 1)
-+        mappings[k] = v
-+        setattr(namespace, self.dest, mappings)
- 
- def create_cython_argparser():
-     description = "Cython (https://cython.org/) is a compiler for code written in the "\
-@@ -157,9 +163,10 @@ def create_cython_argparser():
-                            'deduced from the import path if source file is in '
-                            'a package, or equals the filename otherwise.')
-     parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
-+    # TODO: add help
-+    parser.add_argument("--prefix-map", action=SetPrefixMapAction)
-     parser.add_argument('sources', nargs='*', default=[])
- 
--    # TODO: add help
-     parser.add_argument("-z", "--pre-import", dest='pre_import', action='store', type=str, help=SUPPRESS)
-     parser.add_argument("--convert-range", dest='convert_range', action='store_true', help=SUPPRESS)
-     parser.add_argument("--no-c-in-traceback", dest='c_line_in_traceback', action='store_false', help=SUPPRESS)
-diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py
-index 80946c0..28cfe68 100644
---- a/Cython/Compiler/Main.py
-+++ b/Cython/Compiler/Main.py
-@@ -70,7 +70,7 @@ class Context(object):
-     language_level = None  # warn when not set but default to Py2
- 
-     def __init__(self, include_directories, compiler_directives, cpp=False,
--                 language_level=None, options=None):
-+                 language_level=None, prefix_map=None, options=None):
-         # cython_scope is a hack, set to False by subclasses, in order to break
-         # an infinite loop.
-         # Better code organization would fix it.
-@@ -83,6 +83,7 @@ class Context(object):
-         self.future_directives = set()
-         self.compiler_directives = compiler_directives
-         self.cpp = cpp
-+        self.prefix_map = prefix_map or {}
-         self.options = options
- 
-         self.pxds = {}  # full name -> node tree
-@@ -98,7 +99,7 @@ class Context(object):
-     @classmethod
-     def from_options(cls, options):
-         return cls(options.include_path, options.compiler_directives,
--                   options.cplus, options.language_level, options=options)
-+                   options.cplus, options.language_level, prefix_map=options.prefix_map, options=options)
- 
-     def set_language_level(self, level):
-         from .Future import print_function, unicode_literals, absolute_import, division, generator_stop
-@@ -259,7 +260,7 @@ class Context(object):
-                     rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
-                     if not pxd_pathname.endswith(rel_path):
-                         rel_path = pxd_pathname  # safety measure to prevent printing incorrect paths
--                    source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
-+                    source_desc = FileSourceDescriptor(pxd_pathname, rel_path, prefix_map=self.prefix_map)
-                     err, result = self.process_pxd(source_desc, scope, qualified_name)
-                     if err:
-                         raise err
-@@ -509,7 +510,7 @@ def run_pipeline(source, options, full_module_name=None, context=None):
-             rel_path = source  # safety measure to prevent printing incorrect paths
-     else:
-         rel_path = abs_path
--    source_desc = FileSourceDescriptor(abs_path, rel_path)
-+    source_desc = FileSourceDescriptor(abs_path, rel_path, prefix_map=context.prefix_map)
-     source = CompilationSource(source_desc, full_module_name, cwd)
- 
-     # Set up result object
-diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py
-index 61950a7..cc52732 100644
---- a/Cython/Compiler/Options.py
-+++ b/Cython/Compiler/Options.py
-@@ -796,4 +796,5 @@ default_options = dict(
-     create_extension=None,
-     np_pythran=False,
-     legacy_implicit_noexcept=None,
-+    prefix_map=dict(pair.split("=", 1) for pair in os.environ.get("CYTHON_PREFIX_MAP", "").split()),
- )
-diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py
-index 25c0de9..6c0eccf 100644
---- a/Cython/Compiler/Parsing.py
-+++ b/Cython/Compiler/Parsing.py
-@@ -2106,6 +2106,7 @@ def p_include_statement(s, ctx):
-             s.included_files.append(include_file_name)
-             with Utils.open_source_file(include_file_path) as f:
-                 source_desc = FileSourceDescriptor(include_file_path)
-+                print(f"TODO Cannot use prefix map on {include_file_path}")
-                 s2 = PyrexScanner(f, source_desc, s, source_encoding=f.encoding, parse_comments=s.parse_comments)
-                 tree = p_statement_list(s2, ctx)
-             return tree
-diff --git a/Cython/Compiler/Scanning.py b/Cython/Compiler/Scanning.py
-index 372392b..0fa3b30 100644
---- a/Cython/Compiler/Scanning.py
-+++ b/Cython/Compiler/Scanning.py
-@@ -195,7 +195,7 @@ class FileSourceDescriptor(SourceDescriptor):
-     optional name argument and will be passed back when asking for
-     the position()-tuple.
-     """
--    def __init__(self, filename, path_description=None):
-+    def __init__(self, filename, path_description=None, prefix_map={}):
-         filename = Utils.decode_filename(filename)
-         self.path_description = path_description or filename
-         self.filename = filename
-@@ -205,6 +205,7 @@ class FileSourceDescriptor(SourceDescriptor):
-         self.set_file_type_from_name(filename)
-         self._cmp_name = filename
-         self._lines = {}
-+        self.prefix_map = prefix_map
- 
-     def get_lines(self, encoding=None, error_handling=None):
-         # we cache the lines only the second time this is called, in
-@@ -243,7 +244,11 @@ class FileSourceDescriptor(SourceDescriptor):
-         return path
- 
-     def get_filenametable_entry(self):
--        return self.file_path
-+        entry = self.file_path
-+        for k, v in self.prefix_map.items():
-+            # TODO: should just replace the prefix
-+            entry = entry.replace(k, v)
-+        return entry
- 
-     def __eq__(self, other):
-         return isinstance(other, FileSourceDescriptor) and self.filename == other.filename
diff --git a/meta/recipes-devtools/python/python3-cython_3.0.11.bb b/meta/recipes-devtools/python/python3-cython_3.0.11.bb
index 020a8e7205c..2501e6ed232 100644
--- a/meta/recipes-devtools/python/python3-cython_3.0.11.bb
+++ b/meta/recipes-devtools/python/python3-cython_3.0.11.bb
@@ -7,7 +7,7 @@ SECTION = "devel/python"
 LICENSE = "Apache-2.0"
 LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=61c3ee8961575861fa86c7e62bc9f69c"
 
-SRC_URI += "file://0001-WIP-prefix-map.patch"
+SRC_URI += "file://0001-Output-import-relative-paths-in-generated-C-code.-GH.patch"
 SRC_URI[sha256sum] = "7146dd2af8682b4ca61331851e6aebce9fe5158e75300343f80c07ca80b1faff"
 
 inherit pypi setuptools3 cython
