diff --git a/.gitignore b/.gitignore index d9b9949816..b56ea57456 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ .DS_Store .AppleDouble USD_emscripten/ +build .vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c2601235e..e70471b9a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(usd) -if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT PXR_ENABLE_JS_SUPPORT) +if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT EMSCRIPTEN) if (WIN32) message(FATAL_ERROR "Compiler does not support 64-bit builds. " "If you are using Visual Studio, make sure you are in the " @@ -39,7 +39,7 @@ set(CMAKE_CXX_FLAGS "${_PXR_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") if(PXR_ENABLE_JS_SUPPORT) # Add EMSCRIPTEN specific compiler flags (is this the right place)? - set(EMSCRIPTEN_COMPILE_FLAGS "-s ALLOW_MEMORY_GROWTH=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -s MODULARIZE=1 -s EXPORT_NAME='getUsdModule' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"FS\"]' -s FORCE_FILESYSTEM=1") + set(EMSCRIPTEN_COMPILE_FLAGS "-s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s ASSERTIONS=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -s MODULARIZE=1 -s EXPORT_NAME='getUsdModule' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"FS\"]' -s FORCE_FILESYSTEM=1 --pre-js ${CMAKE_SOURCE_DIR}/js/prejs.js") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EMSCRIPTEN_COMPILE_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EMSCRIPTEN_COMPILE_FLAGS}") diff --git a/build_scripts/build_usd.py b/build_scripts/build_usd.py index 280241aa13..bb983f5ca2 100644 --- a/build_scripts/build_usd.py +++ b/build_scripts/build_usd.py @@ -1,2438 +1,2460 @@ -# -# Copyright 2017 Pixar -# -# Licensed under the Apache License, Version 2.0 (the "Apache License") -# with the following modification; you may not use this file except in -# compliance with the Apache License and the following modification to it: -# Section 6. Trademarks. is deleted and replaced with: -# -# 6. Trademarks. This License does not grant permission to use the trade -# names, trademarks, service marks, or product names of the Licensor -# and its affiliates, except as required to comply with Section 4(c) of -# the License and to reproduce the content of the NOTICE file. -# -# You may obtain a copy of the Apache License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the Apache License with the above modification is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the Apache License for the specific -# language governing permissions and limitations under the Apache License. -# -from __future__ import print_function - -import argparse -import codecs -import contextlib -import ctypes -import datetime -import distutils -import fnmatch -import glob -import locale -import multiprocessing -import os -import platform -import re -import shlex -import shutil -import subprocess -import sys -import sysconfig -import tarfile -import zipfile - -if sys.version_info.major >= 3: - from urllib.request import urlopen - from shutil import which -else: - from urllib2 import urlopen - - # Doesn't deal with .bat / .cmd like shutil.which, but only option - # available with stock python-2 - from distutils.spawn import find_executable as which - -# Helpers for printing output -verbosity = 1 - -def Print(msg): - if verbosity > 0: - print(msg) - -def PrintWarning(warning): - if verbosity > 0: - print("WARNING:", warning) - -def PrintStatus(status): - if verbosity >= 1: - print("STATUS:", status) - -def PrintInfo(info): - if verbosity >= 2: - print("INFO:", info) - -def PrintCommandOutput(output): - if verbosity >= 3: - sys.stdout.write(output) - -def PrintError(error): - if verbosity >= 3 and sys.exc_info()[1] is not None: - import traceback - traceback.print_exc() - print ("ERROR:", error) - -# Helpers for determining platform -def Windows(): - return platform.system() == "Windows" -def Linux(): - return platform.system() == "Linux" -def MacOS(): - return platform.system() == "Darwin" - -def Python3(): - return sys.version_info.major == 3 - -def GetLocale(): - return sys.stdout.encoding or locale.getdefaultlocale()[1] or "UTF-8" - -def GetCommandOutput(command): - """Executes the specified command and returns output or None.""" - try: - return subprocess.check_output( - shlex.split(command), - stderr=subprocess.STDOUT).decode(GetLocale(), 'replace').strip() - except subprocess.CalledProcessError: - pass - return None - -def GetXcodeDeveloperDirectory(): - """Returns the active developer directory as reported by 'xcode-select -p'. - Returns None if none is set.""" - if not MacOS(): - return None - - return GetCommandOutput("xcode-select -p") - -def GetVisualStudioCompilerAndVersion(): - """Returns a tuple containing the path to the Visual Studio compiler - and a tuple for its version, e.g. (14, 0). If the compiler is not found - or version number cannot be determined, returns None.""" - if not Windows(): - return None - - msvcCompiler = which('cl') - if msvcCompiler: - # VisualStudioVersion environment variable should be set by the - # Visual Studio Command Prompt. - match = re.search( - r"(\d+)\.(\d+)", - os.environ.get("VisualStudioVersion", "")) - if match: - return (msvcCompiler, tuple(int(v) for v in match.groups())) - return None - -def IsVisualStudioVersionOrGreater(desiredVersion): - if not Windows(): - return False - - msvcCompilerAndVersion = GetVisualStudioCompilerAndVersion() - if msvcCompilerAndVersion: - _, version = msvcCompilerAndVersion - return version >= desiredVersion - return False - -def IsVisualStudio2019OrGreater(): - VISUAL_STUDIO_2019_VERSION = (16, 0) - return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2019_VERSION) - -def IsVisualStudio2017OrGreater(): - VISUAL_STUDIO_2017_VERSION = (15, 0) - return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2017_VERSION) - -def IsVisualStudio2015OrGreater(): - VISUAL_STUDIO_2015_VERSION = (14, 0) - return IsVisualStudioVersionOrGreater(VISUAL_STUDIO_2015_VERSION) - -def IsMayaPython(): - """Determine whether we're running in Maya's version of Python. When - building against Maya's Python, there are some additional restrictions - on what we're able to build.""" - try: - import maya - return True - except: - pass - - return False - -def GetPythonInfo(context): - """Returns a tuple containing the path to the Python executable, shared - library, and include directory corresponding to the version of Python - currently running. Returns None if any path could not be determined. - - This function is used to extract build information from the Python - interpreter used to launch this script. This information is used - in the Boost and USD builds. By taking this approach we can support - having USD builds for different Python versions built on the same - machine. This is very useful, especially when developers have multiple - versions installed on their machine, which is quite common now with - Python2 and Python3 co-existing. - """ - - # If we were given build python info then just use it. - if context.build_python_info: - return (context.build_python_info['PYTHON_EXECUTABLE'], - context.build_python_info['PYTHON_LIBRARY'], - context.build_python_info['PYTHON_INCLUDE_DIR'], - context.build_python_info['PYTHON_VERSION']) - - # First we extract the information that can be uniformly dealt with across - # the platforms: - pythonExecPath = sys.executable - pythonVersion = sysconfig.get_config_var("py_version_short") # "2.7" - pythonVersionNoDot = sysconfig.get_config_var("py_version_nodot") # "27" - - # Lib path is unfortunately special for each platform and there is no - # config_var for it. But we can deduce it for each platform, and this - # logic works for any Python version. - def _GetPythonLibraryFilename(context): - if Windows(): - suffix = '_d' if context.buildDebug and context.debugPython else '' - return "python" + pythonVersionNoDot + suffix + ".lib" - elif Linux(): - return sysconfig.get_config_var("LDLIBRARY") - elif MacOS(): - return "libpython" + pythonVersion + ".dylib" - else: - raise RuntimeError("Platform not supported") - - # XXX: Handle the case where this script is being called using Maya's - # Python since the sysconfig variables are set up differently in Maya. - # Ideally we would not have any special Maya knowledge in here at all. - if IsMayaPython(): - pythonBaseDir = sysconfig.get_config_var("base") - - # On Windows, the "base" path points to a "Python\" subdirectory - # that contains the DLLs for site-package modules but not the - # directories for the headers and .lib file we need -- those - # are one level up. - if Windows(): - pythonBaseDir = os.path.dirname(pythonBaseDir) - - pythonIncludeDir = os.path.join(pythonBaseDir, "include", - "python" + pythonVersion) - pythonLibPath = os.path.join(pythonBaseDir, "lib", - _GetPythonLibraryFilename(context)) - else: - pythonIncludeDir = sysconfig.get_config_var("INCLUDEPY") - if Windows(): - pythonBaseDir = sysconfig.get_config_var("base") - pythonLibPath = os.path.join(pythonBaseDir, "libs", - _GetPythonLibraryFilename(context)) - elif Linux(): - pythonLibDir = sysconfig.get_config_var("LIBDIR") - pythonMultiarchSubdir = sysconfig.get_config_var("multiarchsubdir") - if pythonMultiarchSubdir: - pythonLibDir = pythonLibDir + pythonMultiarchSubdir - pythonLibPath = os.path.join(pythonLibDir, - _GetPythonLibraryFilename(context)) - elif MacOS(): - pythonBaseDir = sysconfig.get_config_var("base") - pythonLibPath = os.path.join(pythonBaseDir, "lib", - _GetPythonLibraryFilename(context)) - else: - raise RuntimeError("Platform not supported") - - return (pythonExecPath, pythonLibPath, pythonIncludeDir, pythonVersion) - -def GetCPUCount(): - try: - return multiprocessing.cpu_count() - except NotImplementedError: - return 1 - -def Run(cmd, logCommandOutput = True): - """Run the specified command in a subprocess.""" - PrintInfo('Running "{cmd}"'.format(cmd=cmd)) - - with codecs.open("log.txt", "a", "utf-8") as logfile: - logfile.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M")) - logfile.write("\n") - logfile.write(cmd) - logfile.write("\n") - - # Let exceptions escape from subprocess calls -- higher level - # code will handle them. - if logCommandOutput: - p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - while True: - l = p.stdout.readline().decode(GetLocale(), 'replace') - if l: - logfile.write(l) - PrintCommandOutput(l) - elif p.poll() is not None: - break - else: - p = subprocess.Popen(shlex.split(cmd)) - p.wait() - - if p.returncode != 0: - # If verbosity >= 3, we'll have already been printing out command output - # so no reason to print the log file again. - if verbosity < 3: - with open("log.txt", "r") as logfile: - Print(logfile.read()) - raise RuntimeError("Failed to run '{cmd}'\nSee {log} for more details." - .format(cmd=cmd, log=os.path.abspath("log.txt"))) - -@contextlib.contextmanager -def CurrentWorkingDirectory(dir): - """Context manager that sets the current working directory to the given - directory and resets it to the original directory when closed.""" - curdir = os.getcwd() - os.chdir(dir) - try: yield - finally: os.chdir(curdir) - -def CopyFiles(context, src, dest): - """Copy files like shutil.copy, but src may be a glob pattern.""" - filesToCopy = glob.glob(src) - if not filesToCopy: - raise RuntimeError("File(s) to copy {src} not found".format(src=src)) - - instDestDir = os.path.join(context.instDir, dest) - for f in filesToCopy: - PrintCommandOutput("Copying {file} to {destDir}\n" - .format(file=f, destDir=instDestDir)) - shutil.copy(f, instDestDir) - -def CopyDirectory(context, srcDir, destDir): - """Copy directory like shutil.copytree.""" - instDestDir = os.path.join(context.instDir, destDir) - if os.path.isdir(instDestDir): - shutil.rmtree(instDestDir) - - PrintCommandOutput("Copying {srcDir} to {destDir}\n" - .format(srcDir=srcDir, destDir=instDestDir)) - shutil.copytree(srcDir, instDestDir) - -def AppendCXX11ABIArg(buildFlag, context, buildArgs): - """Append a build argument that defines _GLIBCXX_USE_CXX11_ABI - based on the settings in the context. This may either do nothing - or append an entry to buildArgs like: - - ="-D_GLIBCXX_USE_CXX11_ABI={0, 1}" - - If buildArgs contains settings for buildFlag, those settings will - be merged with the above define.""" - if context.useCXX11ABI is None: - return - - cxxFlags = ["-D_GLIBCXX_USE_CXX11_ABI={}".format(context.useCXX11ABI)] - - # buildArgs might look like: - # ["-DFOO=1", "-DBAR=2", ...] or ["-DFOO=1 -DBAR=2 ...", ...] - # - # See if any of the arguments in buildArgs start with the given - # buildFlag. If so, we want to take whatever that buildFlag has - # been set to and merge it in with the cxxFlags above. - # - # For example, if buildArgs = ['-DCMAKE_CXX_FLAGS="-w"', ...] - # we want to add "-w" to cxxFlags. - splitArgs = [shlex.split(a) for a in buildArgs] - for p in [item for arg in splitArgs for item in arg]: - if p.startswith(buildFlag): - (_, _, flags) = p.partition("=") - cxxFlags.append(flags) - - buildArgs.append('{flag}="{flags}"'.format( - flag=buildFlag, flags=" ".join(cxxFlags))) - -def FormatMultiProcs(numJobs, generator): - tag = "-j" - if generator: - if "Visual Studio" in generator: - tag = "/M:" # This will build multiple projects at once. - elif "Xcode" in generator: - tag = "-j " - - return "{tag}{procs}".format(tag=tag, procs=numJobs) - -def RunCMake(context, force, extraArgs = None): - """Invoke CMake to configure, build, and install a library whose - source code is located in the current working directory.""" - # Create a directory for out-of-source builds in the build directory - # using the name of the current working directory. - srcDir = os.getcwd() - instDir = (context.usdInstDir if srcDir == context.usdSrcDir - else context.instDir) - buildDir = os.path.join(context.buildDir, os.path.split(srcDir)[1]) - if force and os.path.isdir(buildDir): - shutil.rmtree(buildDir) - - if not os.path.isdir(buildDir): - os.makedirs(buildDir) - - generator = context.cmakeGenerator - - # On Windows, we need to explicitly specify the generator to ensure we're - # building a 64-bit project. (Surely there is a better way to do this?) - # TODO: figure out exactly what "vcvarsall.bat x64" sets to force x64 - if generator is None and Windows(): - if IsVisualStudio2019OrGreater(): - generator = "Visual Studio 16 2019" - elif IsVisualStudio2017OrGreater(): - generator = "Visual Studio 15 2017 Win64" - else: - generator = "Visual Studio 14 2015 Win64" - - if generator is not None: - generator = '-G "{gen}"'.format(gen=generator) - - if IsVisualStudio2019OrGreater(): - generator = generator + " -A x64" - - toolset = context.cmakeToolset - if toolset is not None: - toolset = '-T "{toolset}"'.format(toolset=toolset) - - # On MacOS, enable the use of @rpath for relocatable builds. - osx_rpath = None - if MacOS(): - osx_rpath = "-DCMAKE_MACOSX_RPATH=ON" - - # We use -DCMAKE_BUILD_TYPE for single-configuration generators - # (Ninja, make), and --config for multi-configuration generators - # (Visual Studio); technically we don't need BOTH at the same - # time, but specifying both is simpler than branching - config = "Release" - if context.buildDebug: - config = "Debug" - elif context.buildRelease: - config = "Release" - elif context.buildRelWithDebug: - config = "RelWithDebInfo" - - # Append extra argument controlling libstdc++ ABI if specified. - AppendCXX11ABIArg("-DCMAKE_CXX_FLAGS", context, extraArgs) - - with CurrentWorkingDirectory(buildDir): - Run(('emcmake ' if context.emscripten else '') + - 'cmake ' - '-DCMAKE_INSTALL_PREFIX="{instDir}" ' - '-DCMAKE_PREFIX_PATH="{depsInstDir}" ' - '-DCMAKE_BUILD_TYPE={config} ' - '{osx_rpath} ' - '{generator} ' - '{toolset} ' - '{extraArgs} ' - '"{srcDir}"' - .format(instDir=instDir, - depsInstDir=context.instDir, - config=config, - srcDir=srcDir, - osx_rpath=(osx_rpath or ""), - generator=(generator or ""), - toolset=(toolset or ""), - extraArgs=(" ".join(extraArgs) if extraArgs else ""))) - Run(('emmake ' if context.emscripten else '') + - "cmake --build . --config {config} --target install -- {multiproc}" - .format(config=config, - multiproc=FormatMultiProcs(context.numJobs, generator))) - -def GetCMakeVersion(): - """ - Returns the CMake version as tuple of integers (major, minor) or - (major, minor, patch) or None if an error occured while launching cmake and - parsing its output. - """ - - output_string = GetCommandOutput("cmake --version") - if not output_string: - PrintWarning("Could not determine cmake version -- please install it " - "and adjust your PATH") - return None - - # cmake reports, e.g., "... version 3.14.3" - match = re.search(r"version (\d+)\.(\d+)(\.(\d+))?", output_string) - if not match: - PrintWarning("Could not determine cmake version") - return None - - major, minor, patch_group, patch = match.groups() - if patch_group is None: - return (int(major), int(minor)) - else: - return (int(major), int(minor), int(patch)) - -def PatchFile(filename, patches, multiLineMatches=False): - """Applies patches to the specified file. patches is a list of tuples - (old string, new string).""" - if multiLineMatches: - oldLines = [open(filename, 'r').read()] - else: - oldLines = open(filename, 'r').readlines() - newLines = oldLines - for (oldString, newString) in patches: - newLines = [s.replace(oldString, newString) for s in newLines] - if newLines != oldLines: - PrintInfo("Patching file {filename} (original in {oldFilename})..." - .format(filename=filename, oldFilename=filename + ".old")) - shutil.copy(filename, filename + ".old") - open(filename, 'w').writelines(newLines) - -def DownloadFileWithCurl(url, outputFilename): - # Don't log command output so that curl's progress - # meter doesn't get written to the log file. - Run("curl {progress} -L -o {filename} {url}".format( - progress="-#" if verbosity >= 2 else "-s", - filename=outputFilename, url=url), - logCommandOutput=False) - -def DownloadFileWithPowershell(url, outputFilename): - # It's important that we specify to use TLS v1.2 at least or some - # of the downloads will fail. - cmd = "powershell [Net.ServicePointManager]::SecurityProtocol = \ - [Net.SecurityProtocolType]::Tls12; \"(new-object \ - System.Net.WebClient).DownloadFile('{url}', '{filename}')\""\ - .format(filename=outputFilename, url=url) - - Run(cmd,logCommandOutput=False) - -def DownloadFileWithUrllib(url, outputFilename): - r = urlopen(url) - with open(outputFilename, "wb") as outfile: - outfile.write(r.read()) - -def DownloadURL(url, context, force, extractDir = None, - dontExtract = None): - """Download and extract the archive file at given URL to the - source directory specified in the context. - - dontExtract may be a sequence of path prefixes that will - be excluded when extracting the archive. - - Returns the absolute path to the directory where files have - been extracted.""" - with CurrentWorkingDirectory(context.srcDir): - # Extract filename from URL and see if file already exists. - filename = url.split("/")[-1] - if force and os.path.exists(filename): - os.remove(filename) - - if os.path.exists(filename): - PrintInfo("{0} already exists, skipping download" - .format(os.path.abspath(filename))) - else: - PrintInfo("Downloading {0} to {1}" - .format(url, os.path.abspath(filename))) - - # To work around occasional hiccups with downloading from websites - # (SSL validation errors, etc.), retry a few times if we don't - # succeed in downloading the file. - maxRetries = 5 - lastError = None - - # Download to a temporary file and rename it to the expected - # filename when complete. This ensures that incomplete downloads - # will be retried if the script is run again. - tmpFilename = filename + ".tmp" - if os.path.exists(tmpFilename): - os.remove(tmpFilename) - - for i in range(maxRetries): - try: - context.downloader(url, tmpFilename) - break - except Exception as e: - PrintCommandOutput("Retrying download due to error: {err}\n" - .format(err=e)) - lastError = e - else: - errorMsg = str(lastError) - if "SSL: TLSV1_ALERT_PROTOCOL_VERSION" in errorMsg: - errorMsg += ("\n\n" - "Your OS or version of Python may not support " - "TLS v1.2+, which is required for downloading " - "files from certain websites. This support " - "was added in Python 2.7.9." - "\n\n" - "You can use curl to download dependencies " - "by installing it in your PATH and re-running " - "this script.") - raise RuntimeError("Failed to download {url}: {err}" - .format(url=url, err=errorMsg)) - - shutil.move(tmpFilename, filename) - - # Open the archive and retrieve the name of the top-most directory. - # This assumes the archive contains a single directory with all - # of the contents beneath it, unless a specific extractDir is specified, - # which is to be used. - archive = None - rootDir = None - members = None - try: - if tarfile.is_tarfile(filename): - archive = tarfile.open(filename) - if extractDir: - rootDir = extractDir - else: - rootDir = archive.getnames()[0].split('/')[0] - if dontExtract != None: - members = (m for m in archive.getmembers() - if not any((fnmatch.fnmatch(m.name, p) - for p in dontExtract))) - elif zipfile.is_zipfile(filename): - archive = zipfile.ZipFile(filename) - if extractDir: - rootDir = extractDir - else: - rootDir = archive.namelist()[0].split('/')[0] - if dontExtract != None: - members = (m for m in archive.getnames() - if not any((fnmatch.fnmatch(m, p) - for p in dontExtract))) - elif filename.endswith('.js'): - return os.path.abspath(filename) - else: - raise RuntimeError("unrecognized archive file type") - - with archive: - extractedPath = os.path.abspath(rootDir) - if force and os.path.isdir(extractedPath): - shutil.rmtree(extractedPath) - - if os.path.isdir(extractedPath): - PrintInfo("Directory {0} already exists, skipping extract" - .format(extractedPath)) - else: - PrintInfo("Extracting archive to {0}".format(extractedPath)) - - # Extract to a temporary directory then move the contents - # to the expected location when complete. This ensures that - # incomplete extracts will be retried if the script is run - # again. - tmpExtractedPath = os.path.abspath("extract_dir") - if os.path.isdir(tmpExtractedPath): - shutil.rmtree(tmpExtractedPath) - - archive.extractall(tmpExtractedPath, members=members) - - shutil.move(os.path.join(tmpExtractedPath, rootDir), - extractedPath) - shutil.rmtree(tmpExtractedPath) - - return extractedPath - except Exception as e: - # If extraction failed for whatever reason, assume the - # archive file was bad and move it aside so that re-running - # the script will try downloading and extracting again. - shutil.move(filename, filename + ".bad") - raise RuntimeError("Failed to extract archive {filename}: {err}" - .format(filename=filename, err=e)) - -############################################################ -# 3rd-Party Dependencies - -AllDependencies = list() -AllDependenciesByName = dict() - -class Dependency(object): - def __init__(self, name, installer, *files): - self.name = name - self.installer = installer - self.filesToCheck = files - - AllDependencies.append(self) - AllDependenciesByName.setdefault(name.lower(), self) - - def Exists(self, context): - return all([os.path.isfile(os.path.join(context.instDir, f)) - for f in self.filesToCheck]) - -class PythonDependency(object): - def __init__(self, name, getInstructions, moduleNames): - self.name = name - self.getInstructions = getInstructions - self.moduleNames = moduleNames - - def Exists(self, context): - # If one of the modules in our list imports successfully, we are good. - for moduleName in self.moduleNames: - try: - pyModule = __import__(moduleName) - return True - except: - pass - - return False - -def AnyPythonDependencies(deps): - return any([type(d) is PythonDependency for d in deps]) - -############################################################ -# zlib - -ZLIB_URL = "https://github.com/madler/zlib/archive/v1.2.11.zip" - -def InstallZlib(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(ZLIB_URL, context, force)): - RunCMake(context, force, buildArgs) - -ZLIB = Dependency("zlib", InstallZlib, "include/zlib.h") - -############################################################ -# boost - -if MacOS(): - BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" - BOOST_VERSION_FILE = "include/boost/version.hpp" -elif Linux(): - if Python3(): - BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" - else: - BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.66.0/source/boost_1_66_0.tar.gz" - BOOST_VERSION_FILE = "include/boost/version.hpp" -elif Windows(): - # The default installation of boost on Windows puts headers in a versioned - # subdirectory, which we have to account for here. In theory, specifying - # "layout=system" would make the Windows install match Linux/MacOS, but that - # causes problems for other dependencies that look for boost. - # - # boost 1.70 is required for Visual Studio 2019. For simplicity, we use - # this version for all older Visual Studio versions as well. - BOOST_URL = "https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.gz" - BOOST_VERSION_FILE = "include/boost-1_70/boost/version.hpp" - -def InstallBoost_Helper(context, force, buildArgs): - # Documentation files in the boost archive can have exceptionally - # long paths. This can lead to errors when extracting boost on Windows, - # since paths are limited to 260 characters by default on that platform. - # To avoid this, we skip extracting all documentation. - # - # For some examples, see: https://svn.boost.org/trac10/ticket/11677 - dontExtract = ["*/doc/*", "*/libs/*/doc/*"] - - with CurrentWorkingDirectory(DownloadURL(BOOST_URL, context, force, - dontExtract=dontExtract)): - bootstrap = "bootstrap.bat" if Windows() else "./bootstrap.sh" - Run('{bootstrap} --prefix="{instDir}"' - .format(bootstrap=bootstrap, instDir=context.instDir)) - - # b2 supports at most -j64 and will error if given a higher value. - num_procs = min(64, context.numJobs) - - # boost only accepts three variants: debug, release, profile - boostBuildVariant = "profile" - if context.buildDebug: - boostBuildVariant= "debug" - elif context.buildRelease: - boostBuildVariant= "release" - elif context.buildRelWithDebug: - boostBuildVariant= "profile" - - b2_settings = [ - '--prefix="{instDir}"'.format(instDir=context.instDir), - '--build-dir="{buildDir}"'.format(buildDir=context.buildDir), - '-j{procs}'.format(procs=num_procs), - 'address-model=64', - 'link=shared', - 'runtime-link=shared', - 'threading=multi', - 'variant={variant}'.format(variant=boostBuildVariant), - '--with-atomic', - '--with-program_options', - '--with-regex' - ] - - if context.buildPython: - b2_settings.append("--with-python") - pythonInfo = GetPythonInfo(context) - # This is the only platform-independent way to configure these - # settings correctly and robustly for the Boost jam build system. - # There are Python config arguments that can be passed to bootstrap - # but those are not available in boostrap.bat (Windows) so we must - # take the following approach: - projectPath = 'python-config.jam' - with open(projectPath, 'w') as projectFile: - # Note that we must escape any special characters, like - # backslashes for jam, hence the mods below for the path - # arguments. Also, if the path contains spaces jam will not - # handle them well. Surround the path parameters in quotes. - projectFile.write('using python : %s\n' % pythonInfo[3]) - projectFile.write(' : "%s"\n' % pythonInfo[0].replace("\\","/")) - projectFile.write(' : "%s"\n' % pythonInfo[2].replace("\\","/")) - projectFile.write(' : "%s"\n' % os.path.dirname(pythonInfo[1]).replace("\\","/")) - if context.buildDebug and context.debugPython: - projectFile.write(' : on\n') - projectFile.write(' ;\n') - b2_settings.append("--user-config=python-config.jam") - - if context.buildDebug and context.debugPython: - b2_settings.append("python-debugging=on") - - if context.buildOIIO: - b2_settings.append("--with-date_time") - - if context.buildOIIO or context.enableOpenVDB: - b2_settings.append("--with-system") - b2_settings.append("--with-thread") - - if context.enableOpenVDB: - b2_settings.append("--with-iostreams") - - # b2 with -sNO_COMPRESSION=1 fails with the following error message: - # error: at [...]/boost_1_61_0/tools/build/src/kernel/modules.jam:107 - # error: Unable to find file or target named - # error: '/zlib//zlib' - # error: referred to from project at - # error: 'libs/iostreams/build' - # error: could not resolve project reference '/zlib' - - # But to avoid an extra library dependency, we can still explicitly - # exclude the bzip2 compression from boost_iostreams (note that - # OpenVDB uses blosc compression). - b2_settings.append("-sNO_BZIP2=1") - - if context.buildOIIO: - b2_settings.append("--with-filesystem") - - if force: - b2_settings.append("-a") - - if Windows(): - # toolset parameter for Visual Studio documented here: - # https://github.com/boostorg/build/blob/develop/src/tools/msvc.jam - if context.cmakeToolset == "v142": - b2_settings.append("toolset=msvc-14.2") - elif context.cmakeToolset == "v141": - b2_settings.append("toolset=msvc-14.1") - elif context.cmakeToolset == "v140": - b2_settings.append("toolset=msvc-14.0") - elif IsVisualStudio2019OrGreater(): - b2_settings.append("toolset=msvc-14.2") - elif IsVisualStudio2017OrGreater(): - b2_settings.append("toolset=msvc-14.1") - else: - b2_settings.append("toolset=msvc-14.0") - - if MacOS(): - # Must specify toolset=clang to ensure install_name for boost - # libraries includes @rpath - b2_settings.append("toolset=clang") - - if context.buildDebug: - b2_settings.append("--debug-configuration") - - # Add on any user-specified extra arguments. - b2_settings += buildArgs - - # Append extra argument controlling libstdc++ ABI if specified. - AppendCXX11ABIArg("cxxflags", context, b2_settings) - - b2 = "b2" if Windows() else "./b2" - Run('{b2} {options} install' - .format(b2=b2, options=" ".join(b2_settings))) - -def InstallBoost(context, force, buildArgs): - # Boost's build system will install the version.hpp header before - # building its libraries. We make sure to remove it in case of - # any failure to ensure that the build script detects boost as a - # dependency to build the next time it's run. - try: - InstallBoost_Helper(context, force, buildArgs) - except: - versionHeader = os.path.join(context.instDir, BOOST_VERSION_FILE) - if os.path.isfile(versionHeader): - try: os.remove(versionHeader) - except: pass - raise - -BOOST = Dependency("boost", InstallBoost, BOOST_VERSION_FILE) - -############################################################ -# Intel TBB - -if Windows(): - TBB_URL = "https://github.com/oneapi-src/oneTBB/releases/download/2018_U6/tbb2018_20180822oss_win.zip" -elif MacOS(): - # On MacOS we experience various crashes in tests during teardown - # starting with 2018 Update 2. Until we figure that out, we use - # 2018 Update 1 on this platform. - TBB_URL = "https://github.com/oneapi-src/oneTBB/archive/2018_U1.tar.gz" -else: - TBB_URL = "https://github.com/oneapi-src/oneTBB/archive/2018_U6.tar.gz" - -# Note: this refers to a fork of tbb for wasm. Is this maintained? -TBB_EMSCRIPTEN_URL = "https://github.com/hpcwasm/wasmtbb/archive/master.zip" - -def InstallTBB(context, force, buildArgs): - if context.emscripten: - InstallTBB_Emscripten(context, force, buildArgs) - elif Windows(): - InstallTBB_Windows(context, force, buildArgs) - elif Linux() or MacOS(): - InstallTBB_LinuxOrMacOS(context, force, buildArgs) - -def InstallTBB_Windows(context, force, buildArgs): - TBB_ROOT_DIR_NAME = "tbb2018_20180822oss" - with CurrentWorkingDirectory(DownloadURL(TBB_URL, context, force, - TBB_ROOT_DIR_NAME)): - # On Windows, we simply copy headers and pre-built DLLs to - # the appropriate location. - if buildArgs: - PrintWarning("Ignoring build arguments {}, TBB is " - "not built from source on this platform." - .format(buildArgs)) - - CopyFiles(context, "bin\\intel64\\vc14\\*.*", "bin") - CopyFiles(context, "lib\\intel64\\vc14\\*.*", "lib") - CopyDirectory(context, "include\\serial", "include\\serial") - CopyDirectory(context, "include\\tbb", "include\\tbb") - -def InstallTBB_LinuxOrMacOS(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(TBB_URL, context, force)): - # Note: TBB installation fails on OSX when cuda is installed, a - # suggested fix: - # https://github.com/spack/spack/issues/6000#issuecomment-358817701 - if MacOS(): - PatchFile("build/macos.inc", - [("shell clang -v ", "shell clang --version ")]) - - # Append extra argument controlling libstdc++ ABI if specified. - AppendCXX11ABIArg("CXXFLAGS", context, buildArgs) - - # TBB does not support out-of-source builds in a custom location. - Run('make -j{procs} {buildArgs}' - .format(procs=context.numJobs, - buildArgs=" ".join(buildArgs))) - - # Install both release and debug builds. USD requires the debug - # libraries when building in debug mode, and installing both - # makes it easier for users to install dependencies in some - # location that can be shared by both release and debug USD - # builds. Plus, the TBB build system builds both versions anyway. - CopyFiles(context, "build/*_release/libtbb*.*", "lib") - CopyFiles(context, "build/*_debug/libtbb*.*", "lib") - CopyDirectory(context, "include/serial", "include/serial") - CopyDirectory(context, "include/tbb", "include/tbb") - -def InstallTBB_Emscripten(context, force, buildArgs): - - with CurrentWorkingDirectory(DownloadURL(TBB_EMSCRIPTEN_URL, context, force)): - # By default no config for macos is avaiable, but the one for linux - # seems to work fine - if MacOS(): - shutil.copy('build/linux.emscripten.inc', 'build/macos.emscripten.inc') - - # TBB does not support out-of-source builds in a custom location. - Run('emmake make -j{procs} extra_inc=big_iron.inc tbb {buildArgs}' - .format(procs=context.numJobs, - buildArgs=" ".join(buildArgs))) - - # Install both release and debug builds. USD requires the debug - # libraries when building in debug mode, and installing both - # makes it easier for users to install dependencies in some - # location that can be shared by both release and debug USD - # builds. Plus, the TBB build system builds both versions anyway. - CopyFiles(context, "build/*_release/libtbb*.*", "lib") - CopyFiles(context, "build/*_debug/libtbb*.*", "lib") - CopyDirectory(context, "include/serial", "include/serial") - CopyDirectory(context, "include/tbb", "include/tbb") - -TBB = Dependency("TBB", InstallTBB, "include/tbb/tbb.h") - -############################################################ -# JPEG - -if Windows(): - JPEG_URL = "https://github.com/libjpeg-turbo/libjpeg-turbo/archive/1.5.1.zip" -else: - JPEG_URL = "https://www.ijg.org/files/jpegsrc.v9b.tar.gz" - -def InstallJPEG(context, force, buildArgs): - if Windows(): - InstallJPEG_Turbo(context, force, buildArgs) - else: - InstallJPEG_Lib(context, force, buildArgs) - -def InstallJPEG_Turbo(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(JPEG_URL, context, force)): - RunCMake(context, force, buildArgs) - -def InstallJPEG_Lib(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(JPEG_URL, context, force)): - Run('./configure --prefix="{instDir}" ' - '--disable-static --enable-shared ' - '{buildArgs}' - .format(instDir=context.instDir, - buildArgs=" ".join(buildArgs))) - Run('make -j{procs} install' - .format(procs=context.numJobs)) - -JPEG = Dependency("JPEG", InstallJPEG, "include/jpeglib.h") - -############################################################ -# TIFF - -TIFF_URL = "https://gitlab.com/libtiff/libtiff/-/archive/Release-v4-0-7/libtiff-Release-v4-0-7.tar.gz" - -def InstallTIFF(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(TIFF_URL, context, force)): - # libTIFF has a build issue on Windows where tools/tiffgt.c - # unconditionally includes unistd.h, which does not exist. - # To avoid this, we patch the CMakeLists.txt to skip building - # the tools entirely. We do this on Linux and MacOS as well - # to avoid requiring some GL and X dependencies. - # - # We also need to skip building tests, since they rely on - # the tools we've just elided. - PatchFile("CMakeLists.txt", - [("add_subdirectory(tools)", "# add_subdirectory(tools)"), - ("add_subdirectory(test)", "# add_subdirectory(test)")]) - - # The libTIFF CMakeScript says the ld-version-script - # functionality is only for compilers using GNU ld on - # ELF systems or systems which provide an emulation; therefore - # skipping it completely on mac and windows. - if MacOS() or Windows(): - extraArgs = ["-Dld-version-script=OFF"] - else: - extraArgs = [] - extraArgs += buildArgs - RunCMake(context, force, extraArgs) - -TIFF = Dependency("TIFF", InstallTIFF, "include/tiff.h") - -############################################################ -# PNG - -PNG_URL = "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.29.tar.gz" - -def InstallPNG(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(PNG_URL, context, force)): - RunCMake(context, force, buildArgs) - -PNG = Dependency("PNG", InstallPNG, "include/png.h") - -############################################################ -# IlmBase/OpenEXR - -OPENEXR_URL = "https://github.com/AcademySoftwareFoundation/openexr/archive/v2.3.0.zip" - -def InstallOpenEXR(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(OPENEXR_URL, context, force)): - RunCMake(context, force, - ['-DOPENEXR_BUILD_PYTHON_LIBS=OFF', - '-DOPENEXR_PACKAGE_PREFIX="{}"'.format(context.instDir), - '-DOPENEXR_ENABLE_TESTS=OFF'] + buildArgs) - -OPENEXR = Dependency("OpenEXR", InstallOpenEXR, "include/OpenEXR/ImfVersion.h") - -############################################################ -# Ptex - -PTEX_URL = "https://github.com/wdas/ptex/archive/v2.1.33.zip" - -def InstallPtex(context, force, buildArgs): - if Windows(): - InstallPtex_Windows(context, force, buildArgs) - else: - InstallPtex_LinuxOrMacOS(context, force, buildArgs) - -def InstallPtex_Windows(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(PTEX_URL, context, force)): - # Ptex has a bug where the import library for the dynamic library and - # the static library both get the same name, Ptex.lib, and as a - # result one clobbers the other. We hack the appropriate CMake - # file to prevent that. Since we don't need the static library we'll - # rename that. - # - # In addition src\tests\CMakeLists.txt adds -DPTEX_STATIC to the - # compiler but links tests against the dynamic library, causing the - # links to fail. We patch the file to not add the -DPTEX_STATIC - PatchFile('src\\ptex\\CMakeLists.txt', - [("set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptex)", - "set_target_properties(Ptex_static PROPERTIES OUTPUT_NAME Ptexs)")]) - PatchFile('src\\tests\\CMakeLists.txt', - [("add_definitions(-DPTEX_STATIC)", - "# add_definitions(-DPTEX_STATIC)")]) - - # Patch Ptex::String to export symbol for operator<< - # This is required for newer versions of OIIO, which make use of the - # this operator on Windows platform specifically. - PatchFile('src\\ptex\\Ptexture.h', - [("std::ostream& operator << (std::ostream& stream, const Ptex::String& str);", - "PTEXAPI std::ostream& operator << (std::ostream& stream, const Ptex::String& str);")]) - - - RunCMake(context, force, buildArgs) - -def InstallPtex_LinuxOrMacOS(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(PTEX_URL, context, force)): - RunCMake(context, force, buildArgs) - -PTEX = Dependency("Ptex", InstallPtex, "include/PtexVersion.h") - -############################################################ -# BLOSC (Compression used by OpenVDB) - -# Using blosc v1.20.1 to avoid build errors on macOS Catalina (10.15) -# related to implicit declaration of functions in zlib. See: -# https://github.com/Blosc/python-blosc/issues/229 -BLOSC_URL = "https://github.com/Blosc/c-blosc/archive/v1.20.1.zip" - -def InstallBLOSC(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(BLOSC_URL, context, force)): - RunCMake(context, force, buildArgs) - -BLOSC = Dependency("Blosc", InstallBLOSC, "include/blosc.h") - -############################################################ -# OpenVDB - -# Using version 6.1.0 since it has reworked its CMake files so that -# there are better options to not compile the OpenVDB binaries and to -# not require additional dependencies such as GLFW. Note that version -# 6.1.0 does require CMake 3.3 though. - -OPENVDB_URL = "https://github.com/AcademySoftwareFoundation/openvdb/archive/v6.1.0.zip" - -def InstallOpenVDB(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(OPENVDB_URL, context, force)): - extraArgs = [ - '-DOPENVDB_BUILD_PYTHON_MODULE=OFF', - '-DOPENVDB_BUILD_BINARIES=OFF', - '-DOPENVDB_BUILD_UNITTESTS=OFF' - ] - - # Make sure to use boost installed by the build script and not any - # system installed boost - extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') - extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') - - extraArgs.append('-DBLOSC_ROOT="{instDir}"' - .format(instDir=context.instDir)) - extraArgs.append('-DTBB_ROOT="{instDir}"' - .format(instDir=context.instDir)) - # OpenVDB needs Half type from IlmBase - extraArgs.append('-DILMBASE_ROOT="{instDir}"' - .format(instDir=context.instDir)) - - # Add on any user-specified extra arguments. - extraArgs += buildArgs - - RunCMake(context, force, extraArgs) - -OPENVDB = Dependency("OpenVDB", InstallOpenVDB, "include/openvdb/openvdb.h") - -############################################################ -# OpenImageIO - -OIIO_URL = "https://github.com/OpenImageIO/oiio/archive/Release-2.1.16.0.zip" - -def InstallOpenImageIO(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(OIIO_URL, context, force)): - extraArgs = ['-DOIIO_BUILD_TOOLS=OFF', - '-DOIIO_BUILD_TESTS=OFF', - '-DUSE_PYTHON=OFF', - '-DSTOP_ON_WARNING=OFF'] - - # OIIO's FindOpenEXR module circumvents CMake's normal library - # search order, which causes versions of OpenEXR installed in - # /usr/local or other hard-coded locations in the module to - # take precedence over the version we've built, which would - # normally be picked up when we specify CMAKE_PREFIX_PATH. - # This may lead to undefined symbol errors at build or runtime. - # So, we explicitly specify the OpenEXR we want to use here. - extraArgs.append('-DOPENEXR_ROOT="{instDir}"' - .format(instDir=context.instDir)) - - # If Ptex support is disabled in USD, disable support in OpenImageIO - # as well. This ensures OIIO doesn't accidentally pick up a Ptex - # library outside of our build. - if not context.enablePtex: - extraArgs.append('-DUSE_PTEX=OFF') - - # Make sure to use boost installed by the build script and not any - # system installed boost - extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') - extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') - - # Add on any user-specified extra arguments. - extraArgs += buildArgs - - RunCMake(context, force, extraArgs) - -OPENIMAGEIO = Dependency("OpenImageIO", InstallOpenImageIO, - "include/OpenImageIO/oiioversion.h") - -############################################################ -# OpenColorIO - -OCIO_URL = "https://github.com/imageworks/OpenColorIO/archive/v1.1.0.zip" - -def InstallOpenColorIO(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(OCIO_URL, context, force)): - extraArgs = ['-DOCIO_BUILD_TRUELIGHT=OFF', - '-DOCIO_BUILD_APPS=OFF', - '-DOCIO_BUILD_NUKE=OFF', - '-DOCIO_BUILD_DOCS=OFF', - '-DOCIO_BUILD_TESTS=OFF', - '-DOCIO_BUILD_PYGLUE=OFF', - '-DOCIO_BUILD_JNIGLUE=OFF', - '-DOCIO_STATIC_JNIGLUE=OFF'] - - # OpenImageIO v1.1.0 fails to build on Windows with the RelWithDebInfo - # build type because it doesn't set up the correct properties for the - # YAML library it relies on. This patch works around that issue. - if Windows() and context.buildRelWithDebug: - PatchFile("CMakeLists.txt", - [("IMPORTED_LOCATION_RELEASE", - "IMPORTED_LOCATION_RELWITHDEBINFO")]) - - # The OCIO build treats all warnings as errors but several come up - # on various platforms, including: - # - On gcc6, v1.1.0 emits many -Wdeprecated-declaration warnings for - # std::auto_ptr - # - On clang, v1.1.0 emits a -Wself-assign-field warning. This is fixed - # in https://github.com/AcademySoftwareFoundation/OpenColorIO/commit/0be465feb9ac2d34bd8171f30909b276c1efa996 - # - # To avoid build failures we force all warnings off for this build. - if GetVisualStudioCompilerAndVersion(): - # This doesn't work because CMake stores default flags for - # MSVC in CMAKE_CXX_FLAGS and this would overwrite them. - # However, we don't seem to get any warnings on Windows - # (at least with VS2015 and 2017). - # extraArgs.append('-DCMAKE_CXX_FLAGS=/w') - pass - else: - extraArgs.append('-DCMAKE_CXX_FLAGS=-w') - - # Add on any user-specified extra arguments. - extraArgs += buildArgs - - RunCMake(context, force, extraArgs) - -OPENCOLORIO = Dependency("OpenColorIO", InstallOpenColorIO, - "include/OpenColorIO/OpenColorABI.h") - -############################################################ -# OpenSubdiv - -OPENSUBDIV_URL = "https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_4_3.zip" - -def InstallOpenSubdiv(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(OPENSUBDIV_URL, context, force)): - extraArgs = [ - '-DNO_EXAMPLES=ON', - '-DNO_TUTORIALS=ON', - '-DNO_REGRESSION=ON', - '-DNO_DOC=ON', - '-DNO_OMP=ON', - '-DNO_CUDA=ON', - '-DNO_OPENCL=ON', - '-DNO_DX=ON', - '-DNO_TESTS=ON', - '-DNO_GLEW=ON', - '-DNO_GLFW=ON', - ] - if context.emscripten: - extraArgs.append('-DBUILD_SHARED_LIB=OFF') - extraArgs.append('-DCMAKE_CXX_FLAGS="-s USE_PTHREADS=1"') - extraArgs.append('-DCMAKE_C_FLAGS="-s USE_PTHREADS=1"') - extraArgs.append('-DNO_OPENGL=ON') - extraArgs.append('-DNO_METAL=ON') - - # If Ptex support is disabled in USD, disable support in OpenSubdiv - # as well. This ensures OSD doesn't accidentally pick up a Ptex - # library outside of our build. - if not context.enablePtex: - extraArgs.append('-DNO_PTEX=ON') - - # NOTE: For now, we disable TBB in our OpenSubdiv build. - # This avoids an issue where OpenSubdiv will link against - # all TBB libraries it finds, including libtbbmalloc and - # libtbbmalloc_proxy. On Linux and MacOS, this has the - # unwanted effect of replacing the system allocator with - # tbbmalloc. - extraArgs.append('-DNO_TBB=ON') - - # Add on any user-specified extra arguments. - extraArgs += buildArgs - - # OpenSubdiv seems to error when building on windows w/ Ninja... - # ...so just use the default generator (ie, Visual Studio on Windows) - # until someone can sort it out - oldGenerator = context.cmakeGenerator - if oldGenerator == "Ninja" and Windows(): - context.cmakeGenerator = None - - # OpenSubdiv 3.3 and later on MacOS occasionally runs into build - # failures with multiple build jobs. Workaround this by using - # just 1 job for now. See: - # https://github.com/PixarAnimationStudios/OpenSubdiv/issues/1194 - oldNumJobs = context.numJobs - if MacOS() or context.emscripten: - context.numJobs = 1 - - try: - RunCMake(context, force, extraArgs) - finally: - context.cmakeGenerator = oldGenerator - context.numJobs = oldNumJobs - -OPENSUBDIV = Dependency("OpenSubdiv", InstallOpenSubdiv, - "include/opensubdiv/version.h") - -############################################################ -# PyOpenGL - -def GetPyOpenGLInstructions(): - return ('PyOpenGL is not installed. If you have pip ' - 'installed, run "pip install PyOpenGL" to ' - 'install it, then re-run this script.\n' - 'If PyOpenGL is already installed, you may need to ' - 'update your PYTHONPATH to indicate where it is ' - 'located.') - -PYOPENGL = PythonDependency("PyOpenGL", GetPyOpenGLInstructions, - moduleNames=["OpenGL"]) - -############################################################ -# PySide - -def GetPySideInstructions(): - # For licensing reasons, this script cannot install PySide itself. - if Windows(): - # There is no distribution of PySide2 for Windows for Python 2.7. - # So use PySide instead. See the following for more details: - # https://wiki.qt.io/Qt_for_Python/Considerations#Missing_Windows_.2F_Python_2.7_release - return ('PySide is not installed. If you have pip ' - 'installed, run "pip install PySide" ' - 'to install it, then re-run this script.\n' - 'If PySide is already installed, you may need to ' - 'update your PYTHONPATH to indicate where it is ' - 'located.') - else: - return ('PySide2 is not installed. If you have pip ' - 'installed, run "pip install PySide2" ' - 'to install it, then re-run this script.\n' - 'If PySide2 is already installed, you may need to ' - 'update your PYTHONPATH to indicate where it is ' - 'located.') - -PYSIDE = PythonDependency("PySide", GetPySideInstructions, - moduleNames=["PySide", "PySide2"]) - -############################################################ -# HDF5 - -HDF5_URL = "https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.0-patch1/src/hdf5-1.10.0-patch1.zip" - -def InstallHDF5(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(HDF5_URL, context, force)): - RunCMake(context, force, - ['-DBUILD_TESTING=OFF', - '-DHDF5_BUILD_TOOLS=OFF', - '-DHDF5_BUILD_EXAMPLES=OFF'] + buildArgs) - -HDF5 = Dependency("HDF5", InstallHDF5, "include/hdf5.h") - -############################################################ -# Alembic - -ALEMBIC_URL = "https://github.com/alembic/alembic/archive/1.7.10.zip" - -def InstallAlembic(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(ALEMBIC_URL, context, force)): - cmakeOptions = ['-DUSE_BINARIES=OFF', '-DUSE_TESTS=OFF'] - if context.enableHDF5: - # HDF5 requires the H5_BUILT_AS_DYNAMIC_LIB macro be defined if - # it was built with CMake as a dynamic library. - cmakeOptions += [ - '-DUSE_HDF5=ON', - '-DHDF5_ROOT="{instDir}"'.format(instDir=context.instDir), - '-DCMAKE_CXX_FLAGS="-D H5_BUILT_AS_DYNAMIC_LIB"'] - else: - cmakeOptions += ['-DUSE_HDF5=OFF'] - - cmakeOptions += buildArgs - - RunCMake(context, force, cmakeOptions) - -ALEMBIC = Dependency("Alembic", InstallAlembic, "include/Alembic/Abc/Base.h") - -############################################################ -# Draco - -DRACO_URL = "https://github.com/google/draco/archive/master.zip" - -def InstallDraco(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(DRACO_URL, context, force)): - cmakeOptions = ['-DBUILD_USD_PLUGIN=ON'] - cmakeOptions += buildArgs - RunCMake(context, force, cmakeOptions) - -DRACO = Dependency("Draco", InstallDraco, "include/draco/compression/decode.h") - -############################################################ -# MaterialX - -MATERIALX_URL = "https://github.com/materialx/MaterialX/archive/v1.38.0.zip" - -def InstallMaterialX(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(MATERIALX_URL, context, force)): - # USD requires MaterialX to be built as a shared library on Linux and MacOS - # Currently MaterialX does not support shared builds on Windows - cmakeOptions = [] - if Linux() or MacOS(): - cmakeOptions += ['-DMATERIALX_BUILD_SHARED_LIBS=ON'] - - cmakeOptions += buildArgs; - - RunCMake(context, force, cmakeOptions) - -MATERIALX = Dependency("MaterialX", InstallMaterialX, "include/MaterialXCore/Library.h") - -############################################################ -# Embree -# For MacOS we use version 3.7.0 to include a fix from Intel -# to build on Catalina. -if MacOS(): - EMBREE_URL = "https://github.com/embree/embree/archive/v3.7.0.tar.gz" -else: - EMBREE_URL = "https://github.com/embree/embree/archive/v3.2.2.tar.gz" - -def InstallEmbree(context, force, buildArgs): - with CurrentWorkingDirectory(DownloadURL(EMBREE_URL, context, force)): - extraArgs = [ - '-DTBB_ROOT={instDir}'.format(instDir=context.instDir), - '-DEMBREE_TUTORIALS=OFF', - '-DEMBREE_ISPC_SUPPORT=OFF' - ] - - # By default Embree fails to build on Visual Studio 2015 due - # to an internal compiler issue that is worked around via the - # following flag. For more details see: - # https://github.com/embree/embree/issues/157 - if IsVisualStudio2015OrGreater() and not IsVisualStudio2017OrGreater(): - extraArgs.append('-DCMAKE_CXX_FLAGS=/d2SSAOptimizer-') - - extraArgs += buildArgs - - RunCMake(context, force, extraArgs) - -EMBREE = Dependency("Embree", InstallEmbree, "include/embree3/rtcore.h") - -############################################################ -# USD - -def InstallUSD(context, force, buildArgs): - with CurrentWorkingDirectory(context.usdSrcDir): - extraArgs = [] - - extraArgs.append('-DPXR_PREFER_SAFETY_OVER_SPEED=' + - 'ON' if context.safetyFirst else 'OFF') - - if context.buildPython: - extraArgs.append('-DPXR_ENABLE_PYTHON_SUPPORT=ON') - if Python3(): - extraArgs.append('-DPXR_USE_PYTHON_3=ON') - - # Many people on Windows may not have python with the - # debugging symbol ( python27_d.lib ) installed, this is the common case - # where one downloads the python from official download website. Therefore we - # can still let people decide to build USD with release version of python if - # debugging into python land is not what they want which can be done by setting the - # debugPython - if context.buildDebug and context.debugPython: - extraArgs.append('-DPXR_USE_DEBUG_PYTHON=ON') - else: - extraArgs.append('-DPXR_USE_DEBUG_PYTHON=OFF') - - # CMake has trouble finding the executable, library, and include - # directories when there are multiple versions of Python installed. - # This can lead to crashes due to USD being linked against one - # version of Python but running through some other Python - # interpreter version. This primarily shows up on macOS, as it's - # common to have a Python install that's separate from the one - # included with the system. - # - # To avoid this, we try to determine these paths from Python - # itself rather than rely on CMake's heuristics. - pythonInfo = GetPythonInfo(context) - if pythonInfo: - # According to FindPythonLibs.cmake these are the variables - # to set to specify which Python installation to use. - extraArgs.append('-DPYTHON_EXECUTABLE="{pyExecPath}"' - .format(pyExecPath=pythonInfo[0])) - extraArgs.append('-DPYTHON_LIBRARY="{pyLibPath}"' - .format(pyLibPath=pythonInfo[1])) - extraArgs.append('-DPYTHON_INCLUDE_DIR="{pyIncPath}"' - .format(pyIncPath=pythonInfo[2])) - else: - extraArgs.append('-DPXR_ENABLE_PYTHON_SUPPORT=OFF') - - if context.buildShared: - extraArgs.append('-DBUILD_SHARED_LIBS=ON') - elif context.buildMonolithic: - extraArgs.append('-DPXR_BUILD_MONOLITHIC=ON') - - if context.buildDebug: - extraArgs.append('-DTBB_USE_DEBUG_BUILD=ON') - else: - extraArgs.append('-DTBB_USE_DEBUG_BUILD=OFF') - - if context.buildDocs: - extraArgs.append('-DPXR_BUILD_DOCUMENTATION=ON') - else: - extraArgs.append('-DPXR_BUILD_DOCUMENTATION=OFF') - - if context.buildTests: - extraArgs.append('-DPXR_BUILD_TESTS=ON') - else: - extraArgs.append('-DPXR_BUILD_TESTS=OFF') - - if context.buildExamples: - extraArgs.append('-DPXR_BUILD_EXAMPLES=ON') - else: - extraArgs.append('-DPXR_BUILD_EXAMPLES=OFF') - - if context.buildTutorials: - extraArgs.append('-DPXR_BUILD_TUTORIALS=ON') - else: - extraArgs.append('-DPXR_BUILD_TUTORIALS=OFF') - - if context.buildTools: - extraArgs.append('-DPXR_BUILD_USD_TOOLS=ON') - else: - extraArgs.append('-DPXR_BUILD_USD_TOOLS=OFF') - - if context.buildImaging: - extraArgs.append('-DPXR_BUILD_IMAGING=ON') - if context.enablePtex: - extraArgs.append('-DPXR_ENABLE_PTEX_SUPPORT=ON') - else: - extraArgs.append('-DPXR_ENABLE_PTEX_SUPPORT=OFF') - - if context.enableOpenVDB: - extraArgs.append('-DPXR_ENABLE_OPENVDB_SUPPORT=ON') - else: - extraArgs.append('-DPXR_ENABLE_OPENVDB_SUPPORT=OFF') - - if context.buildEmbree: - extraArgs.append('-DPXR_BUILD_EMBREE_PLUGIN=ON') - else: - extraArgs.append('-DPXR_BUILD_EMBREE_PLUGIN=OFF') - - if context.buildPrman: - if context.prmanLocation: - extraArgs.append('-DRENDERMAN_LOCATION="{location}"' - .format(location=context.prmanLocation)) - extraArgs.append('-DPXR_BUILD_PRMAN_PLUGIN=ON') - else: - extraArgs.append('-DPXR_BUILD_PRMAN_PLUGIN=OFF') - - if context.buildOIIO: - extraArgs.append('-DPXR_BUILD_OPENIMAGEIO_PLUGIN=ON') - else: - extraArgs.append('-DPXR_BUILD_OPENIMAGEIO_PLUGIN=OFF') - - if context.buildOCIO: - extraArgs.append('-DPXR_BUILD_OPENCOLORIO_PLUGIN=ON') - else: - extraArgs.append('-DPXR_BUILD_OPENCOLORIO_PLUGIN=OFF') - - else: - extraArgs.append('-DPXR_BUILD_IMAGING=OFF') - - if context.buildUsdImaging: - extraArgs.append('-DPXR_BUILD_USD_IMAGING=ON') - else: - extraArgs.append('-DPXR_BUILD_USD_IMAGING=OFF') - - if context.buildUsdview: - extraArgs.append('-DPXR_BUILD_USDVIEW=ON') - else: - extraArgs.append('-DPXR_BUILD_USDVIEW=OFF') - - if context.buildAlembic: - extraArgs.append('-DPXR_BUILD_ALEMBIC_PLUGIN=ON') - if context.enableHDF5: - extraArgs.append('-DPXR_ENABLE_HDF5_SUPPORT=ON') - - # CMAKE_PREFIX_PATH isn't sufficient for the FindHDF5 module - # to find the HDF5 we've built, so provide an extra hint. - extraArgs.append('-DHDF5_ROOT="{instDir}"' - .format(instDir=context.instDir)) - else: - extraArgs.append('-DPXR_ENABLE_HDF5_SUPPORT=OFF') - else: - extraArgs.append('-DPXR_BUILD_ALEMBIC_PLUGIN=OFF') - - if context.buildDraco: - extraArgs.append('-DPXR_BUILD_DRACO_PLUGIN=ON') - draco_root = (context.dracoLocation - if context.dracoLocation else context.instDir) - extraArgs.append('-DDRACO_ROOT="{}"'.format(draco_root)) - else: - extraArgs.append('-DPXR_BUILD_DRACO_PLUGIN=OFF') - - if context.buildMaterialX: - extraArgs.append('-DPXR_ENABLE_MATERIALX_SUPPORT=ON') - else: - extraArgs.append('-DPXR_ENABLE_MATERIALX_SUPPORT=OFF') - - if Windows(): - # Increase the precompiled header buffer limit. - extraArgs.append('-DCMAKE_CXX_FLAGS="/Zm150"') - - # Make sure to use boost installed by the build script and not any - # system installed boost - extraArgs.append('-DBoost_NO_BOOST_CMAKE=On') - extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True') - extraArgs += buildArgs - - if context.emscripten: - extraArgs.append('-DPXR_ENABLE_JS_SUPPORT=ON') - # For some reason we have to manually specify path to boost - extraArgs.append('-DBoost_INCLUDE_DIR='+os.path.join(context.usdInstDir, "include")) - - extraArgs.append('-DTBB_INCLUDE_DIRS=' + os.path.join(context.usdInstDir, 'include')) - extraArgs.append('-DTBB_tbb_LIBRARY_DEBUG=' + os.path.join(context.usdInstDir, 'lib/libtbb_debug.a')) - extraArgs.append('-DTBB_tbb_LIBRARY_RELEASE=' + os.path.join(context.usdInstDir, 'lib/libtbb.a')) - - extraArgs.append('-DOPENSUBDIV_INCLUDE_DIR=' + os.path.join(context.usdInstDir, 'include')) - extraArgs.append('-DOPENSUBDIV_OSDCPU_LIBRARY=' + os.path.join(context.usdInstDir, 'lib/libosdCPU.a')) - - extraArgs.append('-DPXR_ENABLE_GL_SUPPORT=OFF') - extraArgs.append('-DBUILD_SHARED_LIBS=OFF') - - RunCMake(context, force, extraArgs) - -USD = Dependency("USD", InstallUSD, "include/pxr/pxr.h") - -############################################################ -# Install script - -programDescription = """\ -Installation Script for USD - -Builds and installs USD and 3rd-party dependencies to specified location. - -- Libraries: -The following is a list of libraries that this script will download and build -as needed. These names can be used to identify libraries for various script -options, like --force or --build-args. - -{libraryList} - -- Downloading Libraries: -If curl or powershell (on Windows) are installed and located in PATH, they -will be used to download dependencies. Otherwise, a built-in downloader will -be used. - -- Specifying Custom Build Arguments: -Users may specify custom build arguments for libraries using the --build-args -option. This values for this option must take the form ,