@@ -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 \n If 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