From b360ef4818f2c918308171b7fc176b6a14a42af4 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 8 Jun 2026 09:27:29 +0200 Subject: [PATCH] build_py: filter directory symlinks from manifest_files in non-editable mode Recent setuptools includes bare directory symlinks (e.g. src/executorch/backends -> ../../backends) from version control in manifest_files. These exist for editable mode but break regular installs: build_package_data passes them to copy_file, which calls os.path.isfile() and gets False for a symlink-to-directory. Override analyze_manifest() to filter out non-regular-file entries after the parent populates manifest_files, guarded by editable_mode. --- setup.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/setup.py b/setup.py index 85228bd37ae..881ff49ab84 100644 --- a/setup.py +++ b/setup.py @@ -684,6 +684,21 @@ class CustomBuildPy(build_py): a file to a different relative location under the output package directory. """ + def analyze_manifest(self): + super().analyze_manifest() + # Recent versions of setuptools may include bare directory symlinks from version + # control (e.g. src/executorch/{backends,codegen,data,...} -> + # ../../) in manifest_files. These exist for editable mode but + # break regular installs: build_package_data passes them to copy_file, + # which calls os.path.isfile() and gets False for a symlink-to-directory. + if not self.editable_mode: + _root = os.path.dirname(os.path.abspath(__file__)) + for _pkg in list(self.manifest_files): + self.manifest_files[_pkg] = [ + _f for _f in self.manifest_files[_pkg] + if os.path.isfile(os.path.join(_root, _f)) + ] + def run(self): # Copy python files to the output directory. This set of files is # defined by the py_module list and package_data patterns.