Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions compile_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,18 @@ def get_cmake_options(self) -> List[str]:
def compile_all(self):
# This option borks Tcl by making it find the wrong paths: remove it
os.environ.pop("NoDefaultCurrentDirectoryInExePath", None)
# Keep pip's wheel and HTTP cache inside the build tree rather than the user-global
# location (%LOCALAPPDATA%\pip\cache). This isolates the build both ways: wheels built
# here never leak into the developer's machine-wide cache, and a stale wheel from
# unrelated local pip activity can never be pulled into the LibPack. The directory lives
# under working-<mode>/ and so is not part of the shipped LibPack. Setting it in the
# environment covers every pip subprocess uniformly (requirements, tooling, pip self-
# upgrade, individual installs) regardless of how each call constructs its env.
pip_cache_dir = os.path.abspath(
os.path.join(os.path.dirname(self.install_dir), "pip-cache")
)
os.makedirs(pip_cache_dir, exist_ok=True)
os.environ["PIP_CACHE_DIR"] = pip_cache_dir
for item in self.config["content"]:
# All build methods are named using "build_XXX" where XXX is the name of the package in the config file
os.chdir(item["name"])
Expand Down Expand Up @@ -832,6 +844,9 @@ def _install_debug_library_aliases(self):
("lib/libxml2d.lib", "lib/libxml2.lib"),
("lib/libxsltd.lib", "lib/libxslt.lib"),
("lib/libexsltd.lib", "lib/libexslt.lib"),
# lxml's setup.py hardcodes 'iconv' in its Windows link line; win-iconv builds with
# the debug 'd' postfix, so expose iconvd.lib under the undecorated name it expects.
("lib/iconvd.lib", "lib/iconv.lib"),
)
for src, dst in aliases:
src_path = os.path.join(self.install_dir, src)
Expand Down Expand Up @@ -917,6 +932,24 @@ def _install_python_requirements(self, requirements):
config_settings=config_settings + (("setup-args", "-Duse-pythran=false"),),
)

def _native_pkgconf_path(self, env) -> Optional[str]:
"""Return the path to pkgconf-pypi's bundled native pkgconf executable, or None if the
pkgconf package is not yet installed in the LibPack. Uses the package's documented
get_executable() API rather than hardcoding its internal .bin layout."""
try:
result = subprocess.run(
[self.python_exe(), "-c", "import pkgconf; print(pkgconf.get_executable())"],
capture_output=True,
text=True,
env=env,
)
except OSError:
return None
if result.returncode != 0:
return None
path = result.stdout.strip()
return path if path and os.path.exists(path) else None

def _run_pip_install(
self, requirements, no_build_isolation, no_binary_packages, config_settings=()
):
Expand Down Expand Up @@ -971,6 +1004,18 @@ def _run_pip_install(
# without this, pkg-config silently returns no flags and lxml's compile
# cannot find <libxml/xmlversion.h>.
env["FORCE_PKGCONF_PYPI"] = "1"
# lxml's setup.py (and meson) honor the PKG_CONFIG environment variable to locate
# the pkg-config executable. Point it straight at pkgconf-pypi's bundled native
# binary rather than its pkg-config.exe console-script wrapper: under Python 3.14 the
# wrapper's subinterpreter entrypoint intermittently returns no flags at all, which
# makes lxml fall back to a bare "/usr/include/libxml2" and fail to find
# <libxml/xmlversion.h>. The native binary has no such failure mode. pkgconf is
# installed as part of _DEBUG_BUILD_REQUIRED_TOOLING before the requirements that
# consume it, so this resolves on the main install; on the tooling bootstrap pass it
# is not yet present and PKG_CONFIG is simply left unset.
native_pkgconf = self._native_pkgconf_path(env)
if native_pkgconf:
env["PKG_CONFIG"] = native_pkgconf
scripts_dir = os.path.join(self.install_dir, "bin", "Scripts")
bin_dir = os.path.join(self.install_dir, "bin")
env["PATH"] = scripts_dir + os.pathsep + bin_dir + os.pathsep + env.get("PATH", "")
Expand Down Expand Up @@ -1063,6 +1108,9 @@ def build_qt(self, options: dict):
f" Attempting to use default path {build_dir}. \n\nIf the build fails, consider making a temp directory to work in.\n"
)

if os.path.exists(build_dir):
print(f" Removing existing Qt build directory {build_dir}")
shutil.rmtree(build_dir, onerror=remove_readonly)
os.makedirs(build_dir, exist_ok=True)
old_cwd = os.getcwd()
os.chdir(build_dir)
Expand Down Expand Up @@ -1819,6 +1867,14 @@ def build_hdf5(self, _: None):
"-D HDF5_ENABLE_Z_LIB_SUPPORT=ON",
"-D ZLIB_USE_EXTERNAL=ON",
]
if sys.platform.startswith("win32"):
# HDF5 compiles the same sources into both a static and a shared library. Under the
# default Visual Studio generator, MSBuild's project-level parallelism builds those two
# targets concurrently, so the shared object PDB is written by competing cl.exe
# processes and the build dies with "C1090: PDB API call failed, error code '3'". Ninja
# schedules the whole graph through a single job pool and sidesteps that race, the same
# workaround build_vtk uses for its PDB race.
extra_args.extend(["-G", "Ninja"])
self._build_standard_cmake(extra_args)

def build_medfile(self, _: None):
Expand Down
50 changes: 25 additions & 25 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"FreeCAD-version":"1.2.0",
"LibPack-version":"3.5.0",
"FreeCAD-version":"26.3.0",
"LibPack-version":"3.5.1",
"content": [
{
"name":"libiconv",
Expand All @@ -11,8 +11,8 @@
{
"name":"libxml2",
"git-repo":"https://github.com/GNOME/libxml2",
"git-ref":"v2.13.9",
"note": "Debug-only package. Source-built so that lxml has a libxml2 to link against under Py_DEBUG. Release uses lxml's PyPI wheel which bundles libxml2 internally."
"git-ref":"v2.15.2",
"note": "Debug-only package. Source-built so that lxml has a libxml2 to link against under Py_DEBUG. Pinned to the version lxml 6.1.1 bundles in its release wheel, so the Debug source build matches the Release ABI. Release uses lxml's PyPI wheel which bundles libxml2 internally."
},
{
"name":"libxslt",
Expand Down Expand Up @@ -53,47 +53,47 @@
"annotated-types==0.7.0",
"anyio==4.13.0",
"attrs==23.2.0",
"certifi==2026.4.22",
"certifi==2026.5.20",
"charset-normalizer==3.4.7",
"click==8.3.3",
"click==8.4.1",
"cmake==4.3.2",
"cog==0.16.12",
"colorama==0.4.6",
"configparser==7.2.0",
"contourpy==1.3.3",
"cycler==0.12.1",
"debugpy==1.8.20",
"debugpy==1.8.21",
"definitions==0.2.0",
"defusedxml==0.7.1",
"elementpath==5.1.1",
"elementpath==5.1.2",
"fastapi==0.118.3",
"fonttools==4.63.0",
"h11==0.16.0",
"httptools==0.7.1",
"idna==3.15",
"httptools==0.8.0",
"idna==3.18",
"ifcopenshell==0.8.5; platform_machine != \"ARM64\"",
"isodate==0.7.2",
"joblib==1.5.3",
"kiwisolver==1.5.0",
"lark==1.3.1",
"lxml==6.1.0",
"matplotlib==3.10.9",
"lxml==6.1.1",
"matplotlib==3.11.0",
"nltk==3.9.4",
"numpy==2.4.4",
"numpy==2.4.6",
"packaging==26.2",
"pillow==12.2.0",
"ply==3.11",
"pycollada==0.9.3",
"pydantic==2.13.4",
"pydantic_core==2.46.4",
"pyparsing==3.3.2",
"pyshp==3.0.3",
"pyshp==3.0.12",
"pysolar==0.13",
"python-dateutil==2.9.0.post0",
"python-dotenv==1.2.2",
"PyYAML==6.0.3",
"regex==2026.5.9",
"requests==2.34.1",
"requests==2.34.2",
"rpdb2==2.0.0.1.2",
"scipy==1.17.1",
"sets==0.3.2",
Expand All @@ -103,13 +103,13 @@
"sniffio==1.3.1",
"starlette==0.48.0",
"structlog==24.4.0",
"tqdm==4.67.3",
"tqdm==4.68.2",
"typing-inspection==0.4.2",
"typing_extensions==4.15.0",
"urllib3==2.7.0",
"uvicorn==0.46.0",
"uvicorn==0.49.0",
"vermin==1.8.0",
"watchfiles==1.1.1",
"watchfiles==1.2.0",
"websockets==16.0",
"wheel==0.47.0",
"xmlschema==4.3.1"
Expand Down Expand Up @@ -183,12 +183,12 @@
{
"name":"vtk",
"git-repo":"https://gitlab.kitware.com/vtk/vtk.git",
"git-ref":"v9.6.1"
"git-ref":"v9.6.2"
},
{
"name":"harfbuzz",
"git-repo":"https://github.com/harfbuzz/harfbuzz",
"git-ref":"14.2.0"
"git-ref":"14.2.1"
},
{
"name":"freetype",
Expand All @@ -198,12 +198,12 @@
{
"name":"tcl",
"git-repo":"https://github.com/tcltk/tcl",
"git-ref":"core-8-6-17"
"git-ref":"core-8-6-18"
},
{
"name":"tk",
"git-repo":"https://github.com/tcltk/tk",
"git-ref":"core-8-6-17"
"git-ref":"core-8-6-18"
},
{
"name": "rapidjson",
Expand Down Expand Up @@ -245,11 +245,11 @@
{
"name":"gmsh",
"git-repo":"https://gitlab.onelab.info/gmsh/gmsh",
"git-hash":"23c47b0e6a91f2f67afcbe3bf9ad1b5c253e96e2",
"git-hash":"8fb091efce58de4ecaea56dcb90545e67cdc06b2",
"patches": [
"patches/gmsh-01-windows_stdint.patch"
],
"note": "git hash from 2026-05-08, with support for OCCT 8.0.0"
"note": "git hash from 2026-06-10 (latest master), with support for OCCT 8.0.0"
},
{
"name":"pycxx",
Expand Down Expand Up @@ -296,7 +296,7 @@
{
"name": "googletest",
"git-repo": "https://github.com/google/googletest",
"git-hash": "d72f9c8aea6817cdf1ca0ac10887f328de7f3da2"
"git-hash": "7140cd416cecd7462a8aae488024abeee55598e4"
},
{
"name": "ifcopenshell",
Expand Down
Loading