Quellcode durchsuchen

Temp WIP - openimageIO and OpenColorIO build scripts

Signed-off-by: lawsonamzn <[email protected]>
lawsonamzn vor 3 Jahren
Ursprung
Commit
8c8aa3fc49

+ 4 - 0
Scripts/cmake/Platform/Mac/Toolchain_mac.cmake

@@ -14,4 +14,8 @@ set(CMAKE_SYSTEM_NAME Darwin)
 set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "The minimum OSX Version to support" FORCE)
 set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "The minimum OSX Version to support" FORCE)
 set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
 set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
 
 
+# If we need to compile for Mac M1, set CMAKE_APPLE_SILICON_PROCESSOR to arm64 on the command line.
+# this will override CMAKE_HOST_SYSTEM_PROCESSOR.
+set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
+
 # cmake will auto-select the rest.
 # cmake will auto-select the rest.

+ 1 - 1
Scripts/extras/pull_and_build_from_git.py

@@ -623,7 +623,7 @@ class BuildInfo(object):
 
 
                 if self.package_info.custom_toolchain_file:
                 if self.package_info.custom_toolchain_file:
                     custom_toolchain_file = self.package_info.custom_toolchain_file
                     custom_toolchain_file = self.package_info.custom_toolchain_file
-                    custom_toolchain_file_path = pathlib.Path(custom_toolchain_file).resolve()
+                    custom_toolchain_file_path = pathlib.Path(custom_toolchain_file).absolute().resolve()
                     if not custom_toolchain_file_path.exists():
                     if not custom_toolchain_file_path.exists():
                         raise BuildError(f"Custom toolchain file specified does not exist: {custom_toolchain_file}\n"
                         raise BuildError(f"Custom toolchain file specified does not exist: {custom_toolchain_file}\n"
                                          f"Path resolved: {custom_toolchain_file_path} ")
                                          f"Path resolved: {custom_toolchain_file_path} ")

+ 40 - 7
package-system/OpenEXR/FindImath.cmake

@@ -14,13 +14,46 @@ include(${CMAKE_CURRENT_LIST_DIR}/o3de_package_utilities.cmake)
 
 
 o3de_import_existing_config_files(Imath ${CMAKE_CURRENT_LIST_DIR}/OpenEXR/lib/cmake)
 o3de_import_existing_config_files(Imath ${CMAKE_CURRENT_LIST_DIR}/OpenEXR/lib/cmake)
 
 
-o3de_import_targets(NAMESPACE_FROM 
-                        Imath
-                    NAMESPACE_TO 
-                        3rdParty
-                    COMPONENTS 
-                        Imath 
-                        ImathConfig)
+set(Imath_COMPONENTS
+    Imath::Imath
+    Imath::ImathConfig
+)
+
+foreach(component ${Imath_COMPONENTS})
+    if(TARGET ${component})
+        # convert the includes to system includes
+        get_target_property(system_includes ${component} INTERFACE_INCLUDE_DIRECTORIES)
+        set_target_properties(${component} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") # Clear it in case someone refers to it
+        
+        if (COMMAND ly_target_include_system_directories)
+            ly_target_include_system_directories(TARGET ${component} INTERFACE ${system_includes})
+        else()
+            target_include_directories(${component} SYSTEM INTERFACE ${system_includes})
+        endif()
+
+        # Alias the target with 3rdParty prefix
+        add_library(3rdParty::${component} ALIAS ${component})
+
+        # inside the loop where it sets the system includes for each component
+        foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
+            string(TOUPPER ${conf} UCONF)
+            if (${UCONF} STREQUAL "DEBUG" AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows)
+                set_target_properties(${component} PROPERTIES 
+                                        MAP_IMPORTED_CONFIG_${UCONF} DEBUG)
+            else()
+                set_target_properties(${component} PROPERTIES 
+                                        MAP_IMPORTED_CONFIG_${UCONF} RELEASE)
+            endif()
+        endforeach()
+    else()
+        message(WARNING "Target not found in Imath: ${component}")
+    endif()
+endforeach()
+
+# create main library alias that O3DE can use to get default dependencies.
+# users can also bind to any of the other components above, but this one gives you most of the functionality
+# you probably want:
+add_library(3rdParty::Imath ALIAS Imath::Imath)
 
 
 # if we're not in O3DE, it's also extremely helpful to show a message to logs that indicate that this
 # if we're not in O3DE, it's also extremely helpful to show a message to logs that indicate that this
 # library was successfully picked up, as opposed to the system one.
 # library was successfully picked up, as opposed to the system one.

+ 43 - 0
package-system/OpenEXR/FindOpenEXR.cmake

@@ -24,6 +24,49 @@ if (NOT TARGET ZLIB::ZLIB)
 endif()
 endif()
 
 
 find_package(Imath MODULE REQUIRED) # will bring in the FindImath.cmake in the same folder
 find_package(Imath MODULE REQUIRED) # will bring in the FindImath.cmake in the same folder
+find_package(OpenEXR CONFIG REQUIRED)
+
+set(OpenEXR_COMPONENTS
+    OpenEXR::OpenEXRConfig
+    OpenEXR::IexConfig
+    OpenEXR::IlmThreadConfig
+    OpenEXR::Iex
+    OpenEXR::IlmThread
+    OpenEXR::OpenEXRCore
+    OpenEXR::OpenEXRUtil
+    OpenEXR::OpenEXR
+)
+
+foreach(component ${OpenEXR_COMPONENTS})
+    if(TARGET ${component})
+        # convert the includes to system includes
+        get_target_property(system_includes ${component} INTERFACE_INCLUDE_DIRECTORIES)
+        set_target_properties(${component} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") # Clear it in case someone refers to it
+        
+        if (COMMAND ly_target_include_system_directories)
+            ly_target_include_system_directories(TARGET ${component} INTERFACE ${system_includes})
+        else()
+            target_include_directories(${component} SYSTEM INTERFACE ${system_includes})
+        endif()
+
+        # Alias the target with 3rdParty prefix
+        add_library(3rdParty::${component} ALIAS ${component})
+
+        # inside the loop where it sets the system includes for each component
+        foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES)
+            string(TOUPPER ${conf} UCONF)
+            if (${UCONF} STREQUAL "DEBUG" AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows)
+                set_target_properties(${component} PROPERTIES 
+                                        MAP_IMPORTED_CONFIG_${UCONF} DEBUG)
+            else()
+                set_target_properties(${component} PROPERTIES 
+                                        MAP_IMPORTED_CONFIG_${UCONF} RELEASE)
+            endif()
+        endforeach()
+    else()
+        message(WARNING "Target not found in OpenEXR: ${component}")
+    endif()
+endforeach()
 
 
 # read the existing config files that OpenEXR made when it compiled:
 # read the existing config files that OpenEXR made when it compiled:
 o3de_import_existing_config_files(OpenEXR ${CMAKE_CURRENT_LIST_DIR}/OpenEXR/lib/cmake)
 o3de_import_existing_config_files(OpenEXR ${CMAKE_CURRENT_LIST_DIR}/OpenEXR/lib/cmake)

+ 6 - 0
package-system/openimageio-opencolorio/LICENSE.TXT

@@ -0,0 +1,6 @@
+Copyright (c) Contributors to the Open 3D Engine Project.
+SPDX-License-Identifier: Apache-2.0 OR MIT
+
+Licensed under the Apache License, Version 2.0 (the "License");
+You may obtain a copy of the License at
+     http://www.apache.org/licenses/LICENSE-2.0

+ 557 - 0
package-system/openimageio-opencolorio/build_openimageio.py

@@ -0,0 +1,557 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+'''
+Builds a version of OpenImageIO and OpenColorIO that include python bindings.
+The two libraries (OpenImageIO and OpenColorIO, aka oiio and ocio) are inter-dependent on each other
+so need to be built in a special sequence, some modules from each first, then some more modules from
+each after that.
+
+Notably, this script will build and fetch dependencies as needed, but is stricly limited to the
+supported set that works for Open 3D Engine.  
+
+Notably, the following features are DISABLED and will n ot be present:
+ - Camera RAW support
+ - The image viewer application 'iv'
+ - Jpeg2000 support
+ - ffmpeg and any other potentially troublesome patent-laden components
+ - OpenCV
+ - WebP
+ - OpenVDB
+ - GIF
+ - HEIV/AVIF
+ - DICOM / DCMTK
+ - Ptex
+ - Field3D
+
+All of the above could get added support if necessary - it would involve updating the build
+script here to handle the dependent libs and also ensuring that their licenses are compatible and
+that there is no patent danger.
+'''
+
+import argparse
+import os
+import platform
+import subprocess
+import sys
+import pathlib
+import shutil
+from typing import final
+
+
+openimageio_repository_url = 'https://github.com/OpenImageIO/oiio.git'
+openimageio_repository_tag = 'v2.3.10.1'
+
+opencolorio_repository_url='https://github.com/AcademySoftwareFoundation/OpenColorIO.git'
+opencolorio_repository_tag='v2.1.0' # officially, oiio uses 'v2.0.1'
+
+boost_repository_url = 'https://github.com/boostorg/boost.git'
+boost_repository_tag = 'boost-1.76.0' 
+
+libjpegturbo_repository_url ='https://github.com/libjpeg-turbo/libjpeg-turbo.git'
+libjpegturbo_repository_tag = '2.1.2'
+
+temp_folder_name = 'temp'
+source_folder_name = 'src'
+build_folder_name = 'bld'
+
+# the following are used for debugging and skip steps.
+# do not approve a pull request if they are not set to FALSE / None.
+SKIP_OPENCOLORIO = False
+SKIP_BOOST = False
+SKIP_LIBJPEGTURBO = False
+SKIP_OPENIMAGEIO = False
+SKIP_OPENCOLORIO_WITH_OPENIMAGEIO = False
+
+dependencies = {
+    # dependencies format:
+    # platformname : 
+    #          package_short_name : (packagename,  hashe)
+    'darwin' : 
+        {
+            'zlib' :     ('zlib-1.2.11-rev5-mac',              'b6fea9c79b8bf106d4703b67fecaa133f832ad28696c2ceef45fb5f20013c096'),
+            'openexr' :  ('OpenEXR-3.1.3-rev2-mac',            'af8163d3a92ebf8833ebf61589c5f82ba48d8b5fe42e55693ed6248e540609ef'),
+            'python' :   ('python-3.7.12-rev1-darwin',         'fb8292c0ec52cb66676eb14ce7989523ba4b973690319573e5eb78cf221dae4f'),
+            'tiff' :     ('tiff-4.2.0.15-rev3-mac',            'c2615ccdadcc0e1d6c5ed61e5965c4d3a82193d206591b79b805c3b3ff35a4bf'),
+            'libpng' :   ('png-1.6.37-rev1-mac',               '723c64763bed5f9946ed46f00cdc71acb6e6de5caffc6a07388c901c1921b782'),
+            'expat' :    ('expat-2.4.2-rev2-mac',              '70f195977a17b08a4dc8687400fd7f2589e3b414d4961b562129166965b6f658'),
+            'freetype' : ('freetype-2.11.1-rev1-mac',          'b66107d3499f2e9c072bd88db26e0e5c1b8013128699393c6a8495afca3d2548')
+        }
+}
+
+script_folder = pathlib.Path(__file__).parent.absolute()
+temp_folder_path = script_folder / temp_folder_name
+build_folder_path = temp_folder_path / build_folder_name
+source_folder_path = temp_folder_path / source_folder_name
+repo_root_path = script_folder.parent.parent
+general_scripts_path = repo_root_path / 'Scripts' / 'extras'
+dependencies_folder_path = (temp_folder_path / 'dependencies').absolute().resolve()
+ocio_install_path = temp_folder_path / 'ocio_install'
+boost_install_path = temp_folder_path / 'boost_install'
+oiio_install_path = temp_folder_path / 'oiio_install'
+libjpegturbo_install_path = temp_folder_path / 'libjpegturbo_install'
+final_package_image_root = temp_folder_path / 'package'
+
+sys.path.insert(1, str(general_scripts_path.absolute().resolve()) )
+
+from package_downloader import PackageDownloader
+
+def exec_and_exit_if_failed(invoke_params, cwd=script_folder, shell=False):
+    # thin wrapper around subprocess.run, 
+    # includes output tracing and also allows non-str params to be entered (such as pathlib)
+    # without issue.  Otherwise things like str.join may fail
+    invoke_params = [str(x) for x in invoke_params] 
+    cwd = str(cwd)
+    friendly_args = ' '.join(invoke_params)
+    print('Exec:')
+    print(f'   CMDLINE: {friendly_args}')
+    print(f'       CWD: {cwd}')
+    print(f'     SHELL: {shell}')
+    print('Output:')
+    result_value = subprocess.run(invoke_params, shell=shell, cwd=cwd)
+    if result_value.returncode != 0:
+        print(f"Exec: Failed with return code {result_value}")
+        sys.exit(0)
+    return result_value.returncode
+
+# only clones the repo if it doesn't exist.  Otherwise cleans it.
+def clone_repo(url, tag, dest_folder):
+    if pathlib.Path(dest_folder).exists():
+        print(f"Not re-cloning {url} to {dest_folder} becuase it already exists (use --clean to clean fully)")
+        exec_and_exit_if_failed(['git', 'clean', '-f'], cwd=dest_folder)
+        exec_and_exit_if_failed(['git', 'restore', '.'], cwd=dest_folder)
+    else:
+        exec_and_exit_if_failed(['git', 'clone', '--depth=1', '--single-branch', '--depth=1', '--recursive',
+              '-b', tag,   
+              url,
+              dest_folder
+              ])
+
+    exec_and_exit_if_failed(['git', 'submodule', 'update', '--init', '--recursive'], cwd=dest_folder)
+
+def get_dependencies(deps):
+    for dependency in deps:
+        packagename, hash = deps[dependency]
+        if not (dependencies_folder_path / packagename).exists():
+            if not PackageDownloader.DownloadAndUnpackPackage(packagename, hash, str(dependencies_folder_path)):
+                raise Exception("Failed to build!")
+        else:
+            print(f'{packagename} already in dependencies folder, skipping. Use --clean to refresh')
+
+def get_dependency_path(platform, depname):
+    dependencies_package_name = dependencies[platform][depname][0]
+    return (dependencies_folder_path / dependencies_package_name).absolute().resolve()
+
+# ------------------------------------ MAIN SCRIPT STARTS HERE ----------------------------------------------
+
+parser = argparse.ArgumentParser(description='Builds this package')
+parser.add_argument('--platform', default=platform.system().lower(), required=False, help=f'Platform to build (defaults to \"{platform.system().lower()}\")')
+parser.add_argument('--clean',    default=False,                     required=False, help=f'Complete clean build, if true, will delete entire temp and refetch dependencies')
+
+args = parser.parse_args()
+if args.platform not in dependencies.keys():
+    print(f"Platform {args.platform} not in the list of supported dependency platforms {dependencies.keys()}")
+    sys.exit(1)
+
+
+# similar to CMAKE, we define these as blank or filled depending on platform.
+lib_prefix = ''
+if args.platform.lower() == 'windows':
+    lib_suffix = '.lib'
+else:
+    lib_suffix = '.a'
+    lib_prefix = 'lib'
+
+
+print(f"OpenImageIO / OpenColorIO Build Script")
+print(f"Script folder : {script_folder.relative_to(repo_root_path)}")
+print(f"Temp folder   : {temp_folder_path.relative_to(repo_root_path)}")
+print(f"Build folder  : {build_folder_path.relative_to(repo_root_path)}")
+print(f"Source folder : {source_folder_path.relative_to(repo_root_path)}")
+print(f"Dependencies  : {dependencies_folder_path.relative_to(repo_root_path)}")
+print(f"Platform      : {args.platform}")
+print(f"ocio install  : {ocio_install_path}")
+print(f"boost install : {boost_install_path}")
+print(f"oiio install  : {oiio_install_path}")
+print(f"jpg install   : {libjpegturbo_install_path}")
+print(f"final package : {final_package_image_root}")
+
+print("\n---------------------------------- CLEANING ----------------------------------")
+
+if args.clean:
+    if temp_folder_path.exists():
+        print(f'\n--clean specified on command line - removing entire temp folder: {temp_folder_path}...')
+        shutil.rmtree(str(temp_folder_path.resolve()), ignore_errors=True)
+else:
+    print('\n--clean not specified on the command line.\nWill only clean build folders, not source or installs')
+
+os.makedirs(str(temp_folder_path), exist_ok=True)
+os.makedirs(str(build_folder_path), exist_ok=True)
+os.makedirs(str(source_folder_path), exist_ok=True)
+
+print("\n----------------------------- FETCH Dependencies -----------------------------")
+get_dependencies(dependencies[args.platform])
+
+# we can re-use this path string (semicolon seperated list of folders) for all finds.
+module_path_string = ';'.join( [ 
+        f'{get_dependency_path(args.platform, "openexr")}',
+        f'{get_dependency_path(args.platform, "expat")}',
+        f'{get_dependency_path(args.platform, "zlib")}',
+        f'{get_dependency_path(args.platform, "tiff")}',
+        f'{get_dependency_path(args.platform, "libpng")}',
+        f'{get_dependency_path(args.platform, "freetype")}',
+        # add a custom path for our custom find modules:
+])
+
+# building opencolorIO is a function becuase we call it twice
+# once before we have OpenImageIO built, and once again with that dependency ready
+def BuildOpenColorIO(module_paths_to_use):
+    clone_repo(opencolorio_repository_url, opencolorio_repository_tag, source_folder_path / 'opencolorio')
+    opencolorio_build_folder = build_folder_path / 'opencolorio_build'
+
+    if opencolorio_build_folder.exists():
+        shutil.rmtree(str(opencolorio_build_folder.resolve()), ignore_errors=True)
+
+    opencolorio_configure_command = [ 
+                'cmake',
+                '-G', 'Ninja',
+                f'-S',
+                f'{source_folder_path / "opencolorio"}',
+                f'-B',
+                f'{opencolorio_build_folder}',
+                f'-Dexpat_STATIC_LIBRARY=ON',
+                f'-DCMAKE_INSTALL_PREFIX={ocio_install_path}',
+                f'-DCMAKE_TOOLCHAIN_FILE={repo_root_path / "Scripts/cmake/Platform/Mac/Toolchain_mac.cmake"}',
+                f'-DCMAKE_BUILD_TYPE=Release',
+                f'-DBUILD_SHARED_LIBS=OFF',
+                f'-DCMAKE_CXX_STANDARD=17',
+                f'-DOCIO_BUILD_APPS=ON',
+                f'-DOCIO_BUILD_OPENFX=OFF',
+                f'-DOCIO_BUILD_TESTS=OFF',
+                f'-DOCIO_BUILD_GPU_TESTS=OFF',
+                f'-DOCIO_BUILD_PYTHON=ON',
+                f'-DCMAKE_CXX_VISIBILITY_PRESET=hidden',
+                f'-DOCIO_BUILD_DOCS=OFF',   # <---- TODO: we have to fix this maybe
+                f'-DPython_ROOT={get_dependency_path(args.platform, "python") / "Python.framework/Versions/3.7"}',
+                f'-DPython_EXECUTABLE={get_dependency_path(args.platform, "python") / "Python.framework/Versions/3.7/bin/Python3"}',
+                f'-DCMAKE_MODULE_PATH={module_paths_to_use}',
+                
+    ]
+    exec_and_exit_if_failed(opencolorio_configure_command)
+
+    opencolorio_build_command = [
+        f'cmake',
+        f'--build',
+        f'{opencolorio_build_folder}',
+        f'--parallel',
+        f'--config',
+        f'Release',
+        f'--target',
+        f'install'
+    ]
+    exec_and_exit_if_failed(opencolorio_build_command)
+
+    # opencolorio built statically only installs its own files, none of its dependencies
+    # we need to actually also deploy its dependencies, namely
+    # pystring::pystring
+    # yaml-cpp (note, no namespace!)
+
+    ocio_private_library_build_path = build_folder_path / 'opencolorio_build' / 'ext' / 'dist' / 'lib'
+    ocio_private_libary_source_path = build_folder_path / 'opencolorio_build' / 'ext' / 'build'
+    pystring_source_path =  ocio_private_libary_source_path / 'pystring' / 'src' / 'pystring_install'
+    yamlcpp_source_path =   ocio_private_libary_source_path / 'yaml-cpp' / 'src' / 'yaml-cpp_install'
+    pystring_install_path = temp_folder_path / 'pystring_install'
+    yamlcpp_install_path =  temp_folder_path / 'yaml-cpp_install'
+    os.makedirs(pystring_install_path / 'lib', exist_ok=True)
+    os.makedirs(yamlcpp_install_path  / 'lib', exist_ok=True)
+    shutil.copy2(ocio_private_library_build_path / f'{lib_prefix}pystring{lib_suffix}', pystring_install_path / 'lib' / f'{lib_prefix}pystring{lib_suffix}', follow_symlinks=False)
+    shutil.copy2(ocio_private_library_build_path / f'{lib_prefix}yaml-cpp{lib_suffix}', yamlcpp_install_path /  'lib' / f'{lib_prefix}yaml-cpp{lib_suffix}', follow_symlinks=False)
+    shutil.copy2(pystring_source_path / 'LICENSE', pystring_install_path / 'LICENSE', follow_symlinks=False)
+    shutil.copy2(yamlcpp_source_path  / 'LICENSE', yamlcpp_install_path  / 'LICENSE', follow_symlinks=False)
+
+if not SKIP_OPENCOLORIO:
+    print("\n----------------------------- BUILD OpenColorIO ------------------------------")
+    
+    BuildOpenColorIO(module_path_string)
+# the final install of OpenColorIO looks like this
+# (install folder)
+#       - bin
+#          (various programs)
+#       - lib
+#           - cmake
+#               (the cmake files that define the target)
+#           - pkgconfig
+#           - python3.7/site-packages
+#                 - PyOpenColorIO.so
+#           libOpenColorIO.a
+#           libOpenColorIOoglapphelpers.a
+#           libpystring.a
+#           libyaml-cpp.a
+
+# now that we have openColorIO we can make openImageIO which uses it
+# then we can circle back into openColorIO and make any apps it was missing.
+if not SKIP_BOOST:
+    print("\n-------------------------------- BUILD BOOST ---------------------------------")
+
+    boost_build_folder = build_folder_path / 'boost'
+    if boost_build_folder.exists():
+        shutil.rmtree(str(boost_build_folder.resolve()), ignore_errors=True)
+
+    clone_repo(boost_repository_url, boost_repository_tag, source_folder_path / 'boost')
+
+    exec_and_exit_if_failed(['./bootstrap.sh --with-libraries=filesystem,atomic,thread,system,headers,date_time,chrono'], 
+                            cwd=source_folder_path / 'boost', shell=True)
+
+    boost_build_command = ['./b2',
+                            f'--build-dir={boost_build_folder}',
+                            f'link=static', 
+                            f'threading=multi', 
+                            f'--prefix={boost_install_path}', 
+                            f'release',
+                            f'install',
+                            f'visibility=hidden',
+                            f'-j', '12']
+    
+    # on non-windows, make sure that the same visibility is set for building the library
+    # as will be likely set for applications where it is used as a dependency.
+    if sys.platform.lower() != 'windows':
+        print("(Using hidden visibility by default)")
+        boost_build_command.append('cxxflags=-fvisibility=hidden')
+        boost_build_command.append('cxxflags=-fvisibility-inlines-hidden')
+
+    exec_and_exit_if_failed(boost_build_command, cwd=source_folder_path / 'boost')
+
+    # boost is now built, and lives in temp/bld/boost/output (which contains the usual lib, include, etc)
+
+if not SKIP_LIBJPEGTURBO:
+    print("\n---------------------------- BUILD libJPEGTurbo ------------------------------")
+    clone_repo(libjpegturbo_repository_url, libjpegturbo_repository_tag, source_folder_path / 'libjpegturbo')
+    
+    libjpegturbo_build_path = build_folder_path / 'libjpegturbo_build'
+    if libjpegturbo_build_path.exists():
+        shutil.rmtree(str(libjpegturbo_build_path.resolve()), ignore_errors=True)
+
+    libjpegturbo_configure_command = [ 
+        'cmake',
+        '-G', 'Ninja',
+        f'-S',
+        f'{source_folder_path / "libjpegturbo"}',
+        f'-B',
+        libjpegturbo_build_path,
+        f'-DCMAKE_INSTALL_PREFIX={libjpegturbo_install_path}',
+        f'-DCMAKE_TOOLCHAIN_FILE={repo_root_path / "Scripts/cmake/Platform/Mac/Toolchain_mac.cmake"}',
+        f'-DCMAKE_BUILD_TYPE=Release',
+        f'-DBUILD_SHARED_LIBS=OFF',
+        f'-DENABLE_SHARED=OFF',
+        f'-DWITH_JAVA=0',
+        f'-DCMAKE_POSITION_INDEPENDENT_CODE=ON',
+        f'-DCMAKE_CXX_STANDARD=17',
+        f'-DPYTHON_VERSION=3.7.12',
+        f'-DCMAKE_CXX_VISIBILITY_PRESET=hidden',
+        f'-DCMAKE_MODULE_PATH={module_path_string}'
+    ]
+
+    exec_and_exit_if_failed(libjpegturbo_configure_command)
+
+    libjpegturbo_build_command = [
+        f'cmake',
+        f'--build',
+        libjpegturbo_build_path,
+        f'--parallel',
+        f'--config',
+        f'Release',
+        f'--target',
+        f'install'
+    ]
+
+    exec_and_exit_if_failed(libjpegturbo_build_command)
+
+# add our custom find files here, not earlier - we only want to use these custom find files
+# in compiling OpenImageIO and etc.
+module_path_string_with_custom_find_files = module_path_string + f';{script_folder / "custom_find_files"}'
+
+if not SKIP_OPENIMAGEIO:
+    print("\n----------------------------- BUILD OpenImageIO ------------------------------")
+
+    clone_repo(openimageio_repository_url, openimageio_repository_tag, source_folder_path / 'openimageio')
+    
+    openimageio_build_folder = build_folder_path / 'openimageio_build'
+    if openimageio_build_folder.exists():
+        shutil.rmtree(str(openimageio_build_folder.resolve()), ignore_errors=True)
+
+    # openimageio looks for OPenColorIO in a way that is not compatible with generated configs.
+    # remove its find file, allow it to just use the OpenColorIO_ROOT:
+    os.remove(source_folder_path / 'openimageio' / 'src' / 'cmake' / 'modules' / 'FindOpenColorIO.cmake' )
+ 
+    # note that we have to clear the install folder for this to actually work as 
+    # otherwise it might try to add RPATHS to existing files.
+    shutil.rmtree(oiio_install_path, ignore_errors=True)
+
+    openimageio_configure_command = [ 
+        'cmake',
+        '-G', 'Ninja',
+        f'-S',
+        f'{source_folder_path / "openimageio"}',
+        f'-B',
+        openimageio_build_folder,
+        f'-DUSE_PYTHON=ON',
+        f'-DBoost_ROOT={boost_install_path}',
+        f'-Dpybind11_ROOT={temp_folder_path / "bld/opencolorio_build/ext/dist"}',  #use pybind from the opencolorio build
+        f'-DJPEGTurbo_ROOT={libjpegturbo_install_path}',
+        f'-DCMAKE_INSTALL_PREFIX={oiio_install_path}',
+        f'-DCMAKE_TOOLCHAIN_FILE={repo_root_path / "Scripts/cmake/Platform/Mac/Toolchain_mac.cmake"}',
+        f'-DPNG_ROOT={get_dependency_path(args.platform, "libpng") / "libpng"}',
+        f'-DCMAKE_BUILD_TYPE=Release',
+        f'-DBUILD_SHARED_LIBS=OFF',
+        f'-DCMAKE_CXX_STANDARD=17',
+        f'-DPYTHON_VERSION=3.7.12',
+        f'-DOIIO_BUILD_TESTS=OFF',
+        f'-DLINKSTATIC=ON',
+        f'-DCMAKE_CXX_VISIBILITY_PRESET=hidden',
+        f'-DUSE_OpenGL=OFF',
+        f'-DUSE_Qt5=OFF',
+        f'-DUSE_BZip2=OFF',
+        f'-DPython_ROOT={get_dependency_path(args.platform, "python") / "Python.framework/Versions/3.7"}',
+        f'-DPython_EXECUTABLE={get_dependency_path(args.platform, "python") / "Python.framework/Versions/3.7/bin/Python3"}',
+        f'-DCMAKE_MODULE_PATH={module_path_string_with_custom_find_files}',
+        f'-DVERBOSE=ON' # reveals problems with library inclusion
+    ]
+
+    exec_and_exit_if_failed(openimageio_configure_command)
+
+    openimageio_build_command = [
+            f'cmake',
+            f'--build',
+            openimageio_build_folder,
+            f'--parallel',
+            f'--config',
+            f'Release',
+            f'--target',
+            f'install'
+        ]
+
+    exec_and_exit_if_failed(openimageio_build_command)
+
+# ----------------- BUILD OpenColorIO again but this time with OpenImageIO support ----------------
+if not SKIP_OPENCOLORIO_WITH_OPENIMAGEIO:
+    print("\n------------------ BUILD OpenColorIO with OpenImageIO support ----------------")
+    BuildOpenColorIO(module_path_string_with_custom_find_files)
+# -------------------------------- Make final installation image --------------------------------------
+# note that we will have to include static libs for things like boost, other deps.
+# and make a FIND FILE that declares openimageio depending on opencolorio
+# as well as on the various 3p libs that it requires.
+
+print("\n------------------------- Create final package image -------------------------")
+
+private_deps_folder = final_package_image_root / 'privatedeps'
+print("Cleaning previous package folder...")
+shutil.rmtree(final_package_image_root, ignore_errors=True)
+os.makedirs(final_package_image_root, exist_ok=True)
+os.makedirs(private_deps_folder, exist_ok=True)
+
+print("Copying OpenImageIO")
+shutil.copytree(src=oiio_install_path, dst=final_package_image_root / 'OpenImageIO')
+shutil.copy2(src=script_folder / 'distribution' / 'FindOpenImageIO.cmake', dst=final_package_image_root / 'FindOpenImageIO.cmake')
+
+print("Copying OpenColorIO")
+shutil.copytree(src=ocio_install_path, dst=final_package_image_root / 'OpenColorIO')
+shutil.copy2(src=script_folder / 'distribution' / 'FindOpenColorIO.cmake', dst=final_package_image_root / 'FindOpenColorIO.cmake')
+
+# the following are considered private dependencies, do not depend on them!
+print("Copying LibJPEGTurbo")
+shutil.copytree(src=libjpegturbo_install_path, dst=private_deps_folder / 'LibJPEGTurbo')
+print("Copying Boost")
+shutil.copytree(src=boost_install_path, dst=private_deps_folder / 'Boost')
+print("Copying pystring")
+shutil.copytree(src=temp_folder_path / 'pystring_install', dst=private_deps_folder / 'pystring')
+print("Copying yaml-cpp")
+shutil.copytree(src=temp_folder_path / 'yaml-cpp_install', dst=private_deps_folder / 'yaml-cpp')
+
+print("Cleaning unnecessary/private files")
+# we don't actually want to expose this copy of boost as being something people can use
+# and the OpenImageIO library doesn't expose any boost usage in its public API, so we can remove all the headers.
+# note that we delete the cmake and pkgconfig files since they contain absolute paths to the machine
+# that they were built on, and won't be useful anyway
+shutil.rmtree(path=private_deps_folder / 'Boost' / 'include')
+shutil.rmtree(path=private_deps_folder / 'Boost' / 'lib' / 'cmake')
+shutil.rmtree(path=private_deps_folder / 'LibJPEGTurbo' / 'include')
+shutil.rmtree(path=private_deps_folder / 'LibJPEGTurbo' / 'bin')
+shutil.rmtree(path=private_deps_folder / 'LibJPEGTurbo' / 'lib' / 'cmake')
+shutil.rmtree(path=private_deps_folder / 'LibJPEGTurbo' / 'lib' / 'pkgconfig')
+shutil.rmtree(path=final_package_image_root / 'OpenColorIO' / 'lib' / 'pkgconfig')
+shutil.rmtree(path=final_package_image_root / 'OpenColorIO' / 'lib' / 'cmake')
+shutil.rmtree(path=final_package_image_root / 'OpenColorIO' / 'share')
+
+shutil.rmtree(path=final_package_image_root / 'OpenImageIO' / 'lib' / 'pkgconfig')
+shutil.rmtree(path=final_package_image_root / 'OpenImageIO' / 'lib' / 'cmake')
+
+print("Copying License and package files")
+shutil.copy2(src=script_folder / 'distribution' / 'PackageInfo.json', dst=final_package_image_root / 'PackageInfo.json')
+shutil.copy2(src=script_folder / 'distribution' / 'LICENSE.TXT', dst=final_package_image_root / 'LICENSE.TXT')
+# note that we're copying the distribution license, ie, the one that goes with the package, not the
+# license thats in THIS repo, to the root of the built package.
+# we also have to include other license files when the install step for the package doesn't do it themselves
+shutil.copy2(src=source_folder_path / 'opencolorio' / 'LICENSE', dst=final_package_image_root / 'OpenColorIO' / 'LICENSE')
+shutil.copy2(src=source_folder_path / 'opencolorio' / 'THIRD-PARTY.md', dst=final_package_image_root / 'OpenColorIO' / 'THIRD-PARTY.md')
+shutil.copy2(src=source_folder_path / 'boost' / 'LICENSE_1_0.txt', dst=private_deps_folder / 'Boost' / 'LICENSE_1_0.txt')
+shutil.copy2(src=source_folder_path / 'boost' / 'README.md', dst=private_deps_folder / 'Boost' / 'README.md')
+shutil.copy2(src=private_deps_folder / 'LibJPEGTurbo' / 'share' / 'doc' / 'libjpeg-turbo' / 'LICENSE.md', dst=private_deps_folder / 'LibJPEGTurbo' / 'LICENSE.md')
+
+print("\n----------------------------- Test package image -----------------------------")
+    
+module_path_string_with_package_folder = module_path_string + f';{final_package_image_root}'
+
+test_build_folder = build_folder_path / 'test_openimageio'
+
+if test_build_folder.exists():
+    shutil.rmtree(str(test_build_folder.resolve()), ignore_errors=True)
+
+test_configure_command = [ 
+    'cmake',
+    '-G', 'Ninja',
+    f'-S',
+    f'{script_folder / "test"}',
+    f'-B',
+    test_build_folder,
+    f'-DCMAKE_TOOLCHAIN_FILE={repo_root_path / "Scripts/cmake/Platform/Mac/Toolchain_mac.cmake"}',
+    f'-DCMAKE_BUILD_TYPE=Release',
+    f'-DCMAKE_CXX_STANDARD=17',
+    f'-DCMAKE_CXX_VISIBILITY_PRESET=hidden',
+    f'-DCMAKE_MODULE_PATH={module_path_string_with_package_folder}',
+]
+
+exec_and_exit_if_failed(test_configure_command)
+
+test_build_command = [
+        f'cmake',
+        f'--build',
+        test_build_folder,
+        f'--parallel',
+        f'--config',
+        f'Release',
+    ]
+
+exec_and_exit_if_failed(test_build_command)
+
+test_executable_path = ''
+if platform.system().lower() == 'darwin':
+    test_executable_path = test_build_folder / 'test_OpenImageIO.app' / 'Contents' / 'MacOS' / 'test_OpenImageIO'
+
+
+test_exec_command = [
+    test_executable_path
+]
+
+exec_and_exit_if_failed(test_exec_command, cwd=script_folder / 'test')
+
+print(f"Build and test complete!  Folder image created in {final_package_image_root}")
+
+# TODO:  Add a test for opencolorio to prove it works without other deps.
+# TODO:  Figure out how the deployment of Python PYDs work (mac, linux, windows)

+ 52 - 0
package-system/openimageio-opencolorio/custom_find_files/FindOpenColorIO.cmake

@@ -0,0 +1,52 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+# we build OpenColorIO statically.  This also means that all its dependencies
+# are built statically, which means that if you want to link to OpenColorIO, you will need those
+# dependencies too.   Unfortunately, OpenColorIO's install script and its own generated target
+# files do not declare these dependencies.   This file "patches" that by providing both OpenColorIO
+# and its dependencies.
+
+# this is only for use during building of OpenImageIO.
+# it assumes that there is an OpenColorIO 'install' folder relative to this one.
+
+# a useful message since it MUST APPEAR if this is working
+message(STATUS "Using the internal FindOpenColorIO.cmake build file")
+
+# where opencolorio itself was installed
+set(PYSTRING_INSTALL_PATH ${CMAKE_CURRENT_LIST_DIR}/../temp/pystring_install)
+set(YAMLCPP_INSTALL_PATH ${CMAKE_CURRENT_LIST_DIR}/../temp/yaml-cpp_install)
+set(OPENCOLORIO_INSTALL_PATH ${CMAKE_CURRENT_LIST_DIR}/../temp/ocio_install)
+set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${OPENCOLORIO_INSTALL_PATH}/lib/cmake")
+# bring in OpenColorIO itself, using the above CMAKE_PREFIX_PATH
+find_package(OpenColorIO CONFIG REQUIRED)
+
+# declare its dependencies, too.  Specifically, If you depend on OpenColorIO you also need
+# pystring::pystring
+# sampleicc::sampleicc
+# utils::strings
+# yaml-cpp (note, no namespace!)
+
+# sampleicc and utils::strings are set as deps but only need to exist to satisfy cmake:
+add_library(sampleicc::sampleicc INTERFACE IMPORTED GLOBAL)
+add_library(utils::strings INTERFACE IMPORTED GLOBAL)
+
+# the following is expected to pick up O3DE's expat.
+find_package(expat 2.2.8 REQUIRED)
+
+# pystring::pystring - use the one built by OpenColorIO
+find_library(pystring_LIBRARY NAMES pystring libpystring HINTS ${PYSTRING_INSTALL_PATH} PATH_SUFFIXES lib64 lib)
+add_library(pystring::pystring UNKNOWN IMPORTED GLOBAL)
+set_target_properties(pystring::pystring PROPERTIES IMPORTED_LOCATION ${pystring_LIBRARY}
+)
+
+# yaml-cpp - use the one built by OpenColorIO
+find_library(yaml_cpp_LIBRARY NAMES libyaml-cpp yaml-cpp HINTS ${YAMLCPP_INSTALL_PATH} PATH_SUFFIXES lib64 lib)
+add_library(yaml-cpp UNKNOWN IMPORTED GLOBAL)
+set_target_properties(yaml-cpp PROPERTIES IMPORTED_LOCATION ${yaml_cpp_LIBRARY}
+)

+ 32 - 0
package-system/openimageio-opencolorio/custom_find_files/FindOpenImageIO.cmake

@@ -0,0 +1,32 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+# we build OpenImageIO statically.  This also means that all its dependencies
+# are built statically, which means that if you want to link to OpenImageIO, you will need those
+# dependencies too.   Unfortunately, OpenImageIO's install script and its own generated target
+# files do not deploy these dependencies to install folder.
+#   This file "patches" that by providing both OpenImageIO and its dependencies as targets.
+
+# a useful message since it MUST APPEAR if this is working
+message(STATUS "Using the internal FindOpenImageIO.cmake build file")
+
+find_package(ZLIB MODULE REQUIRED)
+find_package(OpenEXR MODULE REQUIRED)
+# PNG::PNG - use the one from O3DE 3p
+find_library(png_LIBRARY NAMES png libpng HINTS ${CMAKE_CURRENT_LIST_DIR}/../temp/dependencies/libpng-1.6.37-mac/libpng PATH_SUFFIXES lib64 lib)
+add_library(PNG::PNG UNKNOWN IMPORTED GLOBAL)
+set_target_properties(PNG::PNG PROPERTIES IMPORTED_LOCATION ${png_LIBRARY}
+)
+# where opencolorio itself was installed
+set(OPENIMAGEIO_INSTALL_DIR ${CMAKE_CURRENT_LIST_DIR}/../temp/oiio_install)
+
+set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${OPENIMAGEIO_INSTALL_DIR}/lib/cmake")
+# bring in OpenColorIO itself, using the above CMAKE_PREFIX_PATH
+find_package(OpenImageIO CONFIG REQUIRED)
+
+

+ 58 - 0
package-system/openimageio-opencolorio/distribution/FindOpenColorIO.cmake

@@ -0,0 +1,58 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+if (TARGET 3rdParty::OpenColorIO)
+    return()
+endif()
+
+if (NOT TARGET Imath::Imath)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(Imath)
+    endif()
+    find_package(Imath REQUIRED MODULE)
+endif()
+
+set(OpenColorIO_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenColorIO/include)
+set(OpenColorIO_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenColorIO/lib)
+set(OpenColorIO_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenColorIO/bin)
+set(OpenColorIO_FOUND True)
+set(OpenColorIO_VERSION "2.1.0")
+
+add_library(OpenColorIO::OpenColorIO STATIC IMPORTED GLOBAL)
+set_target_properties(OpenColorIO::OpenColorIO PROPERTIES 
+    IMPORTED_LOCATION ${OpenColorIO_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}OpenColorIO${CMAKE_STATIC_LIBRARY_SUFFIX}
+    INTERFACE_COMPILE_DEFINITIONS "OIIO_STATIC_DEFINE=1"
+)
+
+target_link_libraries(OpenColorIO::OpenColorIO INTERFACE 
+    Imath::Imath
+    # private dependencies that we intentionally DO NOT WANT to create friendly targets for:
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/pystring/lib/${CMAKE_STATIC_LIBRARY_PREFIX}pystring${CMAKE_STATIC_LIBRARY_SUFFIX}
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/yaml-cpp/lib/${CMAKE_STATIC_LIBRARY_PREFIX}yaml-cpp${CMAKE_STATIC_LIBRARY_SUFFIX}
+)
+
+if (COMMAND ly_target_include_system_directories)
+    # O3DE has an extension to fix system directory includes until CMake
+    # has a proper fix for it, so if its available, use that:
+    ly_target_include_system_directories(TARGET OpenColorIO::OpenColorIO INTERFACE ${OpenColorIO_INCLUDE_DIR})
+else()
+    # extension is not available (or not necessary anymore) 
+    # so use default CMake SYSTEM include feature:
+    target_include_directories(OpenColorIO::OpenColorIO SYSTEM INTERFACE ${OpenColorIO_INCLUDE_DIR})
+endif()
+
+# alias the OpenColorIO library to the O3DE 3rdParty library
+add_library(3rdParty::OpenColorIO ALIAS OpenColorIO::OpenColorIO)
+
+# if we're NOT in O3DE, it's also useful to show a message indicating that this
+# library was successfully picked up, as opposed to the system one.
+# A good way to know if you're in O3DE or not is that O3DE sets various cache variables before 
+# calling find_package, specifically, LY_VERSION_ENGINE_NAME is always set very early:
+if (NOT LY_VERSION_ENGINE_NAME)
+    message(STATUS "Using the O3DE versionof the OpenColorIO library ${OpenColorIO_VERSION} from ${CMAKE_CURRENT_LIST_DIR}")
+endif()

+ 137 - 0
package-system/openimageio-opencolorio/distribution/FindOpenImageIO.cmake

@@ -0,0 +1,137 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+# this file actually ingests the library and defines targets.
+if (TARGET 3rdParty::OpenImageIO)
+    return()
+endif()
+
+# OpenImageIO depends on OpenColorIO.  This package includes it!
+find_package(OpenColorIO)
+
+if (NOT TARGET ZLIB::ZLIB)
+    if (COMMAND ly_download_associated_package)
+        # if we happen to be inside O3DE we can use its package system to grab ZLIB.
+        ly_download_associated_package(ZLIB)
+    endif()
+    find_package(ZLIB)
+endif()
+
+# todo: FIX THIS
+if (NOT TARGET PNG::PNG)
+    set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}/../dependencies/libpng-1.6.37-mac/libpng;${CMAKE_PREFIX_PATH}")
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(PNG)
+    endif()
+    find_package(PNG MODULE)
+endif()
+
+if (NOT TARGET Imath::Imath)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(Imath)
+    endif()
+    find_package(Imath)
+endif()
+
+
+if (NOT TARGET Freetype::Freetype)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(Freetype)
+    endif()
+    find_package(Freetype)
+endif()
+
+if (NOT TARGET OpenEXR::OpenEXR)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(OpenEXR)
+    endif()
+    find_package(OpenEXR)
+endif()
+
+if (NOT TARGET TIFF::TIFF)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(TIFF)
+    endif()
+    find_package(TIFF)
+endif()
+
+
+if (NOT TARGET expat::expat)
+    if (COMMAND ly_download_associated_package)
+        ly_download_associated_package(expat)
+    endif()
+    find_package(expat)
+endif()
+
+find_package(expat)
+
+# the following block sets the variables that are expected
+# if you were to use the built-in CMake FindOpenImageIO.cmake
+set(OpenImageIO_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenImageIO/include)
+set(OpenImageIO_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenImageIO/lib)
+set(OpenImageIO_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}/OpenImageIO/bin)
+set(OpenImageIO_VERSION "4.2.0.15")
+set(OpenImageIO_FOUND True)
+
+add_library(OpenImageIO::OpenImageIO_Util STATIC IMPORTED GLOBAL)
+set_target_properties(OpenImageIO::OpenImageIO_Util PROPERTIES 
+    IMPORTED_LOCATION ${OpenImageIO_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}OpenImageIO_Util${CMAKE_STATIC_LIBRARY_SUFFIX})
+
+add_library(OpenImageIO::OpenImageIO STATIC IMPORTED GLOBAL)
+set_target_properties(OpenImageIO::OpenImageIO PROPERTIES
+    INTERFACE_COMPILE_DEFINITIONS "OIIO_STATIC_DEFINE=1"
+    IMPORTED_LOCATION ${OpenImageIO_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}OpenImageIO${CMAKE_STATIC_LIBRARY_SUFFIX})
+
+target_link_libraries(OpenImageIO::OpenImageIO INTERFACE 
+    expat::expat
+    OpenImageIO::OpenImageIO_Util
+    OpenColorIO::OpenColorIO
+    Imath::Imath
+    PNG::PNG
+    TIFF::TIFF
+    OpenEXR::OpenEXR
+    OpenEXR::OpenEXRCore
+    OpenEXR::OpenEXRUtil
+    ZLIB::ZLIB
+    Freetype::Freetype
+    # private dependencies that we intentionally DO NOT WANT to create friendly targets for:
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_atomic.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_chrono.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_date_time.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_filesystem.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_system.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/Boost/lib/libboost_thread.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/LibJPEGTurbo/lib/libturbojpeg.a
+    ${CMAKE_CURRENT_LIST_DIR}/privatedeps/LibJPEGTurbo/lib/libjpeg.a
+    "-framework Carbon"
+    "-framework IOKit"
+)
+
+if (COMMAND ly_target_include_system_directories)
+    # O3DE has an extension to fix system directory includes until CMake
+    # has a proper fix for it, so if its available, use that:
+    ly_target_include_system_directories(TARGET OpenImageIO::OpenImageIO INTERFACE ${OpenImageIO_INCLUDE_DIR})
+else()
+    # extension is not available (or not necessary anymore) 
+    # so use default CMake SYSTEM include feature:
+    target_include_directories(OpenImageIO::OpenImageIO SYSTEM INTERFACE ${OpenImageIO_INCLUDE_DIR})
+endif()
+
+# alias the OpenImageIO library to the O3DE 3rdParty library
+add_library(3rdParty::OpenImageIO ALIAS OpenImageIO::OpenImageIO)
+add_library(3rdParty::OpenImageIO_Util ALIAS OpenImageIO::OpenImageIO_Util)
+
+# if we're NOT in O3DE, it's also useful to show a message indicating that this
+# library was successfully picked up, as opposed to the system one.
+# A good way to know if you're in O3DE or not is that O3DE sets various cache variables before 
+# calling find_package, specifically, LY_VERSION_ENGINE_NAME is always set very early:
+if (NOT LY_VERSION_ENGINE_NAME)
+    message(STATUS "Using the O3DE version of the OpenImageIO library from ${CMAKE_CURRENT_LIST_DIR}")
+endif()
+
+# OpenImageIO Also includes a number of executables, as well as a python module.

+ 21 - 0
package-system/openimageio-opencolorio/distribution/LICENSE.TXT

@@ -0,0 +1,21 @@
+This package contains OpenImageIO, OpenColorIO, and other 3rd party dependencies.
+For full licensing and copyright information of these, see the following documents:
+
+OpenImageIO/share/doc/OpenImageIO/LICENSE.md
+OpenColorIO/LICENSE
+privatedeps/pystring/LICENSE
+privatedeps/yaml-cpp/LICENSE
+privatedeps/LibJPEGTurbo/share/doc/libjpeg-turbo/LICENSE.md
+privatedeps/Boost/LICENSE_1_0.txt
+
+OpenImageIO and OpenColorIO use several third party dependencies.  Please see the
+following documents for a description of them and their licensing:
+
+OpenImageIO/share/doc/OpenImageIO/THIRD-PARTY.md
+OpenColorIO/THIRD-PARTY.md
+
+In addition, OpenColorIO Also ships with a dependency on pystring and yaml-cpp
+
+
+OpenImageIO Also depends on boost and LibJPEGTurbo:
+

+ 6 - 0
package-system/openimageio-opencolorio/distribution/PackageInfo.json

@@ -0,0 +1,6 @@
+{
+    "PackageName" : "openimageio-opencolorio-4.2.0.15-mac",
+    "URL"         : "https://github.com/OpenImageIO/oiio and https://opencolorio.org/",
+    "License"     : "BSD-3-Clause",
+    "LicenseFile" : "LICENSE.TXT"
+}

+ 3 - 0
package-system/openimageio-opencolorio/distribution/README.md

@@ -0,0 +1,3 @@
+The files in this folder are added to the package being built.
+For example, the LICENSE.TXT file applies to the package that is built, not
+to this repo.  It is copied into the package as part of building it.

+ 11 - 0
package-system/openimageio-opencolorio/readme.md

@@ -0,0 +1,11 @@
+OpenImageIO and OpenColorIO
+
+These packages are lumped together because they are interdependent - to build a python-supported OpenColorIO 
+and OpenImageIO you need both of them already compiled and they have circular depdencies on each other.
+
+Thus, they are placed in the same package.  To build them we'll do the following
+1. build OpenImageIO without OpenColorIO or python
+2. build OpenColorIO without python
+3. (re)build OpenImageIO with python and OpenColorIO dependency
+4. (re)build OpenColorIO with python and OpenImageIO dependency
+5. Copy to temp dir and finish

+ 25 - 0
package-system/openimageio-opencolorio/test/CMakeLists.txt

@@ -0,0 +1,25 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+# 
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+cmake_minimum_required(VERSION 3.20)
+
+PROJECT(test_OpenImageIO VERSION 1.0 LANGUAGES C CXX)
+
+find_package(OpenImageIO)
+
+add_executable(test_OpenImageIO test_OpenImageIO.cpp)
+
+# note that we use 3rdParty::OpenEXR here.  This will ONLY work 
+# if the O3DE version of OpenEXR is used, which is what we are testing for.
+target_link_libraries(test_OpenImageIO PRIVATE 3rdParty::OpenImageIO)
+
+set_target_properties(test_OpenImageIO PROPERTIES
+                 XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED OFF
+                 MACOSX_BUNDLE TRUE
+                 XCODE_ATTRIBUTE_EXECUTABLE_NAME "test_OpenImageIO")
+

BIN
package-system/openimageio-opencolorio/test/base_Log2-48nits_16_LUT.exr


+ 62 - 0
package-system/openimageio-opencolorio/test/test_OpenImageIO.cpp

@@ -0,0 +1,62 @@
+/*
+ Copyright (c) Contributors to the Open 3D Engine Project.
+ For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ 
+ SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+// this is mainly to make sure linkage is ok!  Call some random function.
+#include <stdio.h>
+#include <vector>
+
+#include <OpenImageIO/imageio.h>
+#include <OpenImageIO/imagebufalgo.h>
+
+int main()
+{
+    using namespace OIIO;
+    printf("All is ok\n");
+    const char* filename = "base_Log2-48nits_16_LUT.exr";
+    auto inp = ImageInput::open(filename);
+    if (!inp)
+    {
+        printf("Was unable to read 48nits_16_LUT.exr\n");
+        return -1;
+    }
+    if (inp->has_error())
+    {
+        printf("Error during read of 48nits_16_LUT.exr\n");
+        return -1;
+    }
+
+    const ImageSpec &spec = inp->spec();
+    int xres = spec.width;
+    int yres = spec.height;
+    int channels = spec.nchannels;
+
+    printf("Name: %s\n", filename);
+    printf("xres: %i\n", xres);
+    printf("yres: %i\n", yres);
+    printf("channels: %i\n", channels);
+    printf("element type: %s\n", spec.format.c_str());
+
+    if ((xres != 256) || (yres != 16) || (channels != 3))
+    {
+        printf("Invalid data.  Expected 256, 16, 3");
+        return -1;
+    }
+
+    std::vector<unsigned char> pixels(xres * yres * channels);
+
+    // note that this not only reads the image but converts it to UINT8
+    if (!inp->read_image(0,0, 0, 0, TypeDesc::UINT8, &pixels[0]))
+    {
+        printf("Unable to read pixels from image.\n");
+        return -1;    
+    
+    }
+
+    inp->close();
+    return 0;
+
+}