1# 2# Copyright 2017 Pixar 3# 4# Licensed under the Apache License, Version 2.0 (the "Apache License") 5# with the following modification; you may not use this file except in 6# compliance with the Apache License and the following modification to it: 7# Section 6. Trademarks. is deleted and replaced with: 8# 9# 6. Trademarks. This License does not grant permission to use the trade 10# names, trademarks, service marks, or product names of the Licensor 11# and its affiliates, except as required to comply with Section 4(c) of 12# the License and to reproduce the content of the NOTICE file. 13# 14# You may obtain a copy of the Apache License at 15# 16# http://www.apache.org/licenses/LICENSE-2.0 17# 18# Unless required by applicable law or agreed to in writing, software 19# distributed under the Apache License with the above modification is 20# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21# KIND, either express or implied. See the Apache License for the specific 22# language governing permissions and limitations under the Apache License. 23# 24from __future__ import print_function 25 26import argparse 27import codecs 28import contextlib 29import ctypes 30import datetime 31import distutils 32import fnmatch 33import glob 34import locale 35import multiprocessing 36import os 37import platform 38import re 39import shlex 40import shutil 41import subprocess 42import sys 43import sysconfig 44import tarfile 45import zipfile 46 47if sys.version_info.major >= 3: 48 from urllib.request import urlopen 49 from shutil import which 50else: 51 from urllib2 import urlopen 52 53 # Doesn't deal with .bat / .cmd like shutil.which, but only option 54 # available with stock python-2 55 from distutils.spawn import find_executable as which 56 57# Helpers for printing output 58verbosity = 1 59 60def Print(msg): 61 if verbosity > 0: 62 print(msg) 63 64def PrintWarning(warning): 65 if verbosity > 0: 66 print("WARNING:", warning) 67 68def PrintStatus(status): 69 if verbosity >= 1: 70 print("STATUS:", status) 71 72def PrintInfo(info): 73 if verbosity >= 2: 74 print("INFO:", info) 75 76def PrintCommandOutput(output): 77 if verbosity >= 3: 78 sys.stdout.write(output) 79 80def PrintError(error): 81 if verbosity >= 3 and sys.exc_info()[1] is not None: 82 import traceback 83 traceback.print_exc() 84 print ("ERROR:", error) 85 86# Helpers for determining platform 87def Windows(): 88 return platform.system() == "Windows" 89def Linux(): 90 return platform.system() == "Linux" 91def MacOS(): 92 return platform.system() == "Darwin" 93 94def Python3(): 95 return sys.version_info.major == 3 96 97def GetLocale(): 98 return sys.stdout.encoding or locale.getdefaultlocale()[1] or "UTF-8" 99 100def GetCommandOutput(command): 101 """Executes the specified command and returns output or None.""" 102 try: 103 return subprocess.check_output( 104 shlex.split(command), 105 stderr=subprocess.STDOUT).decode(GetLocale(), 'replace').strip() 106 except subprocess.CalledProcessError: 107 pass 108 return None 109 110def GetXcodeDeveloperDirectory(): 111 """Returns the active developer directory as reported by 'xcode-select -p'. 112 Returns None if none is set.""" 113 if not MacOS(): 114 return None 115 116 return GetCommandOutput("xcode-select -p") 117 118def GetVisualStudioCompilerAndVersion(): 119 """Returns a tuple containing the path to the Visual Studio compiler 120 and a tuple for its version, e.g. (14, 0). If the compiler is not found 121 or version number cannot be determined, returns None.""" 122 if not Windows(): 123 return None 124 125 msvcCompiler = which('cl') 126 if msvcCompiler: 127 # VisualStudioVersion environment variable should be set by the 128 # Visual Studio Command Prompt. 129 match = re.search( 130 r"(\d+)\.(\d+)", 131 os.environ.get("VisualStudioVersion", "")) 132 if match: 133 return (msvcCompiler, tuple(int(v) for v in match.groups())) 134 return None 135 136def IsVisualStudioVersionOrGreater(desiredVersion): 137 if not Windows(): 138 return False 139 140 msvcCompilerAndVersion = GetVisualStudioCompilerAndVersion() 141 if msvcCompilerAndVersion: 142 _, version = msvcCompilerAndVersion 143 return version >= desiredVersion 144 return False 145 146def IsVisualStudio2019OrGreater(): 147 VISUAL_STUDIO_2019_VERSION = (16, 0) 148 return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2019_VERSION) 149 150def IsVisualStudio2017OrGreater(): 151 VISUAL_STUDIO_2017_VERSION = (15, 0) 152 return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2017_VERSION) 153 154def IsVisualStudio2015OrGreater(): 155 VISUAL_STUDIO_2015_VERSION = (14, 0) 156 return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2015_VERSION) 157 158def IsMayaPython(): 159 """Determine whether we're running in Maya's version of Python. When 160 building against Maya's Python, there are some additional restrictions 161 on what we're able to build.""" 162 try: 163 import maya 164 return True 165 except: 166 pass 167 168 return False 169 170def GetPythonInfo(context): 171 """Returns a tuple containing the path to the Python executable, shared 172 library, and include directory corresponding to the version of Python 173 currently running. Returns None if any path could not be determined. 174 175 This function is used to extract build information from the Python 176 interpreter used to launch this script. This information is used 177 in the Boost and USD builds. By taking this approach we can support 178 having USD builds for different Python versions built on the same 179 machine. This is very useful, especially when developers have multiple 180 versions installed on their machine, which is quite common now with 181 Python2 and Python3 co-existing. 182 """ 183 184 # If we were given build python info then just use it. 185 if context.build_python_info: 186 return (context.build_python_info['PYTHON_EXECUTABLE'], 187 context.build_python_info['PYTHON_LIBRARY'], 188 context.build_python_info['PYTHON_INCLUDE_DIR'], 189 context.build_python_info['PYTHON_VERSION']) 190 191 # First we extract the information that can be uniformly dealt with across 192 # the platforms: 193 pythonExecPath = sys.executable 194 pythonVersion = sysconfig.get_config_var("py_version_short") # "2.7" 195 pythonVersionNoDot = sysconfig.get_config_var("py_version_nodot") # "27" 196 197 # Lib path is unfortunately special for each platform and there is no 198 # config_var for it. But we can deduce it for each platform, and this 199 # logic works for any Python version. 200 def _GetPythonLibraryFilename(context): 201 if Windows(): 202 suffix = '_d' if context.buildDebug and context.debugPython else '' 203 return "python" + pythonVersionNoDot + suffix + ".lib" 204 elif Linux(): 205 return sysconfig.get_config_var("LDLIBRARY") 206 elif MacOS(): 207 return "libpython" + pythonVersion + ".dylib" 208 else: 209 raise RuntimeError("Platform not supported") 210 211 # XXX: Handle the case where this script is being called using Maya's 212 # Python since the sysconfig variables are set up differently in Maya. 213 # Ideally we would not have any special Maya knowledge in here at all. 214 if IsMayaPython(): 215 pythonBaseDir = sysconfig.get_config_var("base") 216 217 # On Windows, the "base" path points to a "Python\" subdirectory 218 # that contains the DLLs for site-package modules but not the 219 # directories for the headers and .lib file we need -- those 220 # are one level up. 221 if Windows(): 222 pythonBaseDir = os.path.dirname(pythonBaseDir) 223 224 pythonIncludeDir = os.path.join(pythonBaseDir, "include", 225 "python" + pythonVersion) 226 pythonLibPath = os.path.join(pythonBaseDir, "lib", 227 _GetPythonLibraryFilename(context)) 228 else: 229 pythonIncludeDir = sysconfig.get_config_var("INCLUDEPY") 230 if Windows(): 231 pythonBaseDir = sysconfig.get_config_var("base") 232 pythonLibPath = os.path.join(pythonBaseDir, "libs", 233 _GetPythonLibraryFilename(context)) 234 elif Linux(): 235 pythonLibDir = sysconfig.get_config_var("LIBDIR") 236 pythonMultiarchSubdir = sysconfig.get_config_var("multiarchsubdir") 237 if pythonMultiarchSubdir: 238 pythonLibDir = pythonLibDir + pythonMultiarchSubdir 239 pythonLibPath = os.path.join(pythonLibDir, 240 _GetPythonLibraryFilename(context)) 241 elif MacOS(): 242 pythonBaseDir = sysconfig.get_config_var("base") 243 pythonLibPath = os.path.join(pythonBaseDir, "lib", 244 _GetPythonLibraryFilename(context)) 245 else: 246 raise RuntimeError("Platform not supported") 247 248 return (pythonExecPath, pythonLibPath, pythonIncludeDir, pythonVersion) 249 250def GetCPUCount(): 251 try: 252 return multiprocessing.cpu_count() 253 except NotImplementedError: 254 return 1 255 256def Run(cmd, logCommandOutput = True): 257 """Run the specified command in a subprocess.""" 258 PrintInfo('Running "{cmd}"'.format(cmd=cmd)) 259 260 with codecs.open("log.txt", "a", "utf-8") as logfile: 261 logfile.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M")) 262 logfile.write("\n") 263 logfile.write(cmd) 264 logfile.write("\n") 265 266 # Let exceptions escape from subprocess calls -- higher level 267 # code will handle them. 268 if logCommandOutput: 269 p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, 270 stderr=subprocess.STDOUT) 271 while True: 272 l = p.stdout.readline().decode(GetLocale(), 'replace') 273 if l: 274 logfile.write(l) 275 PrintCommandOutput(l) 276 elif p.poll() is not None: 277 break 278 else: 279 p = subprocess.Popen(shlex.split(cmd)) 280 p.wait() 281 282 if p.returncode != 0: 283 # If verbosity >= 3, we'll have already been printing out command output 284 # so no reason to print the log file again. 285 if verbosity < 3: 286 with open("log.txt", "r") as logfile: 287 Print(logfile.read()) 288 raise RuntimeError("Failed to run '{cmd}'\nSee {log} for more details." 289 .format(cmd=cmd, log=os.path.abspath("log.txt"))) 290 291@contextlib.contextmanager 292def CurrentWorkingDirectory(dir): 293 """Context manager that sets the current working directory to the given 294 directory and resets it to the original directory when closed.""" 295 curdir = os.getcwd() 296 os.chdir(dir) 297 try: yield 298 finally: os.chdir(curdir) 299 300def CopyFiles(context, src, dest): 301 """Copy files like shutil.copy, but src may be a glob pattern.""" 302 filesToCopy = glob.glob(src) 303 if not filesToCopy: 304 raise RuntimeError("File(s) to copy {src} not found".format(src=src)) 305 306 instDestDir = os.path.join(context.instDir, dest) 307 for f in filesToCopy: 308 PrintCommandOutput("Copying {file} to {destDir}\n" 309 .format(file=f, destDir=instDestDir)) 310 shutil.copy(f, instDestDir) 311 312def CopyDirectory(context, srcDir, destDir): 313 """Copy directory like shutil.copytree.""" 314 instDestDir = os.path.join(context.instDir, destDir) 315 if os.path.isdir(instDestDir): 316 shutil.rmtree(instDestDir) 317 318 PrintCommandOutput("Copying {srcDir} to {destDir}\n" 319 .format(srcDir=srcDir, destDir=instDestDir)) 320 shutil.copytree(srcDir, instDestDir) 321 322def AppendCXX11ABIArg(buildFlag, context, buildArgs): 323 """Append a build argument that defines _GLIBCXX_USE_CXX11_ABI 324 based on the settings in the context. This may either do nothing 325 or append an entry to buildArgs like: 326 327 <buildFlag>="-D_GLIBCXX_USE_CXX11_ABI={0, 1}" 328 329 If buildArgs contains settings for buildFlag, those settings will 330 be merged with the above define.""" 331 if context.useCXX11ABI is None: 332 return 333 334 cxxFlags = ["-D_GLIBCXX_USE_CXX11_ABI={}".format(context.useCXX11ABI)] 335 336 # buildArgs might look like: 337 # ["-DFOO=1", "-DBAR=2", ...] or ["-DFOO=1 -DBAR=2 ...", ...] 338 # 339 # See if any of the arguments in buildArgs start with the given 340 # buildFlag. If so, we want to take whatever that buildFlag has 341 # been set to and merge it in with the cxxFlags above. 342 # 343 # For example, if buildArgs = ['-DCMAKE_CXX_FLAGS="-w"', ...] 344 # we want to add "-w" to cxxFlags. 345 splitArgs = [shlex.split(a) for a in buildArgs] 346 for p in [item for arg in splitArgs for item in arg]: 347 if p.startswith(buildFlag): 348 (_, _, flags) = p.partition("=") 349 cxxFlags.append(flags) 350 351 buildArgs.append('{flag}="{flags}"'.format( 352 flag=buildFlag, flags=" ".join(cxxFlags))) 353 354def FormatMultiProcs(numJobs, generator): 355 tag = "-j" 356 if generator: 357 if "Visual Studio" in generator: 358 tag = "/M:" # This will build multiple projects at once. 359 elif "Xcode" in generator: 360 tag = "-j " 361 362 return "{tag}{procs}".format(tag=tag, procs=numJobs) 363 364def RunCMake(context, force, extraArgs = None): 365 """Invoke CMake to configure, build, and install a library whose 366 source code is located in the current working directory.""" 367 # Create a directory for out-of-source builds in the build directory 368 # using the name of the current working directory. 369 srcDir = os.getcwd() 370 instDir = (context.usdInstDir if srcDir == context.usdSrcDir 371 else context.instDir) 372 buildDir = os.path.join(context.buildDir, os.path.split(srcDir)[1]) 373 if force and os.path.isdir(buildDir): 374 shutil.rmtree(buildDir) 375 376 if not os.path.isdir(buildDir): 377 os.makedirs(buildDir) 378 379 generator = context.cmakeGenerator 380 381 # On Windows, we need to explicitly specify the generator to ensure we're 382 # building a 64-bit project. (Surely there is a better way to do this?) 383 # TODO: figure out exactly what "vcvarsall.bat x64" sets to force x64 384 if generator is None and Windows(): 385 if IsVisualStudio2019OrGreater(): 386 generator = "Visual Studio 16 2019" 387 elif IsVisualStudio2017OrGreater(): 388 generator = "Visual Studio 15 2017 Win64" 389 else: 390 generator = "Visual Studio 14 2015 Win64" 391 392 if generator is not None: 393 generator = '-G "{gen}"'.format(gen=generator) 394 395 if IsVisualStudio2019OrGreater(): 396 generator = generator + " -A x64" 397 398 toolset = context.cmakeToolset 399 if toolset is not None: 400 toolset = '-T "{toolset}"'.format(toolset=toolset) 401 402 # On MacOS, enable the use of @rpath for relocatable builds. 403 osx_rpath = None 404 if MacOS(): 405 osx_rpath = "-DCMAKE_MACOSX_RPATH=ON" 406 407 # We use -DCMAKE_BUILD_TYPE for single-configuration generators 408 # (Ninja, make), and --config for multi-configuration generators 409 # (Visual Studio); technically we don't need BOTH at the same 410 # time, but specifying both is simpler than branching 411 config = "Release" 412 if context.buildDebug: 413 config = "Debug" 414 elif context.buildRelease: 415 config = "Release" 416 elif context.buildRelWithDebug: 417 config = "RelWithDebInfo" 418 419 # Append extra argument controlling libstdc++ ABI if specified. 420 AppendCXX11ABIArg("-DCMAKE_CXX_FLAGS", context, extraArgs) 421 422 with CurrentWorkingDirectory(buildDir): 423 Run('cmake ' 424 '-DCMAKE_INSTALL_PREFIX="{instDir}" ' 425 '-DCMAKE_PREFIX_PATH="{depsInstDir}" ' 426 '-DCMAKE_BUILD_TYPE={config} ' 427 '{osx_rpath} ' 428 '{generator} ' 429 '{toolset} ' 430 '{extraArgs} ' 431 '"{srcDir}"' 432 .format(instDir=instDir, 433 depsInstDir=context.instDir, 434 config=config, 435 srcDir=srcDir, 436 osx_rpath=(osx_rpath or ""), 437 generator=(generator or ""), 438 toolset=(toolset or ""), 439 extraArgs=(" ".join(extraArgs) if extraArgs else ""))) 440 Run("cmake --build . --config {config} --target install -- {multiproc}" 441 .format(config=config, 442 multiproc=FormatMultiProcs(context.numJobs, generator))) 443 444def GetCMakeVersion(): 445 """ 446 Returns the CMake version as tuple of integers (major, minor) or 447 (major, minor, patch) or None if an error occured while launching cmake and 448 parsing its output. 449 """ 450 451 output_string = GetCommandOutput("cmake --version") 452 if not output_string: 453 PrintWarning("Could not determine cmake version -- please install it " 454 "and adjust your PATH") 455 return None 456 457 # cmake reports, e.g., "... version 3.14.3" 458 match = re.search(r"version (\d+)\.(\d+)(\.(\d+))?", output_string) 459 if not match: 460 PrintWarning("Could not determine cmake version") 461 return None 462 463 major, minor, patch_group, patch = match.groups() 464 if patch_group is None: 465 return (int(major), int(minor)) 466 else: 467 return (int(major), int(minor), int(patch)) 468 469def PatchFile(filename, patches, multiLineMatches=False): 470 """Applies patches to the specified file. patches is a list of tuples 471 (old string, new string).""" 472 if multiLineMatches: 473 oldLines = [open(filename, 'r').read()] 474 else: 475 oldLines = open(filename, 'r').readlines() 476 newLines = oldLines 477 for (oldString, newString) in patches: 478 newLines = [s.replace(oldString, newString) for s in newLines] 479 if newLines != oldLines: 480 PrintInfo("Patching file {filename} (original in {oldFilename})..." 481 .format(filename=filename, oldFilename=filename + ".old")) 482 shutil.copy(filename, filename + ".old") 483 open(filename, 'w').writelines(newLines) 484 485def DownloadFileWithCurl(url, outputFilename): 486 # Don't log command output so that curl's progress 487 # meter doesn't get written to the log file. 488 Run("curl {progress} -L -o {filename} {url}".format( 489 progress="-#" if verbosity >= 2 else "-s", 490 filename=outputFilename, url=url), 491 logCommandOutput=False) 492 493def DownloadFileWithPowershell(url, outputFilename): 494 # It's important that we specify to use TLS v1.2 at least or some 495 # of the downloads will fail. 496 cmd = "powershell [Net.ServicePointManager]::SecurityProtocol = \ 497 [Net.SecurityProtocolType]::Tls12; \"(new-object \ 498 System.Net.WebClient).DownloadFile('{url}', '{filename}')\""\ 499 .format(filename=outputFilename, url=url) 500 501 Run(cmd,logCommandOutput=False) 502 503def DownloadFileWithUrllib(url, outputFilename): 504 r = urlopen(url) 505 with open(outputFilename, "wb") as outfile: 506 outfile.write(r.read()) 507 508def DownloadURL(url, context, force, extractDir = None, 509 dontExtract = None): 510 """Download and extract the archive file at given URL to the 511 source directory specified in the context. 512 513 dontExtract may be a sequence of path prefixes that will 514 be excluded when extracting the archive. 515 516 Returns the absolute path to the directory where files have 517 been extracted.""" 518 with CurrentWorkingDirectory(context.srcDir): 519 # Extract filename from URL and see if file already exists. 520 filename = url.split("/")[-1] 521 if force and os.path.exists(filename): 522 os.remove(filename) 523 524 if os.path.exists(filename): 525 PrintInfo("{0} already exists, skipping download" 526 .format(os.path.abspath(filename))) 527 else: 528 PrintInfo("Downloading {0} to {1}" 529 .format(url, os.path.abspath(filename))) 530 531 # To work around occasional hiccups with downloading from websites 532 # (SSL validation errors, etc.), retry a few times if we don't 533 # succeed in downloading the file. 534 maxRetries = 5 535 lastError = None 536 537 # Download to a temporary file and rename it to the expected 538 # filename when complete. This ensures that incomplete downloads 539 # will be retried if the script is run again. 540 tmpFilename = filename + ".tmp" 541 if os.path.exists(tmpFilename): 542 os.remove(tmpFilename) 543 544 for i in range(maxRetries): 545 try: 546 context.downloader(url, tmpFilename) 547 break 548 except Exception as e: 549 PrintCommandOutput("Retrying download due to error: {err}\n" 550 .format(err=e)) 551 lastError = e 552 else: 553 errorMsg = str(lastError) 554 if "SSL: TLSV1_ALERT_PROTOCOL_VERSION" in errorMsg: 555 errorMsg += ("\n\n" 556 "Your OS or version of Python may not support " 557 "TLS v1.2+, which is required for downloading " 558 "files from certain websites. This support " 559 "was added in Python 2.7.9." 560 "\n\n" 561 "You can use curl to download dependencies " 562 "by installing it in your PATH and re-running " 563 "this script.") 564 raise RuntimeError("Failed to download {url}: {err}" 565 .format(url=url, err=errorMsg)) 566 567 shutil.move(tmpFilename, filename) 568 569 # Open the archive and retrieve the name of the top-most directory. 570 # This assumes the archive contains a single directory with all 571 # of the contents beneath it, unless a specific extractDir is specified, 572 # which is to be used. 573 archive = None 574 rootDir = None 575 members = None 576 try: 577 if tarfile.is_tarfile(filename): 578 archive = tarfile.open(filename) 579 if extractDir: 580 rootDir = extractDir 581 else: 582 rootDir = archive.getnames()[0].split('/')[0] 583 if dontExtract != None: 584 members = (m for m in archive.getmembers() 585 if not any((fnmatch.fnmatch(m.name, p) 586 for p in dontExtract))) 587 elif zipfile.is_zipfile(filename): 588 archive = zipfile.ZipFile(filename) 589 if extractDir: 590 rootDir = extractDir 591 else: 592 rootDir = archive.namelist()[0].split('/')[0] 593 if dontExtract != None: 594 members = (m for m in archive.getnames() 595 if not any((fnmatch.fnmatch(m, p) 596 for p in dontExtract))) 597 else: 598 raise RuntimeError("unrecognized archive file type") 599 600 with archive: 601 extractedPath = os.path.abspath(rootDir) 602 if force and os.path.isdir(extractedPath): 603 shutil.rmtree(extractedPath) 604 605 if os.path.isdir(extractedPath): 606 PrintInfo("Directory {0} already exists, skipping extract" 607 .format(extractedPath)) 608 else: 609 PrintInfo("Extracting archive to {0}".format(extractedPath)) 610 611 # Extract to a temporary directory then move the contents 612 # to the expected location when complete. This ensures that 613 # incomplete extracts will be retried if the script is run 614 # again. 615 tmpExtractedPath = os.path.abspath("extract_dir") 616 if os.path.isdir(tmpExtractedPath): 617 shutil.rmtree(tmpExtractedPath) 618 619 archive.extractall(tmpExtractedPath, members=members) 620 621 shutil.move(os.path.join(tmpExtractedPath, rootDir), 622 extractedPath) 623 shutil.rmtree(tmpExtractedPath) 624 625 return extractedPath 626 except Exception as e: 627 # If extraction failed for whatever reason, assume the 628 # archive file was bad and move it aside so that re-running 629 # the script will try downloading and extracting again. 630 shutil.move(filename, filename + ".bad") 631 raise RuntimeError("Failed to extract archive {filename}: {err}" 632 .format(filename=filename, err=e)) 633 634############################################################ 635# 3rd-Party Dependencies 636 637AllDependencies = list() 638AllDependenciesByName = dict() 639 640class Dependency(object): 641 def __init__(self, name, installer, *files): 642 self.name = name 643 self.installer = installer 644 self.filesToCheck = files 645 646 AllDependencies.append(self) 647 AllDependenciesByName.setdefault(name.lower(), self) 648 649 def Exists(self, context): 650 return all([os.path.isfile(os.path.join(context.instDir, f)) 651 for f in self.filesToCheck]) 652 653class PythonDependency(object): 654 def __init__(self, name, getInstructions, moduleNames): 655 self.name = name 656 self.getInstructions = getInstructions 657 self.moduleNames = moduleNames 658 659 def Exists(self, context): 660 # If one of the modules in our list imports successfully, we are good. 661 for moduleName in self.moduleNames: 662 try: 663 pyModule = __import__(moduleName) 664 return True 665 except: 666 pass 667 668 return False 669 670def AnyPythonDependencies(deps): 671 return any([type(d) is PythonDependency for d in deps]) 672 673############################################################ 674# zlib 675 676ZLIB_URL = "https://github.com/madler/zlib/archive/v1.2.11.zip" 677 678def InstallZlib(context, force, buildArgs): 679 with CurrentWorkingDirectory(DownloadURL(ZLIB_URL, context, force)): 680 RunCMake(context, force, buildArgs) 681 682ZLIB = Dependency("zlib", InstallZlib, "include/zlib.h") 683 684############################################################ 685# boost 686 687if MacOS(): 688 BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" 689 BOOST_VERSION_FILE = "include/boost/version.hpp" 690elif Linux(): 691 if Python3(): 692 BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" 693 else: 694 BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.66.0/source/boost_1_66_0.tar.gz" 695 BOOST_VERSION_FILE = "include/boost/version.hpp" 696elif Windows(): 697 # The default installation of boost on Windows puts headers in a versioned 698 # subdirectory, which we have to account for here. In theory, specifying 699 # "layout=system" would make the Windows install match Linux/MacOS, but that 700 # causes problems for other dependencies that look for boost. 701 # 702 # boost 1.70 is required for Visual Studio 2019. For simplicity, we use 703 # this version for all older Visual Studio versions as well. 704 BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" 705 BOOST_VERSION_FILE = "include/boost-1_70/boost/version.hpp" 706 707def InstallBoost_Helper(context, force, buildArgs): 708 # Documentation files in the boost archive can have exceptionally 709 # long paths. This can lead to errors when extracting boost on Windows, 710 # since paths are limited to 260 characters by default on that platform. 711 # To avoid this, we skip extracting all documentation. 712 # 713 # For some examples, see: https://svn.boost.org/trac10/ticket/11677 714 dontExtract = ["*/doc/*", "*/libs/*/doc/*"] 715 716 with CurrentWorkingDirectory(DownloadURL(BOOST_URL, context, force, 717 dontExtract=dontExtract)): 718 bootstrap = "bootstrap.bat" if Windows() else "./bootstrap.sh" 719 Run('{bootstrap} --prefix="{instDir}"' 720 .format(bootstrap=bootstrap, instDir=context.instDir)) 721 722 # b2 supports at most -j64 and will error if given a higher value. 723 num_procs = min(64, context.numJobs) 724 725 # boost only accepts three variants: debug, release, profile 726 boostBuildVariant = "profile" 727 if context.buildDebug: 728 boostBuildVariant= "debug" 729 elif context.buildRelease: 730 boostBuildVariant= "release" 731 elif context.buildRelWithDebug: 732 boostBuildVariant= "profile" 733 734 b2_settings = [ 735 '--prefix="{instDir}"'.format(instDir=context.instDir), 736 '--build-dir="{buildDir}"'.format(buildDir=context.buildDir), 737 '-j{procs}'.format(procs=num_procs), 738 'address-model=64', 739 'link=shared', 740 'runtime-link=shared', 741 'threading=multi', 742 'variant={variant}'.format(variant=boostBuildVariant), 743 '--with-atomic', 744 '--with-program_options', 745 '--with-regex' 746 ] 747 748 if context.buildPython: 749 b2_settings.append("--with-python") 750 pythonInfo = GetPythonInfo(context) 751 # This is the only platform-independent way to configure these 752 # settings correctly and robustly for the Boost jam build system. 753 # There are Python config arguments that can be passed to bootstrap 754 # but those are not available in boostrap.bat (Windows) so we must 755 # take the following approach: 756 projectPath = 'python-config.jam' 757 with open(projectPath, 'w') as projectFile: 758 # Note that we must escape any special characters, like 759 # backslashes for jam, hence the mods below for the path 760 # arguments. Also, if the path contains spaces jam will not 761 # handle them well. Surround the path parameters in quotes. 762 projectFile.write('using python : %s\n' % pythonInfo[3]) 763 projectFile.write(' : "%s"\n' % pythonInfo[0].replace("\\","/")) 764 projectFile.write(' : "%s"\n' % pythonInfo[2].replace("\\","/")) 765 projectFile.write(' : "%s"\n' % os.path.dirname(pythonInfo[1]).replace("\\","/")) 766 if context.buildDebug and context.debugPython: 767 projectFile.write(' : <python-debugging>on\n') 768 projectFile.write(' ;\n') 769 b2_settings.append("--user-config=python-config.jam") 770 771 if context.buildDebug and context.debugPython: 772 b2_settings.append("python-debugging=on") 773 774 if context.buildOIIO: 775 b2_settings.append("--with-date_time") 776 777 if context.buildOIIO or context.enableOpenVDB: 778 b2_settings.append("--with-system") 779 b2_settings.append("--with-thread") 780 781 if context.enableOpenVDB: 782 b2_settings.append("--with-iostreams") 783 784 # b2 with -sNO_COMPRESSION=1 fails with the following error message: 785 # error: at [...]/boost_1_61_0/tools/build/src/kernel/modules.jam:107 786 # error: Unable to find file or target named 787 # error: '/zlib//zlib' 788 # error: referred to from project at 789 # error: 'libs/iostreams/build' 790 # error: could not resolve project reference '/zlib' 791 792 # But to avoid an extra library dependency, we can still explicitly 793 # exclude the bzip2 compression from boost_iostreams (note that 794 # OpenVDB uses blosc compression). 795 b2_settings.append("-sNO_BZIP2=1") 796 797 if context.buildOIIO: 798 b2_settings.append("--with-filesystem") 799 800 if force: 801 b2_settings.append("-a") 802 803 if Windows(): 804 # toolset parameter for Visual Studio documented here: 805 # https://github.com/boostorg/build/blob/develop/src/tools/msvc.jam 806 if context.cmakeToolset == "v142": 807 b2_settings.append("toolset=msvc-14.2") 808 elif context.cmakeToolset == "v141": 809 b2_settings.append("toolset=msvc-14.1") 810 elif context.cmakeToolset == "v140": 811 b2_settings.append("toolset=msvc-14.0") 812 elif IsVisualStudio2019OrGreater(): 813 b2_settings.append("toolset=msvc-14.2") 814 elif IsVisualStudio2017OrGreater(): 815 b2_settings.append("toolset=msvc-14.1") 816 else: 817 b2_settings.append("toolset=msvc-14.0") 818 819 if MacOS(): 820 # Must specify toolset=clang to ensure install_name for boost 821 # libraries includes @rpath 822 b2_settings.append("toolset=clang") 823 824 if context.buildDebug: 825 b2_settings.append("--debug-configuration") 826 827 # Add on any user-specified extra arguments. 828 b2_settings += buildArgs 829 830 # Append extra argument controlling libstdc++ ABI if specified. 831 AppendCXX11ABIArg("cxxflags", context, b2_settings) 832 833 b2 = "b2" if Windows() else "./b2" 834 Run('{b2} {options} install' 835 .format(b2=b2, options=" ".join(b2_settings))) 836 837def InstallBoost(context, force, buildArgs): 838 # Boost's build system will install the version.hpp header before 839 # building its libraries. We make sure to remove it in case of 840 # any failure to ensure that the build script detects boost as a 841 # dependency to build the next time it's run. 842 try: 843 InstallBoost_Helper(context, force, buildArgs) 844 except: 845 versionHeader = os.path.join(context.instDir, BOOST_VERSION_FILE) 846 if os.path.isfile(versionHeader): 847 try: os.remove(versionHeader) 848 except: pass 849 raise 850 851BOOST = Dependency("boost", InstallBoost, BOOST_VERSION_FILE) 852 853############################################################ 854# Intel TBB 855 856if Windows(): 857 TBB_URL = "https://github.com/oneapi-src/oneTBB/releases/download/2018_U6/tbb2018_20180822oss_win.zip" 858elif MacOS(): 859 # On MacOS we experience various crashes in tests during teardown 860 # starting with 2018 Update 2. Until we figure that out, we use 861 # 2018 Update 1 on this platform. 862 TBB_URL = "https://github.com/oneapi-src/oneTBB/archive/2018_U1.tar.gz" 863else: 864 TBB_URL = "https://github.com/oneapi-src/oneTBB/archive/2018_U6.tar.gz" 865 866def InstallTBB(context, force, buildArgs): 867 if Windows(): 868 InstallTBB_Windows(context, force, buildArgs) 869 elif Linux() or MacOS(): 870 InstallTBB_LinuxOrMacOS(context, force, buildArgs) 871 872def InstallTBB_Windows(context, force, buildArgs): 873 TBB_ROOT_DIR_NAME = "tbb2018_20180822oss" 874 with CurrentWorkingDirectory(DownloadURL(TBB_URL, context, force, 875 TBB_ROOT_DIR_NAME)): 876 # On Windows, we simply copy headers and pre-built DLLs to 877 # the appropriate location. 878 if buildArgs: 879 PrintWarning("Ignoring build arguments {}, TBB is " 880 "not built from source on this platform." 881 .format(buildArgs)) 882 883 CopyFiles(context, "bin\\intel64\\vc14\\*.*", "bin") 884 CopyFiles(context, "lib\\intel64\\vc14\\*.*", "lib") 885 CopyDirectory(context, "include\\serial", "include\\serial") 886 CopyDirectory(context, "include\\tbb", "include\\tbb") 887 888def InstallTBB_LinuxOrMacOS(context, force, buildArgs): 889 with CurrentWorkingDirectory(DownloadURL(TBB_URL, context, force)): 890 # Note: TBB installation fails on OSX when cuda is installed, a 891 # suggested fix: 892 # https://github.com/spack/spack/issues/6000#issuecomment-358817701 893 if MacOS(): 894 PatchFile("build/macos.inc", 895 [("shell clang -v ", "shell clang --version ")]) 896 897 # Append extra argument controlling libstdc++ ABI if specified. 898 AppendCXX11ABIArg("CXXFLAGS", context, buildArgs) 899 900 # TBB does not support out-of-source builds in a custom location. 901 Run('make -j{procs} {buildArgs}' 902 .format(procs=context.numJobs, 903 buildArgs=" ".join(buildArgs))) 904 905 # Install both release and debug builds. USD requires the debug 906 # libraries when building in debug mode, and installing both 907 # makes it easier for users to install dependencies in some 908 # location that can be shared by both release and debug USD 909 # builds. Plus, the TBB build system builds both versions anyway. 910 CopyFiles(context, "build/*_release/libtbb*.*", "lib") 911 CopyFiles(context, "build/*_debug/libtbb*.*", "lib") 912 CopyDirectory(context, "include/serial", "include/serial") 913 CopyDirectory(context, "include/tbb", "include/tbb") 914 915TBB = Dependency("TBB", InstallTBB, "include/tbb/tbb.h") 916 917############################################################ 918# JPEG 919 920if Windows(): 921 JPEG_URL = "https://github.com/libjpeg-turbo/libjpeg-turbo/archive/1.5.1.zip" 922else: 923 JPEG_URL = "https://www.ijg.org/files/jpegsrc.v9b.tar.gz" 924 925def InstallJPEG(context, force, buildArgs): 926 if Windows(): 927 InstallJPEG_Turbo(context, force, buildArgs) 928 else: 929 InstallJPEG_Lib(context, force, buildArgs) 930 931def InstallJPEG_Turbo(context, force, buildArgs): 932 with CurrentWorkingDirectory(DownloadURL(JPEG_URL, context, force)): 933 RunCMake(context, force, buildArgs) 934 935def InstallJPEG_Lib(context, force, buildArgs): 936 with CurrentWorkingDirectory(DownloadURL(JPEG_URL, context, force)): 937 Run('./configure --prefix="{instDir}" ' 938 '--disable-static --enable-shared ' 939 '{buildArgs}' 940 .format(instDir=context.instDir, 941 buildArgs=" ".join(buildArgs))) 942 Run('make -j{procs} install' 943 .format(procs=context.numJobs)) 944 945JPEG = Dependency("JPEG", InstallJPEG, "include/jpeglib.h") 946 947############################################################ 948# TIFF 949 950TIFF_URL = "https://gitlab.com/libtiff/libtiff/-/archive/Release-v4-0-7/libtiff-Release-v4-0-7.tar.gz" 951 952def InstallTIFF(context, force, buildArgs): 953 with CurrentWorkingDirectory(DownloadURL(TIFF_URL, context, force)): 954 # libTIFF has a build issue on Windows where tools/tiffgt.c 955 # unconditionally includes unistd.h, which does not exist. 956 # To avoid this, we patch the CMakeLists.txt to skip building 957 # the tools entirely. We do this on Linux and MacOS as well 958 # to avoid requiring some GL and X dependencies. 959 # 960 # We also need to skip building tests, since they rely on 961 # the tools we've just elided. 962 PatchFile("CMakeLists.txt", 963 [("add_subdirectory(tools)", "# add_subdirectory(tools)"), 964 ("add_subdirectory(test)", "# add_subdirectory(test)")]) 965 966 # The libTIFF CMakeScript says the ld-version-script 967 # functionality is only for compilers using GNU ld on 968 # ELF systems or systems which provide an emulation; therefore 969 # skipping it completely on mac and windows. 970 if MacOS() or Windows(): 971 extraArgs = ["-Dld-version-script=OFF"] 972 else: 973 extraArgs = [] 974 extraArgs += buildArgs 975 RunCMake(context, force, extraArgs) 976 977TIFF = Dependency("TIFF", InstallTIFF, "include/tiff.h") 978 979############################################################ 980# PNG 981 982PNG_URL = "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.29.tar.gz" 983 984def InstallPNG(context, force, buildArgs): 985 with CurrentWorkingDirectory(DownloadURL(PNG_URL, context, force)): 986 RunCMake(context, force, buildArgs) 987 988PNG = Dependency("PNG", InstallPNG, "include/png.h") 989 990############################################################ 991# IlmBase/OpenEXR 992 993OPENEXR_URL = "https://github.com/AcademySoftwareFoundation/openexr/archive/v2.3.0.zip" 994 995def InstallOpenEXR(context, force, buildArgs): 996 with CurrentWorkingDirectory(DownloadURL(OPENEXR_URL, context, force)): 997 RunCMake(context, force, 998 ['-DOPENEXR_BUILD_PYTHON_LIBS=OFF', 999 '-DOPENEXR_PACKAGE_PREFIX="{}"'.format(context.instDir), 1000 '-DOPENEXR_ENABLE_TESTS=OFF'] + buildArgs) 1001 1002OPENEXR = Dependency("OpenEXR", InstallOpenEXR, "include/OpenEXR/ImfVersion.h") 1003 1004############################################################ 1005# Ptex 1006 1007PTEX_URL = "https://github.com/wdas/ptex/archive/v2.1.33.zip" 1008 1009def InstallPtex(context, force, buildArgs): 1010 if Windows(): 1011 InstallPtex_Windows(context, force, buildArgs) 1012 else: 1013 InstallPtex_LinuxOrMacOS(context, force, buildArgs) 1014 1015def InstallPtex_Windows(context, force, buildArgs): 1016 with CurrentWorkingDirectory(DownloadURL(PTEX_URL, context, force)): 1017 # Ptex has a bug where the import library for the dynamic library and 1018 # the static library both get the same name, Ptex.lib, and as a 1019 # result one clobbers the other. We hack the appropriate CMake 1020 # file to prevent that. Since we don't need the static library we'll 1021 # rename that. 1022 # 1023 # In addition src\tests\CMakeLists.txt adds -DPTEX_STATIC to the 1024 # compiler but links tests against the dynamic library, causing the 1025 # links to fail. We patch the file to not add the -DPTEX_STATIC 1026 PatchFile('src\\ptex\\CMakeLists.txt', 1027 [("set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptex)", 1028 "set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptexs)")]) 1029 PatchFile('src\\tests\\CMakeLists.txt', 1030 [("add_definitions(-DPTEX_STATIC)", 1031 "# add_definitions(-DPTEX_STATIC)")]) 1032 1033 # Patch Ptex::String to export symbol for operator<< 1034 # This is required for newer versions of OIIO, which make use of the 1035 # this operator on Windows platform specifically. 1036 PatchFile('src\\ptex\\Ptexture.h', 1037 [("std::ostream& operator << (std::ostream& stream, const Ptex::String& str);", 1038 "PTEXAPI std::ostream& operator << (std::ostream& stream, const Ptex::String& str);")]) 1039 1040 1041 RunCMake(context, force, buildArgs) 1042 1043def InstallPtex_LinuxOrMacOS(context, force, buildArgs): 1044 with CurrentWorkingDirectory(DownloadURL(PTEX_URL, context, force)): 1045 RunCMake(context, force, buildArgs) 1046 1047PTEX = Dependency("Ptex", InstallPtex, "include/PtexVersion.h") 1048 1049############################################################ 1050# BLOSC (Compression used by OpenVDB) 1051 1052# Using blosc v1.20.1 to avoid build errors on macOS Catalina (10.15) 1053# related to implicit declaration of functions in zlib. See: 1054# https://github.com/Blosc/python-blosc/issues/229 1055BLOSC_URL = "https://github.com/Blosc/c-blosc/archive/v1.20.1.zip" 1056 1057def InstallBLOSC(context, force, buildArgs): 1058 with CurrentWorkingDirectory(DownloadURL(BLOSC_URL, context, force)): 1059 RunCMake(context, force, buildArgs) 1060 1061BLOSC = Dependency("Blosc", InstallBLOSC, "include/blosc.h") 1062 1063############################################################ 1064# OpenVDB 1065 1066# Using version 6.1.0 since it has reworked its CMake files so that 1067# there are better options to not compile the OpenVDB binaries and to 1068# not require additional dependencies such as GLFW. Note that version 1069# 6.1.0 does require CMake 3.3 though. 1070 1071OPENVDB_URL = "https://github.com/AcademySoftwareFoundation/openvdb/archive/v6.1.0.zip" 1072 1073def InstallOpenVDB(context, force, buildArgs): 1074 with CurrentWorkingDirectory(DownloadURL(OPENVDB_URL, context, force)): 1075 extraArgs = [ 1076 '-DOPENVDB_BUILD_PYTHON_MODULE=OFF', 1077 '-DOPENVDB_BUILD_BINARIES=OFF', 1078 '-DOPENVDB_BUILD_UNITTESTS=OFF' 1079 ] 1080 1081 # Make sure to use boost installed by the build script and not any 1082 # system installed boost 1083 extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') 1084 extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') 1085 1086 extraArgs.append('-DBLOSC_ROOT="{instDir}"' 1087 .format(instDir=context.instDir)) 1088 extraArgs.append('-DTBB_ROOT="{instDir}"' 1089 .format(instDir=context.instDir)) 1090 # OpenVDB needs Half type from IlmBase 1091 extraArgs.append('-DILMBASE_ROOT="{instDir}"' 1092 .format(instDir=context.instDir)) 1093 1094 # Add on any user-specified extra arguments. 1095 extraArgs += buildArgs 1096 1097 RunCMake(context, force, extraArgs) 1098 1099OPENVDB = Dependency("OpenVDB", InstallOpenVDB, "include/openvdb/openvdb.h") 1100 1101############################################################ 1102# OpenImageIO 1103 1104OIIO_URL = "https://github.com/OpenImageIO/oiio/archive/Release-2.1.16.0.zip" 1105 1106def InstallOpenImageIO(context, force, buildArgs): 1107 with CurrentWorkingDirectory(DownloadURL(OIIO_URL, context, force)): 1108 extraArgs = ['-DOIIO_BUILD_TOOLS=OFF', 1109 '-DOIIO_BUILD_TESTS=OFF', 1110 '-DUSE_PYTHON=OFF', 1111 '-DSTOP_ON_WARNING=OFF'] 1112 1113 # OIIO's FindOpenEXR module circumvents CMake's normal library 1114 # search order, which causes versions of OpenEXR installed in 1115 # /usr/local or other hard-coded locations in the module to 1116 # take precedence over the version we've built, which would 1117 # normally be picked up when we specify CMAKE_PREFIX_PATH. 1118 # This may lead to undefined symbol errors at build or runtime. 1119 # So, we explicitly specify the OpenEXR we want to use here. 1120 extraArgs.append('-DOPENEXR_ROOT="{instDir}"' 1121 .format(instDir=context.instDir)) 1122 1123 # If Ptex support is disabled in USD, disable support in OpenImageIO 1124 # as well. This ensures OIIO doesn't accidentally pick up a Ptex 1125 # library outside of our build. 1126 if not context.enablePtex: 1127 extraArgs.append('-DUSE_PTEX=OFF') 1128 1129 # Make sure to use boost installed by the build script and not any 1130 # system installed boost 1131 extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') 1132 extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') 1133 1134 # Add on any user-specified extra arguments. 1135 extraArgs += buildArgs 1136 1137 RunCMake(context, force, extraArgs) 1138 1139OPENIMAGEIO = Dependency("OpenImageIO", InstallOpenImageIO, 1140 "include/OpenImageIO/oiioversion.h") 1141 1142############################################################ 1143# OpenColorIO 1144 1145OCIO_URL = "https://github.com/imageworks/OpenColorIO/archive/v1.1.0.zip" 1146 1147def InstallOpenColorIO(context, force, buildArgs): 1148 with CurrentWorkingDirectory(DownloadURL(OCIO_URL, context, force)): 1149 extraArgs = ['-DOCIO_BUILD_TRUELIGHT=OFF', 1150 '-DOCIO_BUILD_APPS=OFF', 1151 '-DOCIO_BUILD_NUKE=OFF', 1152 '-DOCIO_BUILD_DOCS=OFF', 1153 '-DOCIO_BUILD_TESTS=OFF', 1154 '-DOCIO_BUILD_PYGLUE=OFF', 1155 '-DOCIO_BUILD_JNIGLUE=OFF', 1156 '-DOCIO_STATIC_JNIGLUE=OFF'] 1157 1158 # OpenImageIO v1.1.0 fails to build on Windows with the RelWithDebInfo 1159 # build type because it doesn't set up the correct properties for the 1160 # YAML library it relies on. This patch works around that issue. 1161 if Windows() and context.buildRelWithDebug: 1162 PatchFile("CMakeLists.txt", 1163 [("IMPORTED_LOCATION_RELEASE", 1164 "IMPORTED_LOCATION_RELWITHDEBINFO")]) 1165 1166 # The OCIO build treats all warnings as errors but several come up 1167 # on various platforms, including: 1168 # - On gcc6, v1.1.0 emits many -Wdeprecated-declaration warnings for 1169 # std::auto_ptr 1170 # - On clang, v1.1.0 emits a -Wself-assign-field warning. This is fixed 1171 # in https://github.com/AcademySoftwareFoundation/OpenColorIO/commit/0be465feb9ac2d34bd8171f30909b276c1efa996 1172 # 1173 # To avoid build failures we force all warnings off for this build. 1174 if GetVisualStudioCompilerAndVersion(): 1175 # This doesn't work because CMake stores default flags for 1176 # MSVC in CMAKE_CXX_FLAGS and this would overwrite them. 1177 # However, we don't seem to get any warnings on Windows 1178 # (at least with VS2015 and 2017). 1179 # extraArgs.append('-DCMAKE_CXX_FLAGS=/w') 1180 pass 1181 else: 1182 extraArgs.append('-DCMAKE_CXX_FLAGS=-w') 1183 1184 # Add on any user-specified extra arguments. 1185 extraArgs += buildArgs 1186 1187 RunCMake(context, force, extraArgs) 1188 1189OPENCOLORIO = Dependency("OpenColorIO", InstallOpenColorIO, 1190 "include/OpenColorIO/OpenColorABI.h") 1191 1192############################################################ 1193# OpenSubdiv 1194 1195OPENSUBDIV_URL = "https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_4_3.zip" 1196 1197def InstallOpenSubdiv(context, force, buildArgs): 1198 with CurrentWorkingDirectory(DownloadURL(OPENSUBDIV_URL, context, force)): 1199 extraArgs = [ 1200 '-DNO_EXAMPLES=ON', 1201 '-DNO_TUTORIALS=ON', 1202 '-DNO_REGRESSION=ON', 1203 '-DNO_DOC=ON', 1204 '-DNO_OMP=ON', 1205 '-DNO_CUDA=ON', 1206 '-DNO_OPENCL=ON', 1207 '-DNO_DX=ON', 1208 '-DNO_TESTS=ON', 1209 '-DNO_GLEW=ON', 1210 '-DNO_GLFW=ON', 1211 ] 1212 1213 # If Ptex support is disabled in USD, disable support in OpenSubdiv 1214 # as well. This ensures OSD doesn't accidentally pick up a Ptex 1215 # library outside of our build. 1216 if not context.enablePtex: 1217 extraArgs.append('-DNO_PTEX=ON') 1218 1219 # NOTE: For now, we disable TBB in our OpenSubdiv build. 1220 # This avoids an issue where OpenSubdiv will link against 1221 # all TBB libraries it finds, including libtbbmalloc and 1222 # libtbbmalloc_proxy. On Linux and MacOS, this has the 1223 # unwanted effect of replacing the system allocator with 1224 # tbbmalloc. 1225 extraArgs.append('-DNO_TBB=ON') 1226 1227 # Add on any user-specified extra arguments. 1228 extraArgs += buildArgs 1229 1230 # OpenSubdiv seems to error when building on windows w/ Ninja... 1231 # ...so just use the default generator (ie, Visual Studio on Windows) 1232 # until someone can sort it out 1233 oldGenerator = context.cmakeGenerator 1234 if oldGenerator == "Ninja" and Windows(): 1235 context.cmakeGenerator = None 1236 1237 # OpenSubdiv 3.3 and later on MacOS occasionally runs into build 1238 # failures with multiple build jobs. Workaround this by using 1239 # just 1 job for now. See: 1240 # https://github.com/PixarAnimationStudios/OpenSubdiv/issues/1194 1241 oldNumJobs = context.numJobs 1242 if MacOS(): 1243 context.numJobs = 1 1244 1245 try: 1246 RunCMake(context, force, extraArgs) 1247 finally: 1248 context.cmakeGenerator = oldGenerator 1249 context.numJobs = oldNumJobs 1250 1251OPENSUBDIV = Dependency("OpenSubdiv", InstallOpenSubdiv, 1252 "include/opensubdiv/version.h") 1253 1254############################################################ 1255# PyOpenGL 1256 1257def GetPyOpenGLInstructions(): 1258 return ('PyOpenGL is not installed. If you have pip ' 1259 'installed, run "pip install PyOpenGL" to ' 1260 'install it, then re-run this script.\n' 1261 'If PyOpenGL is already installed, you may need to ' 1262 'update your PYTHONPATH to indicate where it is ' 1263 'located.') 1264 1265PYOPENGL = PythonDependency("PyOpenGL", GetPyOpenGLInstructions, 1266 moduleNames=["OpenGL"]) 1267 1268############################################################ 1269# PySide 1270 1271def GetPySideInstructions(): 1272 # For licensing reasons, this script cannot install PySide itself. 1273 if Windows(): 1274 # There is no distribution of PySide2 for Windows for Python 2.7. 1275 # So use PySide instead. See the following for more details: 1276 # https://wiki.qt.io/Qt_for_Python/Considerations#Missing_Windows_.2F_Python_2.7_release 1277 return ('PySide is not installed. If you have pip ' 1278 'installed, run "pip install PySide" ' 1279 'to install it, then re-run this script.\n' 1280 'If PySide is already installed, you may need to ' 1281 'update your PYTHONPATH to indicate where it is ' 1282 'located.') 1283 else: 1284 return ('PySide2 is not installed. If you have pip ' 1285 'installed, run "pip install PySide2" ' 1286 'to install it, then re-run this script.\n' 1287 'If PySide2 is already installed, you may need to ' 1288 'update your PYTHONPATH to indicate where it is ' 1289 'located.') 1290 1291PYSIDE = PythonDependency("PySide", GetPySideInstructions, 1292 moduleNames=["PySide", "PySide2"]) 1293 1294############################################################ 1295# HDF5 1296 1297HDF5_URL = "https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.0-patch1/src/hdf5-1.10.0-patch1.zip" 1298 1299def InstallHDF5(context, force, buildArgs): 1300 with CurrentWorkingDirectory(DownloadURL(HDF5_URL, context, force)): 1301 RunCMake(context, force, 1302 ['-DBUILD_TESTING=OFF', 1303 '-DHDF5_BUILD_TOOLS=OFF', 1304 '-DHDF5_BUILD_EXAMPLES=OFF'] + buildArgs) 1305 1306HDF5 = Dependency("HDF5", InstallHDF5, "include/hdf5.h") 1307 1308############################################################ 1309# Alembic 1310 1311ALEMBIC_URL = "https://github.com/alembic/alembic/archive/1.7.10.zip" 1312 1313def InstallAlembic(context, force, buildArgs): 1314 with CurrentWorkingDirectory(DownloadURL(ALEMBIC_URL, context, force)): 1315 cmakeOptions = ['-DUSE_BINARIES=OFF', '-DUSE_TESTS=OFF'] 1316 if context.enableHDF5: 1317 # HDF5 requires the H5_BUILT_AS_DYNAMIC_LIB macro be defined if 1318 # it was built with CMake as a dynamic library. 1319 cmakeOptions += [ 1320 '-DUSE_HDF5=ON', 1321 '-DHDF5_ROOT="{instDir}"'.format(instDir=context.instDir), 1322 '-DCMAKE_CXX_FLAGS="-D H5_BUILT_AS_DYNAMIC_LIB"'] 1323 else: 1324 cmakeOptions += ['-DUSE_HDF5=OFF'] 1325 1326 cmakeOptions += buildArgs 1327 1328 RunCMake(context, force, cmakeOptions) 1329 1330ALEMBIC = Dependency("Alembic", InstallAlembic, "include/Alembic/Abc/Base.h") 1331 1332############################################################ 1333# Draco 1334 1335DRACO_URL = "https://github.com/google/draco/archive/master.zip" 1336 1337def InstallDraco(context, force, buildArgs): 1338 with CurrentWorkingDirectory(DownloadURL(DRACO_URL, context, force)): 1339 cmakeOptions = ['-DBUILD_USD_PLUGIN=ON'] 1340 cmakeOptions += buildArgs 1341 RunCMake(context, force, cmakeOptions) 1342 1343DRACO = Dependency("Draco", InstallDraco, "include/draco/compression/decode.h") 1344 1345############################################################ 1346# MaterialX 1347 1348MATERIALX_URL = "https://github.com/materialx/MaterialX/archive/v1.38.0.zip" 1349 1350def InstallMaterialX(context, force, buildArgs): 1351 with CurrentWorkingDirectory(DownloadURL(MATERIALX_URL, context, force)): 1352 # USD requires MaterialX to be built as a shared library on Linux and MacOS 1353 # Currently MaterialX does not support shared builds on Windows 1354 cmakeOptions = [] 1355 if Linux() or MacOS(): 1356 cmakeOptions += ['-DMATERIALX_BUILD_SHARED_LIBS=ON'] 1357 1358 cmakeOptions += buildArgs; 1359 1360 RunCMake(context, force, cmakeOptions) 1361 1362MATERIALX = Dependency("MaterialX", InstallMaterialX, "include/MaterialXCore/Library.h") 1363 1364############################################################ 1365# Embree 1366# For MacOS we use version 3.7.0 to include a fix from Intel 1367# to build on Catalina. 1368if MacOS(): 1369 EMBREE_URL = "https://github.com/embree/embree/archive/v3.7.0.tar.gz" 1370else: 1371 EMBREE_URL = "https://github.com/embree/embree/archive/v3.2.2.tar.gz" 1372 1373def InstallEmbree(context, force, buildArgs): 1374 with CurrentWorkingDirectory(DownloadURL(EMBREE_URL, context, force)): 1375 extraArgs = [ 1376 '-DTBB_ROOT={instDir}'.format(instDir=context.instDir), 1377 '-DEMBREE_TUTORIALS=OFF', 1378 '-DEMBREE_ISPC_SUPPORT=OFF' 1379 ] 1380 1381 # By default Embree fails to build on Visual Studio 2015 due 1382 # to an internal compiler issue that is worked around via the 1383 # following flag. For more details see: 1384 # https://github.com/embree/embree/issues/157 1385 if IsVisualStudio2015OrGreater() and not IsVisualStudio2017OrGreater(): 1386 extraArgs.append('-DCMAKE_CXX_FLAGS=/d2SSAOptimizer-') 1387 1388 extraArgs += buildArgs 1389 1390 RunCMake(context, force, extraArgs) 1391 1392EMBREE = Dependency("Embree", InstallEmbree, "include/embree3/rtcore.h") 1393 1394############################################################ 1395# USD 1396 1397def InstallUSD(context, force, buildArgs): 1398 with CurrentWorkingDirectory(context.usdSrcDir): 1399 extraArgs = [] 1400 1401 extraArgs.append('-DPXR_PREFER_SAFETY_OVER_SPEED=' + 1402 'ON' if context.safetyFirst else 'OFF') 1403 1404 if context.buildPython: 1405 extraArgs.append('-DPXR_ENABLE_PYTHON_SUPPORT=ON') 1406 if Python3(): 1407 extraArgs.append('-DPXR_USE_PYTHON_3=ON') 1408 1409 # Many people on Windows may not have python with the 1410 # debugging symbol ( python27_d.lib ) installed, this is the common case 1411 # where one downloads the python from official download website. Therefore we 1412 # can still let people decide to build USD with release version of python if 1413 # debugging into python land is not what they want which can be done by setting the 1414 # debugPython 1415 if context.buildDebug and context.debugPython: 1416 extraArgs.append('-DPXR_USE_DEBUG_PYTHON=ON') 1417 else: 1418 extraArgs.append('-DPXR_USE_DEBUG_PYTHON=OFF') 1419 1420 # CMake has trouble finding the executable, library, and include 1421 # directories when there are multiple versions of Python installed. 1422 # This can lead to crashes due to USD being linked against one 1423 # version of Python but running through some other Python 1424 # interpreter version. This primarily shows up on macOS, as it's 1425 # common to have a Python install that's separate from the one 1426 # included with the system. 1427 # 1428 # To avoid this, we try to determine these paths from Python 1429 # itself rather than rely on CMake's heuristics. 1430 pythonInfo = GetPythonInfo(context) 1431 if pythonInfo: 1432 # According to FindPythonLibs.cmake these are the variables 1433 # to set to specify which Python installation to use. 1434 extraArgs.append('-DPYTHON_EXECUTABLE="{pyExecPath}"' 1435 .format(pyExecPath=pythonInfo[0])) 1436 extraArgs.append('-DPYTHON_LIBRARY="{pyLibPath}"' 1437 .format(pyLibPath=pythonInfo[1])) 1438 extraArgs.append('-DPYTHON_INCLUDE_DIR="{pyIncPath}"' 1439 .format(pyIncPath=pythonInfo[2])) 1440 else: 1441 extraArgs.append('-DPXR_ENABLE_PYTHON_SUPPORT=OFF') 1442 1443 if context.buildShared: 1444 extraArgs.append('-DBUILD_SHARED_LIBS=ON') 1445 elif context.buildMonolithic: 1446 extraArgs.append('-DPXR_BUILD_MONOLITHIC=ON') 1447 1448 if context.buildDebug: 1449 extraArgs.append('-DTBB_USE_DEBUG_BUILD=ON') 1450 else: 1451 extraArgs.append('-DTBB_USE_DEBUG_BUILD=OFF') 1452 1453 if context.buildDocs: 1454 extraArgs.append('-DPXR_BUILD_DOCUMENTATION=ON') 1455 else: 1456 extraArgs.append('-DPXR_BUILD_DOCUMENTATION=OFF') 1457 1458 if context.buildTests: 1459 extraArgs.append('-DPXR_BUILD_TESTS=ON') 1460 else: 1461 extraArgs.append('-DPXR_BUILD_TESTS=OFF') 1462 1463 if context.buildExamples: 1464 extraArgs.append('-DPXR_BUILD_EXAMPLES=ON') 1465 else: 1466 extraArgs.append('-DPXR_BUILD_EXAMPLES=OFF') 1467 1468 if context.buildTutorials: 1469 extraArgs.append('-DPXR_BUILD_TUTORIALS=ON') 1470 else: 1471 extraArgs.append('-DPXR_BUILD_TUTORIALS=OFF') 1472 1473 if context.buildTools: 1474 extraArgs.append('-DPXR_BUILD_USD_TOOLS=ON') 1475 else: 1476 extraArgs.append('-DPXR_BUILD_USD_TOOLS=OFF') 1477 1478 if context.buildImaging: 1479 extraArgs.append('-DPXR_BUILD_IMAGING=ON') 1480 if context.enablePtex: 1481 extraArgs.append('-DPXR_ENABLE_PTEX_SUPPORT=ON') 1482 else: 1483 extraArgs.append('-DPXR_ENABLE_PTEX_SUPPORT=OFF') 1484 1485 if context.enableOpenVDB: 1486 extraArgs.append('-DPXR_ENABLE_OPENVDB_SUPPORT=ON') 1487 else: 1488 extraArgs.append('-DPXR_ENABLE_OPENVDB_SUPPORT=OFF') 1489 1490 if context.buildEmbree: 1491 extraArgs.append('-DPXR_BUILD_EMBREE_PLUGIN=ON') 1492 else: 1493 extraArgs.append('-DPXR_BUILD_EMBREE_PLUGIN=OFF') 1494 1495 if context.buildPrman: 1496 if context.prmanLocation: 1497 extraArgs.append('-DRENDERMAN_LOCATION="{location}"' 1498 .format(location=context.prmanLocation)) 1499 extraArgs.append('-DPXR_BUILD_PRMAN_PLUGIN=ON') 1500 else: 1501 extraArgs.append('-DPXR_BUILD_PRMAN_PLUGIN=OFF') 1502 1503 if context.buildOIIO: 1504 extraArgs.append('-DPXR_BUILD_OPENIMAGEIO_PLUGIN=ON') 1505 else: 1506 extraArgs.append('-DPXR_BUILD_OPENIMAGEIO_PLUGIN=OFF') 1507 1508 if context.buildOCIO: 1509 extraArgs.append('-DPXR_BUILD_OPENCOLORIO_PLUGIN=ON') 1510 else: 1511 extraArgs.append('-DPXR_BUILD_OPENCOLORIO_PLUGIN=OFF') 1512 1513 else: 1514 extraArgs.append('-DPXR_BUILD_IMAGING=OFF') 1515 1516 if context.buildUsdImaging: 1517 extraArgs.append('-DPXR_BUILD_USD_IMAGING=ON') 1518 else: 1519 extraArgs.append('-DPXR_BUILD_USD_IMAGING=OFF') 1520 1521 if context.buildUsdview: 1522 extraArgs.append('-DPXR_BUILD_USDVIEW=ON') 1523 else: 1524 extraArgs.append('-DPXR_BUILD_USDVIEW=OFF') 1525 1526 if context.buildAlembic: 1527 extraArgs.append('-DPXR_BUILD_ALEMBIC_PLUGIN=ON') 1528 if context.enableHDF5: 1529 extraArgs.append('-DPXR_ENABLE_HDF5_SUPPORT=ON') 1530 1531 # CMAKE_PREFIX_PATH isn't sufficient for the FindHDF5 module 1532 # to find the HDF5 we've built, so provide an extra hint. 1533 extraArgs.append('-DHDF5_ROOT="{instDir}"' 1534 .format(instDir=context.instDir)) 1535 else: 1536 extraArgs.append('-DPXR_ENABLE_HDF5_SUPPORT=OFF') 1537 else: 1538 extraArgs.append('-DPXR_BUILD_ALEMBIC_PLUGIN=OFF') 1539 1540 if context.buildDraco: 1541 extraArgs.append('-DPXR_BUILD_DRACO_PLUGIN=ON') 1542 draco_root = (context.dracoLocation 1543 if context.dracoLocation else context.instDir) 1544 extraArgs.append('-DDRACO_ROOT="{}"'.format(draco_root)) 1545 else: 1546 extraArgs.append('-DPXR_BUILD_DRACO_PLUGIN=OFF') 1547 1548 if context.buildMaterialX: 1549 extraArgs.append('-DPXR_ENABLE_MATERIALX_SUPPORT=ON') 1550 else: 1551 extraArgs.append('-DPXR_ENABLE_MATERIALX_SUPPORT=OFF') 1552 1553 if Windows(): 1554 # Increase the precompiled header buffer limit. 1555 extraArgs.append('-DCMAKE_CXX_FLAGS="/Zm150"') 1556 1557 # Make sure to use boost installed by the build script and not any 1558 # system installed boost 1559 extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') 1560 extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') 1561 extraArgs += buildArgs 1562 1563 RunCMake(context, force, extraArgs) 1564 1565USD = Dependency("USD", InstallUSD, "include/pxr/pxr.h") 1566 1567############################################################ 1568# Install script 1569 1570programDescription = """\ 1571Installation Script for USD 1572 1573Builds and installs USD and 3rd-party dependencies to specified location. 1574 1575- Libraries: 1576The following is a list of libraries that this script will download and build 1577as needed. These names can be used to identify libraries for various script 1578options, like --force or --build-args. 1579 1580{libraryList} 1581 1582- Downloading Libraries: 1583If curl or powershell (on Windows) are installed and located in PATH, they 1584will be used to download dependencies. Otherwise, a built-in downloader will 1585be used. 1586 1587- Specifying Custom Build Arguments: 1588Users may specify custom build arguments for libraries using the --build-args 1589option. This values for this option must take the form <library name>,<option>. 1590For example: 1591 1592%(prog)s --build-args boost,cxxflags=... USD,-DPXR_STRICT_BUILD_MODE=ON ... 1593%(prog)s --build-args USD,"-DPXR_STRICT_BUILD_MODE=ON -DPXR_HEADLESS_TEST_MODE=ON" ... 1594 1595These arguments will be passed directly to the build system for the specified 1596library. Multiple quotes may be needed to ensure arguments are passed on 1597exactly as desired. Users must ensure these arguments are suitable for the 1598specified library and do not conflict with other options, otherwise build 1599errors may occur. 1600 1601- Python Versions and DCC Plugins: 1602Some DCCs (most notably, Maya) may ship with and run using their own version of 1603Python. In that case, it is important that USD and the plugins for that DCC are 1604built using the DCC's version of Python and not the system version. This can be 1605done by running %(prog)s using the DCC's version of Python. 1606 1607The flag --build-python-info allows calling the %(prog)s with any python (such as 1608system python) but pass in the python that you want USD to use to build the python 1609bindings with. This flag takes 4 arguments: python executable, python include directory 1610python library and python version. 1611 1612For example, to build USD on macOS for use in Maya 2019, run: 1613 1614/Applications/Autodesk/maya2019/Maya.app/Contents/bin/mayapy %(prog)s --no-usdview ... 1615 1616Note that this is primarily an issue on macOS, where a DCC's version of Python 1617is likely to conflict with the version provided by the system. On other 1618platforms, %(prog)s *should* be run using the system Python and *should not* 1619be run using the DCC's Python. 1620 1621- C++11 ABI Compatibility: 1622On Linux, the --use-cxx11-abi parameter can be used to specify whether to use 1623the C++11 ABI for libstdc++ when building USD and any dependencies. The value 1624given to this parameter will be used to define _GLIBCXX_USE_CXX11_ABI for 1625all builds. 1626 1627If this parameter is not specified, the compiler's default ABI will be used. 1628 1629For more details see: 1630https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html 1631""".format( 1632 libraryList=" ".join(sorted([d.name for d in AllDependencies]))) 1633 1634parser = argparse.ArgumentParser( 1635 formatter_class=argparse.RawDescriptionHelpFormatter, 1636 description=programDescription) 1637 1638parser.add_argument("install_dir", type=str, 1639 help="Directory where USD will be installed") 1640parser.add_argument("-n", "--dry_run", dest="dry_run", action="store_true", 1641 help="Only summarize what would happen") 1642 1643group = parser.add_mutually_exclusive_group() 1644group.add_argument("-v", "--verbose", action="count", default=1, 1645 dest="verbosity", 1646 help="Increase verbosity level (1-3)") 1647group.add_argument("-q", "--quiet", action="store_const", const=0, 1648 dest="verbosity", 1649 help="Suppress all output except for error messages") 1650 1651group = parser.add_argument_group(title="Build Options") 1652group.add_argument("-j", "--jobs", type=int, default=GetCPUCount(), 1653 help=("Number of build jobs to run in parallel. " 1654 "(default: # of processors [{0}])" 1655 .format(GetCPUCount()))) 1656group.add_argument("--build", type=str, 1657 help=("Build directory for USD and 3rd-party dependencies " 1658 "(default: <install_dir>/build)")) 1659 1660BUILD_DEBUG = "debug" 1661BUILD_RELEASE = "release" 1662BUILD_RELWITHDEBUG = "relwithdebuginfo" 1663group.add_argument("--build-variant", default=BUILD_RELEASE, 1664 choices=[BUILD_DEBUG, BUILD_RELEASE, BUILD_RELWITHDEBUG], 1665 help=("Build variant for USD and 3rd-party dependencies. " 1666 "(default: {})".format(BUILD_RELEASE))) 1667 1668group.add_argument("--build-args", type=str, nargs="*", default=[], 1669 help=("Custom arguments to pass to build system when " 1670 "building libraries (see docs above)")) 1671group.add_argument("--build-python-info", type=str, nargs=4, default=[], 1672 metavar=('PYTHON_EXECUTABLE', 'PYTHON_INCLUDE_DIR', 'PYTHON_LIBRARY', 'PYTHON_VERSION'), 1673 help=("Specify a custom python to use during build")) 1674group.add_argument("--force", type=str, action="append", dest="force_build", 1675 default=[], 1676 help=("Force download and build of specified library " 1677 "(see docs above)")) 1678group.add_argument("--force-all", action="store_true", 1679 help="Force download and build of all libraries") 1680group.add_argument("--generator", type=str, 1681 help=("CMake generator to use when building libraries with " 1682 "cmake")) 1683group.add_argument("--toolset", type=str, 1684 help=("CMake toolset to use when building libraries with " 1685 "cmake")) 1686 1687if Linux(): 1688 group.add_argument("--use-cxx11-abi", type=int, choices=[0, 1], 1689 help=("Use C++11 ABI for libstdc++. (see docs above)")) 1690 1691group = parser.add_argument_group(title="3rd Party Dependency Build Options") 1692group.add_argument("--src", type=str, 1693 help=("Directory where dependencies will be downloaded " 1694 "(default: <install_dir>/src)")) 1695group.add_argument("--inst", type=str, 1696 help=("Directory where dependencies will be installed " 1697 "(default: <install_dir>)")) 1698 1699group = parser.add_argument_group(title="USD Options") 1700 1701(SHARED_LIBS, MONOLITHIC_LIB) = (0, 1) 1702subgroup = group.add_mutually_exclusive_group() 1703subgroup.add_argument("--build-shared", dest="build_type", 1704 action="store_const", const=SHARED_LIBS, 1705 default=SHARED_LIBS, 1706 help="Build individual shared libraries (default)") 1707subgroup.add_argument("--build-monolithic", dest="build_type", 1708 action="store_const", const=MONOLITHIC_LIB, 1709 help="Build a single monolithic shared library") 1710 1711subgroup = group.add_mutually_exclusive_group() 1712subgroup.add_argument("--tests", dest="build_tests", action="store_true", 1713 default=False, help="Build unit tests") 1714subgroup.add_argument("--no-tests", dest="build_tests", action="store_false", 1715 help="Do not build unit tests (default)") 1716subgroup = group.add_mutually_exclusive_group() 1717subgroup.add_argument("--examples", dest="build_examples", action="store_true", 1718 default=True, help="Build examples (default)") 1719subgroup.add_argument("--no-examples", dest="build_examples", action="store_false", 1720 help="Do not build examples") 1721subgroup = group.add_mutually_exclusive_group() 1722subgroup.add_argument("--tutorials", dest="build_tutorials", action="store_true", 1723 default=True, help="Build tutorials (default)") 1724subgroup.add_argument("--no-tutorials", dest="build_tutorials", action="store_false", 1725 help="Do not build tutorials") 1726subgroup = group.add_mutually_exclusive_group() 1727subgroup.add_argument("--tools", dest="build_tools", action="store_true", 1728 default=True, help="Build USD tools (default)") 1729subgroup.add_argument("--no-tools", dest="build_tools", action="store_false", 1730 help="Do not build USD tools") 1731subgroup = group.add_mutually_exclusive_group() 1732subgroup.add_argument("--docs", dest="build_docs", action="store_true", 1733 default=False, help="Build documentation") 1734subgroup.add_argument("--no-docs", dest="build_docs", action="store_false", 1735 help="Do not build documentation (default)") 1736subgroup = group.add_mutually_exclusive_group() 1737subgroup.add_argument("--python", dest="build_python", action="store_true", 1738 default=True, help="Build python based components " 1739 "(default)") 1740subgroup.add_argument("--no-python", dest="build_python", action="store_false", 1741 help="Do not build python based components") 1742subgroup = group.add_mutually_exclusive_group() 1743subgroup.add_argument("--prefer-safety-over-speed", dest="safety_first", 1744 action="store_true", default=True, help= 1745 "Enable extra safety checks (which may negatively " 1746 "impact performance) against malformed input files " 1747 "(default)") 1748subgroup.add_argument("--prefer-speed-over-safety", dest="safety_first", 1749 action="store_false", help= 1750 "Disable performance-impacting safety checks against " 1751 "malformed input files") 1752 1753subgroup = group.add_mutually_exclusive_group() 1754subgroup.add_argument("--debug-python", dest="debug_python", action="store_true", 1755 help="Define Boost Python Debug if your Python library comes with Debugging symbols.") 1756 1757subgroup.add_argument("--no-debug-python", dest="debug_python", action="store_false", 1758 help="Don't define Boost Python Debug if your Python library comes with Debugging symbols.") 1759 1760(NO_IMAGING, IMAGING, USD_IMAGING) = (0, 1, 2) 1761 1762group = parser.add_argument_group(title="Imaging and USD Imaging Options") 1763subgroup = group.add_mutually_exclusive_group() 1764subgroup.add_argument("--imaging", dest="build_imaging", 1765 action="store_const", const=IMAGING, default=USD_IMAGING, 1766 help="Build imaging component") 1767subgroup.add_argument("--usd-imaging", dest="build_imaging", 1768 action="store_const", const=USD_IMAGING, 1769 help="Build imaging and USD imaging components (default)") 1770subgroup.add_argument("--no-imaging", dest="build_imaging", 1771 action="store_const", const=NO_IMAGING, 1772 help="Do not build imaging or USD imaging components") 1773subgroup = group.add_mutually_exclusive_group() 1774subgroup.add_argument("--ptex", dest="enable_ptex", action="store_true", 1775 default=False, 1776 help="Enable Ptex support in imaging") 1777subgroup.add_argument("--no-ptex", dest="enable_ptex", 1778 action="store_false", 1779 help="Disable Ptex support in imaging (default)") 1780subgroup = group.add_mutually_exclusive_group() 1781subgroup.add_argument("--openvdb", dest="enable_openvdb", action="store_true", 1782 default=False, 1783 help="Enable OpenVDB support in imaging") 1784subgroup.add_argument("--no-openvdb", dest="enable_openvdb", 1785 action="store_false", 1786 help="Disable OpenVDB support in imaging (default)") 1787subgroup = group.add_mutually_exclusive_group() 1788subgroup.add_argument("--usdview", dest="build_usdview", 1789 action="store_true", default=True, 1790 help="Build usdview (default)") 1791subgroup.add_argument("--no-usdview", dest="build_usdview", 1792 action="store_false", 1793 help="Do not build usdview") 1794 1795group = parser.add_argument_group(title="Imaging Plugin Options") 1796subgroup = group.add_mutually_exclusive_group() 1797subgroup.add_argument("--embree", dest="build_embree", action="store_true", 1798 default=False, 1799 help="Build Embree sample imaging plugin") 1800subgroup.add_argument("--no-embree", dest="build_embree", action="store_false", 1801 help="Do not build Embree sample imaging plugin (default)") 1802subgroup = group.add_mutually_exclusive_group() 1803subgroup.add_argument("--prman", dest="build_prman", action="store_true", 1804 default=False, 1805 help="Build Pixar's RenderMan imaging plugin") 1806subgroup.add_argument("--no-prman", dest="build_prman", action="store_false", 1807 help="Do not build Pixar's RenderMan imaging plugin (default)") 1808group.add_argument("--prman-location", type=str, 1809 help="Directory where Pixar's RenderMan is installed.") 1810subgroup = group.add_mutually_exclusive_group() 1811subgroup.add_argument("--openimageio", dest="build_oiio", action="store_true", 1812 default=False, 1813 help="Build OpenImageIO plugin for USD") 1814subgroup.add_argument("--no-openimageio", dest="build_oiio", action="store_false", 1815 help="Do not build OpenImageIO plugin for USD (default)") 1816subgroup = group.add_mutually_exclusive_group() 1817subgroup.add_argument("--opencolorio", dest="build_ocio", action="store_true", 1818 default=False, 1819 help="Build OpenColorIO plugin for USD") 1820subgroup.add_argument("--no-opencolorio", dest="build_ocio", action="store_false", 1821 help="Do not build OpenColorIO plugin for USD (default)") 1822 1823group = parser.add_argument_group(title="Alembic Plugin Options") 1824subgroup = group.add_mutually_exclusive_group() 1825subgroup.add_argument("--alembic", dest="build_alembic", action="store_true", 1826 default=False, 1827 help="Build Alembic plugin for USD") 1828subgroup.add_argument("--no-alembic", dest="build_alembic", action="store_false", 1829 help="Do not build Alembic plugin for USD (default)") 1830subgroup = group.add_mutually_exclusive_group() 1831subgroup.add_argument("--hdf5", dest="enable_hdf5", action="store_true", 1832 default=False, 1833 help="Enable HDF5 support in the Alembic plugin") 1834subgroup.add_argument("--no-hdf5", dest="enable_hdf5", action="store_false", 1835 help="Disable HDF5 support in the Alembic plugin (default)") 1836 1837group = parser.add_argument_group(title="Draco Plugin Options") 1838subgroup = group.add_mutually_exclusive_group() 1839subgroup.add_argument("--draco", dest="build_draco", action="store_true", 1840 default=False, 1841 help="Build Draco plugin for USD") 1842subgroup.add_argument("--no-draco", dest="build_draco", action="store_false", 1843 help="Do not build Draco plugin for USD (default)") 1844group.add_argument("--draco-location", type=str, 1845 help="Directory where Draco is installed.") 1846 1847group = parser.add_argument_group(title="MaterialX Plugin Options") 1848subgroup = group.add_mutually_exclusive_group() 1849subgroup.add_argument("--materialx", dest="build_materialx", action="store_true", 1850 default=False, 1851 help="Build MaterialX plugin for USD") 1852subgroup.add_argument("--no-materialx", dest="build_materialx", action="store_false", 1853 help="Do not build MaterialX plugin for USD (default)") 1854 1855args = parser.parse_args() 1856 1857class InstallContext: 1858 def __init__(self, args): 1859 # Assume the USD source directory is in the parent directory 1860 self.usdSrcDir = os.path.normpath( 1861 os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) 1862 1863 # Directory where USD will be installed 1864 self.usdInstDir = os.path.abspath(args.install_dir) 1865 1866 # Directory where dependencies will be installed 1867 self.instDir = (os.path.abspath(args.inst) if args.inst 1868 else self.usdInstDir) 1869 1870 # Directory where dependencies will be downloaded and extracted 1871 self.srcDir = (os.path.abspath(args.src) if args.src 1872 else os.path.join(self.usdInstDir, "src")) 1873 1874 # Directory where USD and dependencies will be built 1875 self.buildDir = (os.path.abspath(args.build) if args.build 1876 else os.path.join(self.usdInstDir, "build")) 1877 1878 # Determine which downloader to use. The reason we don't simply 1879 # use urllib2 all the time is that some older versions of Python 1880 # don't support TLS v1.2, which is required for downloading some 1881 # dependencies. 1882 if which("curl"): 1883 self.downloader = DownloadFileWithCurl 1884 self.downloaderName = "curl" 1885 elif Windows() and which("powershell"): 1886 self.downloader = DownloadFileWithPowershell 1887 self.downloaderName = "powershell" 1888 else: 1889 self.downloader = DownloadFileWithUrllib 1890 self.downloaderName = "built-in" 1891 1892 # CMake generator and toolset 1893 self.cmakeGenerator = args.generator 1894 self.cmakeToolset = args.toolset 1895 1896 # Number of jobs 1897 self.numJobs = args.jobs 1898 if self.numJobs <= 0: 1899 raise ValueError("Number of jobs must be greater than 0") 1900 1901 # Build arguments 1902 self.buildArgs = dict() 1903 for a in args.build_args: 1904 (depName, _, arg) = a.partition(",") 1905 if not depName or not arg: 1906 raise ValueError("Invalid argument for --build-args: {}" 1907 .format(a)) 1908 if depName.lower() not in AllDependenciesByName: 1909 raise ValueError("Invalid library for --build-args: {}" 1910 .format(depName)) 1911 1912 self.buildArgs.setdefault(depName.lower(), []).append(arg) 1913 1914 # Build python info 1915 self.build_python_info = dict() 1916 if args.build_python_info: 1917 self.build_python_info['PYTHON_EXECUTABLE'] = args.build_python_info[0] 1918 self.build_python_info['PYTHON_INCLUDE_DIR'] = args.build_python_info[1] 1919 self.build_python_info['PYTHON_LIBRARY'] = args.build_python_info[2] 1920 self.build_python_info['PYTHON_VERSION'] = args.build_python_info[3] 1921 1922 # Build type 1923 self.buildDebug = (args.build_variant == BUILD_DEBUG) 1924 self.buildRelease = (args.build_variant == BUILD_RELEASE) 1925 self.buildRelWithDebug = (args.build_variant == BUILD_RELWITHDEBUG) 1926 1927 self.debugPython = args.debug_python 1928 1929 self.buildShared = (args.build_type == SHARED_LIBS) 1930 self.buildMonolithic = (args.build_type == MONOLITHIC_LIB) 1931 1932 # Build options 1933 self.useCXX11ABI = \ 1934 (args.use_cxx11_abi if hasattr(args, "use_cxx11_abi") else None) 1935 self.safetyFirst = args.safety_first 1936 1937 # Dependencies that are forced to be built 1938 self.forceBuildAll = args.force_all 1939 self.forceBuild = [dep.lower() for dep in args.force_build] 1940 1941 # Optional components 1942 self.buildTests = args.build_tests 1943 self.buildDocs = args.build_docs 1944 self.buildPython = args.build_python 1945 self.buildExamples = args.build_examples 1946 self.buildTutorials = args.build_tutorials 1947 self.buildTools = args.build_tools 1948 1949 # - Imaging 1950 self.buildImaging = (args.build_imaging == IMAGING or 1951 args.build_imaging == USD_IMAGING) 1952 self.enablePtex = self.buildImaging and args.enable_ptex 1953 self.enableOpenVDB = self.buildImaging and args.enable_openvdb 1954 1955 # - USD Imaging 1956 self.buildUsdImaging = (args.build_imaging == USD_IMAGING) 1957 1958 # - usdview 1959 self.buildUsdview = (self.buildUsdImaging and 1960 self.buildPython and 1961 args.build_usdview) 1962 1963 # - Imaging plugins 1964 self.buildEmbree = self.buildImaging and args.build_embree 1965 self.buildPrman = self.buildImaging and args.build_prman 1966 self.prmanLocation = (os.path.abspath(args.prman_location) 1967 if args.prman_location else None) 1968 self.buildOIIO = args.build_oiio 1969 self.buildOCIO = args.build_ocio 1970 1971 # - Alembic Plugin 1972 self.buildAlembic = args.build_alembic 1973 self.enableHDF5 = self.buildAlembic and args.enable_hdf5 1974 1975 # - Draco Plugin 1976 self.buildDraco = args.build_draco 1977 self.dracoLocation = (os.path.abspath(args.draco_location) 1978 if args.draco_location else None) 1979 1980 # - MaterialX Plugin 1981 self.buildMaterialX = args.build_materialx 1982 1983 def GetBuildArguments(self, dep): 1984 return self.buildArgs.get(dep.name.lower(), []) 1985 1986 def ForceBuildDependency(self, dep): 1987 # Never force building a Python dependency, since users are required 1988 # to build these dependencies themselves. 1989 if type(dep) is PythonDependency: 1990 return False 1991 return self.forceBuildAll or dep.name.lower() in self.forceBuild 1992 1993try: 1994 context = InstallContext(args) 1995except Exception as e: 1996 PrintError(str(e)) 1997 sys.exit(1) 1998 1999verbosity = args.verbosity 2000 2001# Augment PATH on Windows so that 3rd-party dependencies can find libraries 2002# they depend on. In particular, this is needed for building IlmBase/OpenEXR. 2003extraPaths = [] 2004extraPythonPaths = [] 2005if Windows(): 2006 extraPaths.append(os.path.join(context.instDir, "lib")) 2007 extraPaths.append(os.path.join(context.instDir, "bin")) 2008 2009if extraPaths: 2010 paths = os.environ.get('PATH', '').split(os.pathsep) + extraPaths 2011 os.environ['PATH'] = os.pathsep.join(paths) 2012 2013if extraPythonPaths: 2014 paths = os.environ.get('PYTHONPATH', '').split(os.pathsep) + extraPythonPaths 2015 os.environ['PYTHONPATH'] = os.pathsep.join(paths) 2016 2017# Determine list of dependencies that are required based on options 2018# user has selected. 2019requiredDependencies = [ZLIB, BOOST, TBB] 2020 2021if context.buildAlembic: 2022 if context.enableHDF5: 2023 requiredDependencies += [HDF5] 2024 requiredDependencies += [OPENEXR, ALEMBIC] 2025 2026if context.buildDraco: 2027 requiredDependencies += [DRACO] 2028 2029if context.buildMaterialX: 2030 requiredDependencies += [MATERIALX] 2031 2032if context.buildImaging: 2033 if context.enablePtex: 2034 requiredDependencies += [PTEX] 2035 2036 requiredDependencies += [OPENSUBDIV] 2037 2038 if context.enableOpenVDB: 2039 requiredDependencies += [BLOSC, BOOST, OPENEXR, OPENVDB, TBB] 2040 2041 if context.buildOIIO: 2042 requiredDependencies += [BOOST, JPEG, TIFF, PNG, OPENEXR, OPENIMAGEIO] 2043 2044 if context.buildOCIO: 2045 requiredDependencies += [OPENCOLORIO] 2046 2047 if context.buildEmbree: 2048 requiredDependencies += [TBB, EMBREE] 2049 2050if context.buildUsdview: 2051 requiredDependencies += [PYOPENGL, PYSIDE] 2052 2053# Assume zlib already exists on Linux platforms and don't build 2054# our own. This avoids potential issues where a host application 2055# loads an older version of zlib than the one we'd build and link 2056# our libraries against. 2057if Linux(): 2058 requiredDependencies.remove(ZLIB) 2059 2060# Error out if user is building monolithic library on windows with draco plugin 2061# enabled. This currently results in missing symbols. 2062if context.buildDraco and context.buildMonolithic and Windows(): 2063 PrintError("Draco plugin can not be enabled for monolithic build on Windows") 2064 sys.exit(1) 2065 2066# Error out if user explicitly specified building usdview without required 2067# components. Otherwise, usdview will be silently disabled. This lets users 2068# specify "--no-python" without explicitly having to specify "--no-usdview", 2069# for instance. 2070if "--usdview" in sys.argv: 2071 if not context.buildUsdImaging: 2072 PrintError("Cannot build usdview when usdImaging is disabled.") 2073 sys.exit(1) 2074 if not context.buildPython: 2075 PrintError("Cannot build usdview when Python support is disabled.") 2076 sys.exit(1) 2077 2078dependenciesToBuild = [] 2079for dep in requiredDependencies: 2080 if context.ForceBuildDependency(dep) or not dep.Exists(context): 2081 if dep not in dependenciesToBuild: 2082 dependenciesToBuild.append(dep) 2083 2084# Verify toolchain needed to build required dependencies 2085if (not which("g++") and 2086 not which("clang") and 2087 not GetXcodeDeveloperDirectory() and 2088 not GetVisualStudioCompilerAndVersion()): 2089 PrintError("C++ compiler not found -- please install a compiler") 2090 sys.exit(1) 2091 2092# Error out if a 64bit version of python interpreter is not being used 2093isPython64Bit = (ctypes.sizeof(ctypes.c_voidp) == 8) 2094if not isPython64Bit: 2095 PrintError("64bit python not found -- please install it and adjust your" 2096 "PATH") 2097 sys.exit(1) 2098 2099if which("cmake"): 2100 # Check cmake requirements 2101 if Windows(): 2102 # Windows build depend on boost 1.70, which is not supported before 2103 # cmake version 3.14 2104 cmake_required_version = (3, 14) 2105 else: 2106 cmake_required_version = (3, 12) 2107 cmake_version = GetCMakeVersion() 2108 if not cmake_version: 2109 PrintError("Failed to determine CMake version") 2110 sys.exit(1) 2111 2112 if cmake_version < cmake_required_version: 2113 def _JoinVersion(v): 2114 return ".".join(str(n) for n in v) 2115 PrintError("CMake version {req} or later required to build USD, " 2116 "but version found was {found}".format( 2117 req=_JoinVersion(cmake_required_version), 2118 found=_JoinVersion(cmake_version))) 2119 sys.exit(1) 2120else: 2121 PrintError("CMake not found -- please install it and adjust your PATH") 2122 sys.exit(1) 2123 2124if context.buildDocs: 2125 if not which("doxygen"): 2126 PrintError("doxygen not found -- please install it and adjust your PATH") 2127 sys.exit(1) 2128 2129 if not which("dot"): 2130 PrintError("dot not found -- please install graphviz and adjust your " 2131 "PATH") 2132 sys.exit(1) 2133 2134if PYSIDE in requiredDependencies: 2135 # Special case - we are given the PYSIDEUICBINARY as cmake arg. 2136 usdBuildArgs = context.GetBuildArguments(USD) 2137 given_pysideUic = 'PYSIDEUICBINARY' in " ".join(usdBuildArgs) 2138 2139 # The USD build will skip building usdview if pyside2-uic or pyside-uic is 2140 # not found, so check for it here to avoid confusing users. This list of 2141 # PySide executable names comes from cmake/modules/FindPySide.cmake 2142 pyside2Uic = ["pyside2-uic", "python2-pyside2-uic", "pyside2-uic-2.7", "uic"] 2143 found_pyside2Uic = any([which(p) for p in pyside2Uic]) 2144 pysideUic = ["pyside-uic", "python2-pyside-uic", "pyside-uic-2.7"] 2145 found_pysideUic = any([which(p) for p in pysideUic]) 2146 if not given_pysideUic and not found_pyside2Uic and not found_pysideUic: 2147 if Windows(): 2148 # Windows does not support PySide2 with Python2.7 2149 PrintError("pyside-uic not found -- please install PySide and" 2150 " adjust your PATH. (Note that this program may be named" 2151 " {0} depending on your platform)" 2152 .format(" or ".join(pysideUic))) 2153 else: 2154 PrintError("pyside2-uic not found -- please install PySide2 and" 2155 " adjust your PATH. (Note that this program may be" 2156 " named {0} depending on your platform)" 2157 .format(" or ".join(pyside2Uic))) 2158 sys.exit(1) 2159 2160if JPEG in requiredDependencies: 2161 # NASM is required to build libjpeg-turbo 2162 if (Windows() and not which("nasm")): 2163 PrintError("nasm not found -- please install it and adjust your PATH") 2164 sys.exit(1) 2165 2166# Summarize 2167summaryMsg = """ 2168Building with settings: 2169 USD source directory {usdSrcDir} 2170 USD install directory {usdInstDir} 2171 3rd-party source directory {srcDir} 2172 3rd-party install directory {instDir} 2173 Build directory {buildDir} 2174 CMake generator {cmakeGenerator} 2175 CMake toolset {cmakeToolset} 2176 Downloader {downloader} 2177 2178 Building {buildType} 2179""" 2180 2181if context.useCXX11ABI is not None: 2182 summaryMsg += """\ 2183 Use C++11 ABI {useCXX11ABI} 2184""" 2185 2186summaryMsg += """\ 2187 Variant {buildVariant} 2188 Imaging {buildImaging} 2189 Ptex support: {enablePtex} 2190 OpenVDB support: {enableOpenVDB} 2191 OpenImageIO support: {buildOIIO} 2192 OpenColorIO support: {buildOCIO} 2193 PRMan support: {buildPrman} 2194 UsdImaging {buildUsdImaging} 2195 usdview: {buildUsdview} 2196 Python support {buildPython} 2197 Python Debug: {debugPython} 2198 Python 3: {enablePython3} 2199 Documentation {buildDocs} 2200 Tests {buildTests} 2201 Examples {buildExamples} 2202 Tutorials {buildTutorials} 2203 Tools {buildTools} 2204 Alembic Plugin {buildAlembic} 2205 HDF5 support: {enableHDF5} 2206 Draco Plugin {buildDraco} 2207 MaterialX Plugin {buildMaterialX} 2208 2209 Dependencies {dependencies}""" 2210 2211if context.buildArgs: 2212 summaryMsg += """ 2213 Build arguments {buildArgs}""" 2214 2215def FormatBuildArguments(buildArgs): 2216 s = "" 2217 for depName in sorted(buildArgs.keys()): 2218 args = buildArgs[depName] 2219 s += """ 2220 {name}: {args}""".format( 2221 name=AllDependenciesByName[depName].name, 2222 args=" ".join(args)) 2223 return s.lstrip() 2224 2225summaryMsg = summaryMsg.format( 2226 usdSrcDir=context.usdSrcDir, 2227 usdInstDir=context.usdInstDir, 2228 srcDir=context.srcDir, 2229 buildDir=context.buildDir, 2230 instDir=context.instDir, 2231 cmakeGenerator=("Default" if not context.cmakeGenerator 2232 else context.cmakeGenerator), 2233 cmakeToolset=("Default" if not context.cmakeToolset 2234 else context.cmakeToolset), 2235 downloader=(context.downloaderName), 2236 dependencies=("None" if not dependenciesToBuild else 2237 ", ".join([d.name for d in dependenciesToBuild])), 2238 buildArgs=FormatBuildArguments(context.buildArgs), 2239 useCXX11ABI=("On" if context.useCXX11ABI else "Off"), 2240 buildType=("Shared libraries" if context.buildShared 2241 else "Monolithic shared library" if context.buildMonolithic 2242 else ""), 2243 buildVariant=("Release" if context.buildRelease 2244 else "Debug" if context.buildDebug 2245 else "Release w/ Debug Info" if context.buildRelWithDebug 2246 else ""), 2247 buildImaging=("On" if context.buildImaging else "Off"), 2248 enablePtex=("On" if context.enablePtex else "Off"), 2249 enableOpenVDB=("On" if context.enableOpenVDB else "Off"), 2250 buildOIIO=("On" if context.buildOIIO else "Off"), 2251 buildOCIO=("On" if context.buildOCIO else "Off"), 2252 buildPrman=("On" if context.buildPrman else "Off"), 2253 buildUsdImaging=("On" if context.buildUsdImaging else "Off"), 2254 buildUsdview=("On" if context.buildUsdview else "Off"), 2255 buildPython=("On" if context.buildPython else "Off"), 2256 debugPython=("On" if context.debugPython else "Off"), 2257 enablePython3=("On" if Python3() else "Off"), 2258 buildDocs=("On" if context.buildDocs else "Off"), 2259 buildTests=("On" if context.buildTests else "Off"), 2260 buildExamples=("On" if context.buildExamples else "Off"), 2261 buildTutorials=("On" if context.buildTutorials else "Off"), 2262 buildTools=("On" if context.buildTools else "Off"), 2263 buildAlembic=("On" if context.buildAlembic else "Off"), 2264 buildDraco=("On" if context.buildDraco else "Off"), 2265 buildMaterialX=("On" if context.buildMaterialX else "Off"), 2266 enableHDF5=("On" if context.enableHDF5 else "Off")) 2267 2268Print(summaryMsg) 2269 2270if args.dry_run: 2271 sys.exit(0) 2272 2273# Scan for any dependencies that the user is required to install themselves 2274# and print those instructions first. 2275pythonDependencies = \ 2276 [dep for dep in dependenciesToBuild if type(dep) is PythonDependency] 2277if pythonDependencies: 2278 for dep in pythonDependencies: 2279 Print(dep.getInstructions()) 2280 sys.exit(1) 2281 2282# Ensure directory structure is created and is writable. 2283for dir in [context.usdInstDir, context.instDir, context.srcDir, 2284 context.buildDir]: 2285 try: 2286 if os.path.isdir(dir): 2287 testFile = os.path.join(dir, "canwrite") 2288 open(testFile, "w").close() 2289 os.remove(testFile) 2290 else: 2291 os.makedirs(dir) 2292 except Exception as e: 2293 PrintError("Could not write to directory {dir}. Change permissions " 2294 "or choose a different location to install to." 2295 .format(dir=dir)) 2296 sys.exit(1) 2297 2298try: 2299 # Download and install 3rd-party dependencies, followed by USD. 2300 for dep in dependenciesToBuild + [USD]: 2301 PrintStatus("Installing {dep}...".format(dep=dep.name)) 2302 dep.installer(context, 2303 buildArgs=context.GetBuildArguments(dep), 2304 force=context.ForceBuildDependency(dep)) 2305except Exception as e: 2306 PrintError(str(e)) 2307 sys.exit(1) 2308 2309# Done. Print out a final status message. 2310requiredInPythonPath = set([ 2311 os.path.join(context.usdInstDir, "lib", "python") 2312]) 2313requiredInPythonPath.update(extraPythonPaths) 2314 2315requiredInPath = set([ 2316 os.path.join(context.usdInstDir, "bin") 2317]) 2318requiredInPath.update(extraPaths) 2319 2320if Windows(): 2321 requiredInPath.update([ 2322 os.path.join(context.usdInstDir, "lib"), 2323 os.path.join(context.instDir, "bin"), 2324 os.path.join(context.instDir, "lib") 2325 ]) 2326 2327Print(""" 2328Success! To use USD, please ensure that you have:""") 2329 2330if context.buildPython: 2331 Print(""" 2332 The following in your PYTHONPATH environment variable: 2333 {requiredInPythonPath}""".format( 2334 requiredInPythonPath="\n ".join(sorted(requiredInPythonPath)))) 2335 2336Print(""" 2337 The following in your PATH environment variable: 2338 {requiredInPath} 2339""".format(requiredInPath="\n ".join(sorted(requiredInPath)))) 2340 2341if context.buildPrman: 2342 Print("See documentation at http://openusd.org/docs/RenderMan-USD-Imaging-Plugin.html " 2343 "for setting up the RenderMan plugin.\n") 2344