Skip to content

Commit f7fb705

Browse files
committed
Remove libclang's bundled CPython
1 parent a95fdb5 commit f7fb705

4 files changed

Lines changed: 87 additions & 1 deletion

File tree

‎compile_all.py‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,19 @@ def build_libclang(self, _=None):
14981498
print(" Not copying libclang, it is already in the LibPack")
14991499
return
15001500
print(" (not really building libclang, just copying from a build provided by Qt)")
1501-
shutil.copytree("libclang", self.install_dir, dirs_exist_ok=True)
1501+
1502+
# Skip libclang's bundled CPython (bin/python3XX.dll and python3XX.zip), which would
1503+
# otherwise clobber the LibPack's own Python and shadow its stdlib.
1504+
def ignore_bundled_python(directory, names):
1505+
return [
1506+
name
1507+
for name in names
1508+
if re.fullmatch(r"python\w*\.(dll|zip|exe|pdb)", name, re.IGNORECASE)
1509+
]
1510+
1511+
shutil.copytree(
1512+
"libclang", self.install_dir, dirs_exist_ok=True, ignore=ignore_bundled_python
1513+
)
15021514

15031515
def build_pyside(self, _=None):
15041516
# Don't use a pip-install for this, we need the linkable libraries and include files for both PySide and

‎create_libpack.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ def prevent_sleep_mode():
682682
path_cleaner.delete_llvm_executables(base_path)
683683
path_cleaner.delete_clang_executables(base_path)
684684
path_cleaner.delete_unused_static_libs(base_path)
685+
path_cleaner.delete_llvm_cmake_packages(base_path)
685686
path_cleaner.delete_lldb(base_path)
686687
path_cleaner.delete_bundled_cmake(base_path)
687688
path_cleaner.delete_llvm_internal_headers(base_path)

‎path_cleaner.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,34 @@ def delete_unused_static_libs(base_path: str) -> int:
262262
return removed
263263

264264

265+
_ORPHANED_LLVM_CMAKE_DIRS = ("llvm", "clang", "lld")
266+
267+
268+
def delete_llvm_cmake_packages(base_path: str) -> int:
269+
"""Remove the LLVM, Clang, and LLD CMake package directories from lib/cmake/.
270+
271+
delete_unused_static_libs deletes the archives these exported targets point at, so leaving the
272+
packages in place would make a downstream find_package(Clang) fail its imported-file existence
273+
check. Nothing FreeCAD builds consumes these packages. Returns the number of directories removed.
274+
"""
275+
print("Removing orphaned LLVM, Clang, and LLD CMake packages")
276+
cmake_dir = os.path.join(base_path, "lib", "cmake")
277+
if not os.path.isdir(cmake_dir):
278+
return 0
279+
280+
removed = 0
281+
for name in _ORPHANED_LLVM_CMAKE_DIRS:
282+
target = os.path.join(cmake_dir, name)
283+
if not os.path.isdir(target):
284+
continue
285+
try:
286+
shutil.rmtree(target)
287+
removed += 1
288+
except OSError as e:
289+
print(f"Failed to delete {target}: {e}")
290+
return removed
291+
292+
265293
_DOCUMENTATION_RELATIVE_DIRS = (
266294
os.path.join("doc"),
267295
os.path.join("share", "doc"),

‎test_path_cleaner.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,51 @@ def test_no_lib_dir_is_not_an_error(self):
230230
self.assertEqual(path_cleaner.delete_unused_static_libs(self.base_dir), 0)
231231

232232

233+
class TestDeleteLlvmCmakePackages(unittest.TestCase):
234+
"""Verifies that the orphaned LLVM, Clang, and LLD CMake packages are removed and nothing else is."""
235+
236+
def setUp(self):
237+
self.base_dir = tempfile.mkdtemp(prefix="libpack_test_")
238+
self.cmake_dir = os.path.join(self.base_dir, "lib", "cmake")
239+
os.makedirs(self.cmake_dir)
240+
241+
def tearDown(self):
242+
shutil.rmtree(self.base_dir, ignore_errors=True)
243+
244+
def _make_package(self, name: str) -> str:
245+
path = os.path.join(self.cmake_dir, name)
246+
os.makedirs(path)
247+
with open(os.path.join(path, f"{name}Config.cmake"), "w", encoding="utf-8") as f:
248+
f.write("x")
249+
return path
250+
251+
def test_removes_llvm_clang_lld_packages(self):
252+
"""The llvm, clang, and lld CMake package directories should be removed."""
253+
targets = [self._make_package(n) for n in ("llvm", "clang", "lld")]
254+
255+
removed = path_cleaner.delete_llvm_cmake_packages(self.base_dir)
256+
257+
self.assertEqual(removed, len(targets))
258+
for path in targets:
259+
self.assertFalse(os.path.exists(path), f"Expected {path} to be removed")
260+
261+
def test_preserves_other_packages(self):
262+
"""Unrelated CMake packages must not be touched."""
263+
keepers = [self._make_package(n) for n in ("Qt6Core", "Shiboken6", "zstd")]
264+
265+
removed = path_cleaner.delete_llvm_cmake_packages(self.base_dir)
266+
267+
self.assertEqual(removed, 0)
268+
for path in keepers:
269+
self.assertTrue(os.path.exists(path), f"Expected {path} to be preserved")
270+
271+
def test_no_cmake_dir_is_not_an_error(self):
272+
"""If the LibPack has no lib/cmake/ directory the function should be a no-op."""
273+
shutil.rmtree(self.cmake_dir)
274+
275+
self.assertEqual(path_cleaner.delete_llvm_cmake_packages(self.base_dir), 0)
276+
277+
233278
class TestDeleteDocumentation(unittest.TestCase):
234279
"""Verifies that share/doc and the top-level Qt qdoc input directory are both removed."""
235280

0 commit comments

Comments
 (0)