|
12 | 12 | # and newer. These interpreters don't search for DLLs in the path anymore, you |
13 | 13 | # have to provide a path explicitly. This re-enables path searching for USD |
14 | 14 | # dependency libraries |
15 | | -import platform, sys |
16 | | -if sys.version_info >= (3, 8) and platform.system() == "Windows": |
| 15 | + |
| 16 | +import platform |
| 17 | +if platform.system() == "Windows": |
17 | 18 | import contextlib |
18 | 19 |
|
| 20 | + _WINDOWS_IMPORT_WRAPPER_DEPTH = 0 |
| 21 | + |
19 | 22 | @contextlib.contextmanager |
20 | 23 | def WindowsImportWrapper(): |
21 | | - import os |
| 24 | + import os, sys |
| 25 | + |
| 26 | + global _WINDOWS_IMPORT_WRAPPER_DEPTH |
22 | 27 | dirs = [] |
| 28 | + |
| 29 | + path_updated = False |
23 | 30 | import_paths = os.getenv('PXR_USD_WINDOWS_DLL_PATH') |
24 | 31 | if import_paths is None: |
25 | | - import_paths = os.getenv('PATH', '') |
26 | | - # the underlying windows API call, AddDllDirectory, states that: |
27 | | - # |
28 | | - # > If AddDllDirectory is used to add more than one directory to the |
29 | | - # > process DLL search path, the order in which those directories are |
30 | | - # > searched is unspecified. |
31 | | - # |
32 | | - # https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory |
33 | | - # |
34 | | - # However, in practice, it seems that the most-recently-added ones |
35 | | - # take precedence - so, reverse the order of entries in PATH to give |
36 | | - # it the same precedence |
37 | | - # |
38 | | - # Note that we have a test (testTfPyDllLink) to alert us if this |
39 | | - # undefined behavior changes. |
40 | | - for path in reversed(import_paths.split(os.pathsep)): |
41 | | - # Calling add_dll_directory raises an exception if paths don't |
42 | | - # exist, or if you pass in dot |
43 | | - if os.path.exists(path) and path != '.': |
44 | | - abs_path = os.path.abspath(path) |
45 | | - dirs.append(os.add_dll_directory(abs_path)) |
| 32 | + |
| 33 | + import_paths = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
| 34 | + os.environ['PXR_USD_WINDOWS_DLL_PATH'] = import_paths |
| 35 | + |
| 36 | + # For python version <3.8 and Anaconda, os.envion['PATH'] is used to |
| 37 | + # populate the DLL search paths. Because there's no bulletproof way to |
| 38 | + # detect an Anaconda environment, we must always update PATH if the |
| 39 | + # PXR_USD_WINDOWS_DLL_PATH is set |
| 40 | + if _WINDOWS_IMPORT_WRAPPER_DEPTH == 0: # but only do it once |
| 41 | + path_updated = True |
| 42 | + os.environ['PATH'] = import_paths + os.pathsep + os.getenv('PATH', '') |
| 43 | + |
| 44 | + if sys.version_info >= (3, 8): |
| 45 | + # the underlying windows API call, AddDllDirectory, states that: |
| 46 | + # |
| 47 | + # > If AddDllDirectory is used to add more than one directory to the |
| 48 | + # > process DLL search path, the order in which those directories are |
| 49 | + # > searched is unspecified. |
| 50 | + # |
| 51 | + # https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory |
| 52 | + # |
| 53 | + # However, in practice, it seems that the most-recently-added ones |
| 54 | + # take precedence - so, reverse the order of entries in PATH to give |
| 55 | + # it the same precedence |
| 56 | + # |
| 57 | + # Note that we have a test (testTfPyDllLink) to alert us if this |
| 58 | + # undefined behavior changes. |
| 59 | + for path in reversed(import_paths.split(os.pathsep)): |
| 60 | + # Calling add_dll_directory raises an exception if paths don't |
| 61 | + # exist, or if you pass in dot |
| 62 | + if os.path.exists(path) and path != '.': |
| 63 | + abs_path = os.path.abspath(path) |
| 64 | + dirs.append(os.add_dll_directory(abs_path)) |
| 65 | + |
46 | 66 | # This block guarantees we clear the dll directories if an exception |
47 | 67 | # is raised in the with block. |
| 68 | + |
| 69 | + _WINDOWS_IMPORT_WRAPPER_DEPTH += 1 |
48 | 70 | try: |
49 | 71 | yield |
50 | 72 | finally: |
| 73 | + _WINDOWS_IMPORT_WRAPPER_DEPTH -= 1 |
51 | 74 | for dll_dir in dirs: |
52 | 75 | dll_dir.close() |
53 | | - del os |
| 76 | + |
| 77 | + if _WINDOWS_IMPORT_WRAPPER_DEPTH == 0 and path_updated: |
| 78 | + os.environ['PATH'] = os.environ['PATH'][:len(import_paths) + 1] |
| 79 | + |
| 80 | + del os, sys |
54 | 81 | del contextlib |
55 | 82 | else: |
56 | 83 | class WindowsImportWrapper(object): |
57 | 84 | def __enter__(self): |
58 | 85 | pass |
59 | 86 | def __exit__(self, exc_type, ex_val, exc_tb): |
60 | 87 | pass |
61 | | -del platform, sys |
| 88 | +del platform |
62 | 89 |
|
63 | 90 |
|
64 | 91 | def PreparePythonModule(moduleName=None): |
|
0 commit comments