Skip to content

Commit 385a86d

Browse files
authored
Merge pull request #79 from FreeCAD/occt8
Changes for OCCT8 (all platforms and build types)
2 parents 1540ee6 + 4d1f422 commit 385a86d

8 files changed

Lines changed: 144 additions & 194 deletions

compile_all.py

Lines changed: 86 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,18 @@ def get_cmake_options(self) -> List[str]:
352352
if python_lib:
353353
base.append(f"-D Python_LIBRARY={python_lib}")
354354
base.append(f"-D Python3_LIBRARY={python_lib}")
355+
if self.mode == BuildMode.RELEASE and sys.platform.startswith("win32"):
356+
# Force PDB generation in Release for the PDB sidecar archive.
357+
# /OPT:REF /OPT:ICF undo /DEBUG's default of disabling COMDAT folding.
358+
base.extend(
359+
[
360+
"-D CMAKE_POLICY_DEFAULT_CMP0141=NEW",
361+
"-D CMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase",
362+
"-D CMAKE_EXE_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF",
363+
"-D CMAKE_SHARED_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF",
364+
"-D CMAKE_MODULE_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF",
365+
]
366+
)
355367
if self.boost_include_path:
356368
base.append(f"-D Boost_INCLUDE_DIR={self.boost_include_path}")
357369
if self.coin_cmake_path:
@@ -1033,7 +1045,7 @@ def build_qt(self, options: dict):
10331045
if os.path.exists(os.path.join(self.install_dir, "metatypes")):
10341046
print(" Not rebuilding Qt, it is already in the LibPack")
10351047
return
1036-
self._prepend_debug_crt_to_path()
1048+
self._prepend_runtime_dirs_to_path()
10371049

10381050
build_dir = os.path.join(os.getcwd(), f"build-{str(self.mode).lower()}")
10391051
if len(build_dir) > 20:
@@ -1043,8 +1055,9 @@ def build_qt(self, options: dict):
10431055
' path name for the actual build directory (e.g., "C:\\temp").\n'
10441056
)
10451057
if "fallback-build-dir" in options:
1046-
print(f" Using fallback build directory {options['fallback-build-dir']}")
1047-
build_dir = options["fallback-build-dir"]
1058+
mode_suffix = "d" if self.mode == BuildMode.DEBUG else "r"
1059+
build_dir = os.path.join(options["fallback-build-dir"], mode_suffix)
1060+
print(f" Using fallback build directory {build_dir}")
10481061
else:
10491062
print(
10501063
f" Attempting to use default path {build_dir}. \n\nIf the build fails, consider making a temp directory to work in.\n"
@@ -1179,53 +1192,65 @@ def _run_cmake(self, args):
11791192
print(e.output.decode("utf-8", errors="replace"))
11801193
exit(e.returncode)
11811194

1182-
def _prepend_debug_crt_to_path(self) -> None:
1183-
"""Make the LibPack's debug DLLs (Qt's zd.dll, libpng16d.dll, and similar) and
1184-
the MSVC and Universal CRT debug DLLs (msvcp140d.dll, vcruntime140d.dll,
1185-
ucrtbased.dll) discoverable by freshly-built debug tools"""
1186-
if self.mode != BuildMode.DEBUG or sys.platform != "win32":
1195+
def _prepend_runtime_dirs_to_path(self) -> None:
1196+
"""Make the LibPack's just-installed runtime DLLs (z.dll/zd.dll,
1197+
libpng16/libpng16d, and similar) discoverable by freshly-built tools that the
1198+
build invokes as subprocesses (Qt's rcc.exe, moc.exe, qlalr.exe are the first
1199+
instances). In Debug mode also add the MSVC and Universal CRT debug-only
1200+
redist directories (msvcp140d.dll, vcruntime140d.dll, ucrtbased.dll), which
1201+
vcvars*.bat does not put on PATH because debug binaries are not generally
1202+
redistributable. Without this, the tools fail with STATUS_DLL_NOT_FOUND
1203+
(0xC0000135) the first time cmake --build runs them. Windows only."""
1204+
if sys.platform != "win32":
11871205
return
1188-
arch_lower = "arm64" if platform.machine() == "ARM64" else "x64"
1189-
toolset_prefix = ""
1190-
if self.msvc_tools_version:
1191-
toolset_prefix = ".".join(self.msvc_tools_version.split(".")[:2])
11921206
extra_dirs: List[str] = [os.path.join(self.install_dir, "bin")]
1193-
vs_root = pathlib.Path("C:/Program Files/Microsoft Visual Studio")
1194-
if vs_root.is_dir():
1195-
for vs_major in sorted(vs_root.iterdir(), reverse=True):
1196-
redist = vs_major / "Community" / "VC" / "Redist" / "MSVC"
1197-
if not redist.is_dir():
1198-
continue
1199-
candidates = [d for d in redist.iterdir() if d.is_dir()]
1200-
if toolset_prefix:
1201-
matching = [d for d in candidates if d.name.startswith(toolset_prefix + ".")]
1202-
if matching:
1203-
candidates = matching
1204-
candidates.sort(
1207+
if self.mode == BuildMode.DEBUG:
1208+
arch_lower = "arm64" if platform.machine() == "ARM64" else "x64"
1209+
toolset_prefix = ""
1210+
if self.msvc_tools_version:
1211+
toolset_prefix = ".".join(self.msvc_tools_version.split(".")[:2])
1212+
vs_root = pathlib.Path("C:/Program Files/Microsoft Visual Studio")
1213+
crt_added = False
1214+
if vs_root.is_dir():
1215+
for vs_major in sorted(vs_root.iterdir(), reverse=True):
1216+
redist = vs_major / "Community" / "VC" / "Redist" / "MSVC"
1217+
if not redist.is_dir():
1218+
continue
1219+
candidates = [d for d in redist.iterdir() if d.is_dir()]
1220+
if toolset_prefix:
1221+
matching = [
1222+
d for d in candidates if d.name.startswith(toolset_prefix + ".")
1223+
]
1224+
if matching:
1225+
candidates = matching
1226+
candidates.sort(
1227+
key=lambda d: tuple(int(p) for p in d.name.split(".") if p.isdigit()),
1228+
reverse=True,
1229+
)
1230+
for ver in candidates:
1231+
for crt_dir in ver.glob(
1232+
f"debug_nonredist/{arch_lower}/Microsoft.VC*.DebugCRT"
1233+
):
1234+
if (crt_dir / "vcruntime140d.dll").exists():
1235+
extra_dirs.append(str(crt_dir))
1236+
crt_added = True
1237+
break
1238+
if crt_added:
1239+
break
1240+
if crt_added:
1241+
break
1242+
sdk_bin = pathlib.Path("C:/Program Files (x86)/Windows Kits/10/bin")
1243+
if sdk_bin.is_dir():
1244+
sdk_versions = sorted(
1245+
[d for d in sdk_bin.iterdir() if d.is_dir() and re.match(r"^\d+\.", d.name)],
12051246
key=lambda d: tuple(int(p) for p in d.name.split(".") if p.isdigit()),
12061247
reverse=True,
12071248
)
1208-
for ver in candidates:
1209-
for crt_dir in ver.glob(f"debug_nonredist/{arch_lower}/Microsoft.VC*.DebugCRT"):
1210-
if (crt_dir / "vcruntime140d.dll").exists():
1211-
extra_dirs.append(str(crt_dir))
1212-
break
1213-
if len(extra_dirs) > 1:
1249+
for ver in sdk_versions:
1250+
ucrt = ver / arch_lower / "ucrt"
1251+
if (ucrt / "ucrtbased.dll").exists():
1252+
extra_dirs.append(str(ucrt))
12141253
break
1215-
if len(extra_dirs) > 1:
1216-
break
1217-
sdk_bin = pathlib.Path("C:/Program Files (x86)/Windows Kits/10/bin")
1218-
if sdk_bin.is_dir():
1219-
sdk_versions = sorted(
1220-
[d for d in sdk_bin.iterdir() if d.is_dir() and re.match(r"^\d+\.", d.name)],
1221-
key=lambda d: tuple(int(p) for p in d.name.split(".") if p.isdigit()),
1222-
reverse=True,
1223-
)
1224-
for ver in sdk_versions:
1225-
ucrt = ver / arch_lower / "ucrt"
1226-
if (ucrt / "ucrtbased.dll").exists():
1227-
extra_dirs.append(str(ucrt))
1228-
break
12291254
current_path = os.environ.get("PATH", "")
12301255
path_parts = current_path.split(os.pathsep) if current_path else []
12311256
normalized = {os.path.normcase(p) for p in path_parts}
@@ -1439,18 +1464,20 @@ def build_pyside(self, _=None):
14391464
env["VULKAN_SDK"] = "None"
14401465
if sys.platform.startswith("win32"):
14411466
ssl = "--openssl=" + os.path.join(self.install_dir, "bin", "DLLs")
1442-
args = [
1443-
*self.init_script,
1444-
"&",
1445-
python,
1446-
"setup.py",
1447-
"install",
1448-
qtpaths,
1449-
ssl,
1450-
parallel,
1451-
]
1452-
if self.mode == BuildMode.DEBUG:
1453-
args.append("--debug")
1467+
python_libs = os.path.join(self.install_dir, "bin", "libs")
1468+
init_call = "call " + subprocess.list2cmdline(self.init_script)
1469+
setup_cmd = subprocess.list2cmdline(
1470+
[python, "setup.py", "install", qtpaths, ssl, parallel]
1471+
+ (["--debug"] if self.mode == BuildMode.DEBUG else [])
1472+
)
1473+
wrapper_path = os.path.abspath("build_pyside_wrapper.bat")
1474+
with open(wrapper_path, "w", encoding="utf-8") as f:
1475+
f.write("@echo off\n")
1476+
f.write(f"{init_call}\n")
1477+
f.write("if errorlevel 1 exit /b %ERRORLEVEL%\n")
1478+
f.write(f"set LIB={python_libs};%LIB%\n")
1479+
f.write(f"{setup_cmd}\n")
1480+
args = [wrapper_path]
14541481
else:
14551482
ssl = "--openssl=" + os.path.join(self.install_dir, "bin", "DLLs")
14561483
args = [python, "setup.py", "install", qtpaths, ssl]
@@ -1960,8 +1987,7 @@ def build_opencamlib(self, _: None):
19601987
# LibPack's site-packages.
19611988
site_packages = os.path.join(self.install_dir, "bin", "Lib", "site-packages")
19621989
if self.skip_existing:
1963-
sentinel_name = "ocl_d.pyd" if self.mode == BuildMode.DEBUG else "ocl.pyd"
1964-
if os.path.exists(os.path.join(site_packages, "opencamlib", sentinel_name)):
1990+
if os.path.exists(os.path.join(site_packages, "opencamlib", "ocl.pyd")):
19651991
print(" Not rebuilding opencamlib, it is already in the LibPack")
19661992
return
19671993
extra_args = [
@@ -2035,76 +2061,5 @@ def build_ifcopenshell(self, _=None):
20352061
shutil.copytree(source, target)
20362062

20372063
def _build_ifcopenshell_debug(self):
2038-
"""Debug-mode source build of IfcOpenShell. fetch_remote_data clones and
2039-
patches the source for us in Debug because the ifcopenshell entry has
2040-
both a git-repo and a url-ARM64 (the latter is the Release-only prebuilt
2041-
zip)."""
2042-
site_packages = os.path.join(self.install_dir, "bin", "Lib", "site-packages")
2043-
target = os.path.join(site_packages, "ifcopenshell")
2044-
if self.skip_existing and os.path.exists(target):
2045-
print(" Not rebuilding ifcopenshell, it is already in the LibPack")
2046-
return
2047-
cwd = os.getcwd()
2048-
# IfcOpenShell's root CMakeLists.txt lives in the cmake/ subdirectory, not
2049-
# the repo root. Dependencies (OpenCASCADE, HDF5, LibXml2, VTK) are resolved
2050-
# through their installed CMake package configs via CMAKE_PREFIX_PATH rather
2051-
# than passing manual include and library paths, because OCCT installs into a
2052-
# flat layout (inc/ and libd/) that does not match the conventional layout
2053-
# IfcOpenShell's Find modules assume.
2054-
ifc_install_dir = self.install_dir.replace("\\", "/")
2055-
extra_args = [
2056-
"-G",
2057-
"Ninja",
2058-
"-D CMAKE_CXX_STANDARD=17",
2059-
f"-D CMAKE_PREFIX_PATH={ifc_install_dir}",
2060-
f"-D BOOST_ROOT={ifc_install_dir}",
2061-
"-D Boost_USE_STATIC_LIBS=OFF",
2062-
f"-D HDF5_DIR={ifc_install_dir}/cmake",
2063-
f"-D PYTHON_EXECUTABLE={self.python_exe()}",
2064-
"-D BUILD_IFCPYTHON=ON",
2065-
"-D BUILD_IFCMAX=OFF",
2066-
"-D BUILD_GEOMSERVER=OFF",
2067-
"-D BUILD_CONVERT=OFF",
2068-
"-D BUILD_EXAMPLES=OFF",
2069-
"-D BUILD_TESTING=OFF",
2070-
"-D WITH_CGAL=OFF",
2071-
"-D COLLADA_SUPPORT=OFF",
2072-
"-D HDF5_SUPPORT=OFF",
2073-
"-D USE_DEBUG_PYTHON=ON",
2074-
"-D BUILD_ONLY_COMMON_SCHEMAS=ON",
2075-
"-D BUILD_SHARED_LIBS=OFF",
2076-
]
2077-
# The source layout puts the CMakeLists in cmake/, not the repo root, so we
2078-
# cannot use the standard _build_standard_cmake helper which assumes "..".
2079-
build_dir = os.path.join(cwd, "build-debug")
2080-
if os.path.exists(build_dir):
2081-
shutil.rmtree(build_dir, onerror=remove_readonly)
2082-
os.makedirs(build_dir)
2083-
os.chdir(build_dir)
2084-
# IfcOpenShell's CMakeLists.txt and svgfill/CMakeLists.txt both contain
2085-
# blocks guarded by `if(WIN32 AND NOT DEFINED ENV{CONDA_BUILD})` that force
2086-
# `Boost_USE_STATIC_LIBS=ON` as a non-cache variable, which shadows any -D
2087-
# we pass and causes Boost's modular shared configs to declare themselves
2088-
# version-incompatible. FindHDF5.cmake similarly takes a Windows naming
2089-
# path that does not match our LibPack when CONDA_BUILD is unset. Setting
2090-
# CONDA_BUILD diverts all three sites to the branch that uses the package
2091-
# configs we install, with no other side effects in IfcOpenShell.
2092-
prev_conda_build = os.environ.get("CONDA_BUILD")
2093-
os.environ["CONDA_BUILD"] = "1"
2094-
old_strict_mode = self.strict_mode
2095-
self.strict_mode = False
2096-
try:
2097-
options = self.get_cmake_options()
2098-
options.extend(extra_args)
2099-
options.extend(self._arm64_platform_flag(extra_args))
2100-
options.append("../cmake")
2101-
self._run_cmake(options)
2102-
self._cmake_build()
2103-
self._cmake_install()
2104-
finally:
2105-
self.strict_mode = old_strict_mode
2106-
if prev_conda_build is None:
2107-
os.environ.pop("CONDA_BUILD", None)
2108-
else:
2109-
os.environ["CONDA_BUILD"] = prev_conda_build
2110-
os.chdir(cwd)
2064+
"""Not built in Debug for LibPack 3.5: IfcOpenShell 0.8.5 does not compile against OCCT 8."""
2065+
print(" Skipping ifcopenshell in Debug mode: not yet OCCT 8 compatible upstream.")

0 commit comments

Comments
 (0)