diff --git a/.gitignore b/.gitignore
index 83fa3abba..c9779a32d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,4 +39,6 @@ session_manager.mu
# See maya_tools.mu.in
maya_tools.mu
# See rvnuke_mode.mu.in
-rvnuke_mode.mu
\ No newline at end of file
+rvnuke_mode.mu
+# see generate_about_rv.py
+about_rv.cpp
\ No newline at end of file
diff --git a/cmake/dependencies/glew.cmake b/cmake/dependencies/glew.cmake
index 97fef1f2a..32ea4b134 100644
--- a/cmake/dependencies/glew.cmake
+++ b/cmake/dependencies/glew.cmake
@@ -52,19 +52,12 @@ EXTERNALPROJECT_ADD(
URL_MD5 ${_download_hash}
DOWNLOAD_NAME ${_target}_${_version}.zip
DOWNLOAD_DIR ${RV_DEPS_DOWNLOAD_DIR}
- # Patch to fix the build issue with OpenGL-Registry
- # Pinning the OpenGL-Registry version to a specific commit
- # https://github.com/nigels-com/glew/issues/449
+ # Patch to fix the build issue with OpenGL-Registry Pinning the OpenGL-Registry version to a specific commit https://github.com/nigels-com/glew/issues/449
# Also clone the required glfixes repository
- PATCH_COMMAND
- cd auto &&
- git clone https://github.com/KhronosGroup/OpenGL-Registry.git || true &&
- cd OpenGL-Registry &&
- git checkout a77f5b6ffd0b0b74904f755ae977fa278eac4e95 &&
- cd .. &&
- git clone --depth=1 --branch glew https://github.com/nigels-com/glfixes glfixes || true &&
- touch OpenGL-Registry/.dummy &&
- cd ..
+ PATCH_COMMAND
+ cd auto && git clone https://github.com/KhronosGroup/OpenGL-Registry.git || true && cd OpenGL-Registry && git checkout
+ a77f5b6ffd0b0b74904f755ae977fa278eac4e95 && cd .. && git clone --depth=1 --branch glew https://github.com/nigels-com/glfixes glfixes || true && touch
+ OpenGL-Registry/.dummy && cd ..
CONFIGURE_COMMAND cd auto && ${_make_command} && cd .. && ${_make_command}
BUILD_COMMAND ${_make_command} -j${_cpu_count} GLEW_DEST=${_install_dir}
INSTALL_COMMAND ${_make_command} install LIBDIR=${_lib_dir} GLEW_DEST=${_install_dir}
diff --git a/cmake/dependencies/imgui.cmake b/cmake/dependencies/imgui.cmake
index fd55d2777..a97fd8d20 100644
--- a/cmake/dependencies/imgui.cmake
+++ b/cmake/dependencies/imgui.cmake
@@ -42,7 +42,7 @@ ENDIF()
IF(RV_TARGET_WINDOWS)
SET(_libpath
- ${_bin_dir}/${_libname}
+ ${_bin_dir}/${_libname}
)
ELSE()
SET(_libpath
@@ -103,20 +103,19 @@ EXTERNALPROJECT_ADD(
USES_TERMINAL_DOWNLOAD TRUE
)
-SET(_qt_location
- ${RV_DEPS_QT_LOCATION}
+SET(_qt_location
+ ${RV_DEPS_QT_LOCATION}
)
-SET(_find_qt_version
- "Qt${RV_DEPS_QT_MAJOR}"
+SET(_find_qt_version
+ "Qt${RV_DEPS_QT_MAJOR}"
)
IF(NOT _qt_location)
- SET(_qt_major
- ${RV_DEPS_QT_MAJOR}
+ SET(_qt_major
+ ${RV_DEPS_QT_MAJOR}
)
MESSAGE(FATAL_ERROR "Qt is not found in path \"${_qt_location}\". Please provide -DRV_DEPS_QT_LOCATION= to CMake.")
ENDIF()
-
SET(_patch_command_for_imgui
patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/imgui_cpp_h.patch
)
@@ -133,8 +132,8 @@ EXTERNALPROJECT_ADD(
${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/imgui/CMakeLists.txt ${CMAKE_BINARY_DIR}/${_target}/src/CMakeLists.txt && ${CMAKE_COMMAND} -E
copy_directory ${CMAKE_BINARY_DIR}/${_target}/deps/implot ${CMAKE_BINARY_DIR}/${_target}/src/implot && ${CMAKE_COMMAND} -E copy_directory
${CMAKE_BINARY_DIR}/${_target}/deps/imgui-backend-qt/backends ${CMAKE_BINARY_DIR}/${_target}/src/backends && ${CMAKE_COMMAND} -E copy_directory
- ${CMAKE_BINARY_DIR}/${_target}/deps/imgui-node-editor ${CMAKE_BINARY_DIR}/${_target}/src/imgui-node-editor
- && ${_patch_command_for_imgui_backend_qt} && ${_patch_command_for_imgui}
+ ${CMAKE_BINARY_DIR}/${_target}/deps/imgui-node-editor ${CMAKE_BINARY_DIR}/${_target}/src/imgui-node-editor && ${_patch_command_for_imgui_backend_qt} &&
+ ${_patch_command_for_imgui}
CONFIGURE_COMMAND ${CMAKE_COMMAND} ${_configure_options} -DFIND_QT_VERSION=${_find_qt_version} -DCMAKE_PREFIX_PATH=${_qt_location}/lib/cmake
BUILD_COMMAND ${_cmake_build_command}
INSTALL_COMMAND ${_cmake_install_command}
@@ -174,3 +173,9 @@ TARGET_INCLUDE_DIRECTORIES(
)
LIST(APPEND RV_DEPS_LIST imgui::imgui)
+
+# Set version for about dialog
+SET(RV_DEPS_IMGUI_VERSION
+ ${_version}
+ CACHE INTERNAL "" FORCE
+)
diff --git a/cmake/dependencies/python3.cmake b/cmake/dependencies/python3.cmake
index f3cb2e3c1..3c04c2b08 100644
--- a/cmake/dependencies/python3.cmake
+++ b/cmake/dependencies/python3.cmake
@@ -13,34 +13,32 @@ SET(_opentimelineio_target
)
SET(_pyside_target
- "${RV_DEPS_PYSIDE_TARGET}"
+ "${RV_DEPS_PYSIDE_TARGET}"
)
SET(_python3_version
"${RV_DEPS_PYTHON_VERSION}"
)
-string(REPLACE "." ";" _python_version_list "${_python3_version}")
-
-list(GET _python_version_list 0 PYTHON_VERSION_MAJOR)
-list(GET _python_version_list 1 PYTHON_VERSION_MINOR)
-list(GET _python_version_list 2 PYTHON_VERSION_PATCH)
+STRING(REPLACE "." ";" _python_version_list "${_python3_version}")
+LIST(GET _python_version_list 0 PYTHON_VERSION_MAJOR)
+LIST(GET _python_version_list 1 PYTHON_VERSION_MINOR)
+LIST(GET _python_version_list 2 PYTHON_VERSION_PATCH)
SET(RV_DEPS_PYTHON_VERSION_SHORT
"${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}"
)
-# This version is used for generating src/build/requirements.txt from requirements.txt.in template
-# All platforms install OpenTimelineIO from git to ensure consistent source builds.
+# This version is used for generating src/build/requirements.txt from requirements.txt.in template All platforms install OpenTimelineIO from git to ensure
+# consistent source builds.
SET(_opentimelineio_version
"${RV_DEPS_OTIO_VERSION}"
)
-SET(_pyside_version
+SET(_pyside_version
"${RV_DEPS_PYSIDE_VERSION}"
)
-# Construct the full git URL for pip to use in requirements.txt
-# Using this avoids @ symbol conflicts in CONFIGURE_FILE
+# Construct the full git URL for pip to use in requirements.txt Using this avoids @ symbol conflicts in CONFIGURE_FILE
SET(_opentimelineio_pip_url
"git+https://github.com/AcademySoftwareFoundation/OpenTimelineIO@v${_opentimelineio_version}#egg=OpenTimelineIO"
)
@@ -49,7 +47,7 @@ SET(_python3_download_url
"https://github.com/python/cpython/archive/refs/tags/v${_python3_version}.zip"
)
-SET(_python3_download_hash
+SET(_python3_download_hash
"${RV_DEPS_PYTHON_DOWNLOAD_HASH}"
)
@@ -62,11 +60,11 @@ SET(_opentimelineio_git_tag
)
SET(_pyside_archive_url
- "${RV_DEPS_PYSIDE_ARCHIVE_URL}"
+ "${RV_DEPS_PYSIDE_ARCHIVE_URL}"
)
-SET(_pyside_download_hash
- "${RV_DEPS_PYSIDE_DOWNLOAD_HASH}"
+SET(_pyside_download_hash
+ "${RV_DEPS_PYSIDE_DOWNLOAD_HASH}"
)
SET(_install_dir
@@ -79,8 +77,8 @@ SET(_build_dir
${RV_DEPS_BASE_DIR}/${_python3_target}/build
)
-# Note: OpenTimelineIO is now installed via requirements.txt from git URL for all platforms.
-# This ensures consistent source builds across Windows, Mac, and Linux.
+# Note: OpenTimelineIO is now installed via requirements.txt from git URL for all platforms. This ensures consistent source builds across Windows, Mac, and
+# Linux.
FETCHCONTENT_DECLARE(
${_pyside_target}
@@ -109,7 +107,6 @@ LIST(APPEND _python3_make_command ${_build_dir})
LIST(APPEND _python3_make_command "--vfx_platform")
LIST(APPEND _python3_make_command ${RV_VFX_CY_YEAR})
-
IF(DEFINED RV_DEPS_OPENSSL_INSTALL_DIR)
LIST(APPEND _python3_make_command "--openssl-dir")
LIST(APPEND _python3_make_command ${RV_DEPS_OPENSSL_INSTALL_DIR})
@@ -260,11 +257,7 @@ SET(_requirements_output_file
"${CMAKE_BINARY_DIR}/requirements.txt"
)
-CONFIGURE_FILE(
- ${_requirements_input_file}
- ${_requirements_output_file}
- @ONLY
-)
+CONFIGURE_FILE(${_requirements_input_file} ${_requirements_output_file} @ONLY)
# OpenTimelineIO needs to be built from source with CMAKE_ARGS to ensure it uses
# the correct custom-built Python libraries. This is required for both old and new
@@ -298,8 +291,18 @@ IF(RV_TARGET_WINDOWS)
patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/python-${RV_DEPS_PYTHON_VERSION}/python.${RV_DEPS_PYTHON_VERSION}.get_externals.bat.patch"
)
- #TODO: Above patches are for Python 3.11.9, need to add other versions.
- RV_VFX_SET_VARIABLE(_patch_command CY2023 "" CY2024 "${_patch_python_command}" CY2025 "${_patch_python_command}" CY2026 "")
+ # TODO: Above patches are for Python 3.11.9, need to add other versions.
+ RV_VFX_SET_VARIABLE(
+ _patch_command
+ CY2023
+ ""
+ CY2024
+ "${_patch_python_command}"
+ CY2025
+ "${_patch_python_command}"
+ CY2026
+ ""
+ )
# Split the command into a semi-colon separated list.
SEPARATE_ARGUMENTS(_patch_command)
STRING(
@@ -339,10 +342,8 @@ IF(APPLE
patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/patch/pyopengl-accelerate.patch
)
- # TODO: pyopengl is now at 3.1.10.
- # Need to check if this is an improvement
- # Still need the patch https://github.com/mcfletch/pyopengl/blob/master/accelerate/src/vbo.pyx
- # https://github.com/mcfletch/pyopengl/compare/release-3.1.8...3.1.10
+ # TODO: pyopengl is now at 3.1.10. Need to check if this is an improvement Still need the patch
+ # https://github.com/mcfletch/pyopengl/blob/master/accelerate/src/vbo.pyx https://github.com/mcfletch/pyopengl/compare/release-3.1.8...3.1.10
EXTERNALPROJECT_ADD(
pyopengl_accelerate
URL "https://github.com/mcfletch/pyopengl/archive/refs/tags/release-3.1.8.tar.gz"
@@ -387,7 +388,8 @@ IF(RV_TARGET_WINDOWS
POST_BUILD
COMMENT "Copying Debug Python lib as a unversionned file for Debug"
COMMAND cmake -E copy_if_different ${_python3_implib} ${_python_release_libpath}
- COMMAND cmake -E copy_if_different ${_python3_implib} ${_python_release_in_bin_libpath} DEPENDS ${_python3_target} ${_requirements_output_file} ${_requirements_input_file}
+ COMMAND cmake -E copy_if_different ${_python3_implib} ${_python_release_in_bin_libpath} DEPENDS ${_python3_target} ${_requirements_output_file}
+ ${_requirements_input_file}
)
ENDIF()
diff --git a/src/lib/app/RvCommon/CMakeLists.txt b/src/lib/app/RvCommon/CMakeLists.txt
index 1ba4ce232..d3362ce3e 100644
--- a/src/lib/app/RvCommon/CMakeLists.txt
+++ b/src/lib/app/RvCommon/CMakeLists.txt
@@ -191,11 +191,163 @@ FOREACH(
LIST(APPEND _sources ${outfile})
ENDFOREACH()
+#
+# Generate about_rv.cpp with build information
+#
+SET(_about_rv_cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/${_target}/generated/about_rv.cpp
+)
+
+# Get compiler name
+IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ SET(_compiler_name
+ "GCC ${CMAKE_CXX_COMPILER_VERSION}"
+ )
+ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ IF(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
+ SET(_compiler_name
+ "Clang-cl ${CMAKE_CXX_COMPILER_VERSION}"
+ )
+ ELSE()
+ SET(_compiler_name
+ "Clang ${CMAKE_CXX_COMPILER_VERSION}"
+ )
+ ENDIF()
+ELSEIF(MSVC)
+ SET(_compiler_name
+ "MSVC ${CMAKE_CXX_COMPILER_VERSION}"
+ )
+ELSE()
+ SET(_compiler_name
+ "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}"
+ )
+ENDIF()
+
+# Get VFX platform
+IF(RV_VFX_PLATFORM)
+ SET(_vfx_platform_str
+ ${RV_VFX_PLATFORM}
+ )
+ELSE()
+ SET(_vfx_platform_str
+ "N/A"
+ )
+ENDIF()
+
+# Get platform and arch
+IF(RV_TARGET_DARWIN)
+ SET(_platform_name
+ "macOS"
+ )
+ELSEIF(RV_TARGET_LINUX)
+ SET(_platform_name
+ "Linux"
+ )
+ELSEIF(RV_TARGET_WINDOWS)
+ SET(_platform_name
+ "Windows"
+ )
+ELSE()
+ SET(_platform_name
+ ${CMAKE_SYSTEM_NAME}
+ )
+ENDIF()
+
+SET(_arch_name
+ ${CMAKE_SYSTEM_PROCESSOR}
+)
+
+# Create a JSON-like string with versions (using semicolon as separator for CMake list)
+SET(_versions_list
+ "Qt:${RV_DEPS_QT_VERSION}"
+ "CMake:${CMAKE_VERSION}"
+ "Python:${RV_DEPS_PYTHON3_VERSION}"
+ "PySide:${RV_DEPS_PYSIDE_VERSION}"
+ "Boost:${RV_DEPS_BOOST_VERSION}"
+ "Imath:${RV_DEPS_IMATH_VERSION}"
+ "OpenEXR:${RV_DEPS_OPENEXR_VERSION}"
+ "OpenImageIO:${RV_DEPS_OIIO_VERSION}"
+ "OpenColorIO:${RV_DEPS_OCIO_VERSION}"
+ "FFmpeg:${RV_DEPS_FFMPEG_VERSION}"
+ "OpenSSL:${RV_DEPS_OPENSSL_VERSION}"
+ "GLEW:${RV_DEPS_GLEW_VERSION_LIB}"
+ "spdlog:${RV_DEPS_SPDLOG_VERSION}"
+ "yaml-cpp:${RV_DEPS_YAML_CPP_VERSION}"
+ "zlib:${RV_DEPS_ZLIB_VERSION}"
+ "dav1d:${RV_DEPS_DAV1D_VERSION}"
+ "jpegturbo:${RV_DEPS_JPEGTURBO_VERSION}"
+ "png:${RV_DEPS_PNG_VERSION}"
+ "tiff:${RV_DEPS_TIFF_VERSION}"
+ "webp:${RV_DEPS_WEBP_VERSION}"
+ "openjpeg:${RV_DEPS_OPENJPEG_VERSION}"
+ "openjph:${RV_DEPS_OPENJPH_VERSION}"
+ "raw:${RV_DEPS_RAW_VERSION}"
+ "gc:${RV_DEPS_GC_VERSION}"
+ "aja:${RV_DEPS_AJA_VERSION}"
+ "bmd:${RV_DEPS_BMD_VERSION}"
+ "imgui:${RV_DEPS_IMGUI_VERSION}"
+ "numpy:$ENV{RV_DEPS_NUMPY_VERSION}"
+ "otio:${RV_DEPS_OTIO_VERSION}"
+ "expat:${RV_DEPS_EXPAT_VERSION}"
+ "nanobind:${RV_DEPS_NANOBIND_VERSION}"
+ "pcre2:${RV_DEPS_PCRE2_VERSION}"
+)
+
+# Add commercial RV-specific SDK versions if they exist
+IF(DEFINED RV_DEPS_PRORES_VERSION
+ AND RV_DEPS_PRORES_VERSION
+)
+ LIST(APPEND _versions_list "prores:${RV_DEPS_PRORES_VERSION}")
+ENDIF()
+IF(DEFINED RV_DEPS_R3DSDK_VERSION
+ AND RV_DEPS_R3DSDK_VERSION
+)
+ LIST(APPEND _versions_list "r3dsdk:${RV_DEPS_R3DSDK_VERSION}")
+ENDIF()
+IF(DEFINED RV_DEPS_ARRIRAW_VERSION
+ AND RV_DEPS_ARRIRAW_VERSION
+)
+ LIST(APPEND _versions_list "arriraw:${RV_DEPS_ARRIRAW_VERSION}")
+ENDIF()
+IF(DEFINED RV_DEPS_X264_VERSION
+ AND RV_DEPS_X264_VERSION
+)
+ LIST(APPEND _versions_list "x264:${RV_DEPS_X264_VERSION}")
+ENDIF()
+IF(DEFINED RV_DEPS_NDI_VERSION
+ AND RV_DEPS_NDI_VERSION
+)
+ LIST(APPEND _versions_list "ndi:${RV_DEPS_NDI_VERSION}")
+ENDIF()
+
+STRING(REPLACE ";" "," _versions_str "${_versions_list}")
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${_about_rv_cpp}
+ COMMAND
+ python3 ${CMAKE_CURRENT_SOURCE_DIR}/generate_about_rv.py ${_about_rv_cpp} "${_compiler_name}"
+ "${_vfx_platform_str}" "${_platform_name}" "${_arch_name}" "${RV_UI_APPLICATION_NAME}" "${_versions_str}" "${RV_GIT_COMMIT_SHORT_HASH}"
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/generate_about_rv.py
+ COMMENT "Generating about_rv.cpp with build information"
+ VERBATIM
+)
+
+# Create explicit target to ensure about_rv.cpp is generated before RvCommon builds
+ADD_CUSTOM_TARGET(
+ generate_about_rv_cpp
+ DEPENDS ${_about_rv_cpp}
+)
+
+LIST(APPEND _sources ${_about_rv_cpp})
+
ADD_LIBRARY(
${_target} STATIC
${_sources} qrc/RvCommon.qrc
)
+# Ensure about_rv.cpp is generated before building RvCommon
+ADD_DEPENDENCIES(${_target} generate_about_rv_cpp)
+
# Need that with Qt6 since the code for this target does not support unicode correctly.
IF(RV_TARGET_WINDOWS
AND RV_VFX_PLATFORM STRGREATER_EQUAL CY2024
diff --git a/src/lib/app/RvCommon/RvApplication.cpp b/src/lib/app/RvCommon/RvApplication.cpp
index 149333ead..4b7bc6da4 100644
--- a/src/lib/app/RvCommon/RvApplication.cpp
+++ b/src/lib/app/RvCommon/RvApplication.cpp
@@ -59,6 +59,9 @@
extern char** environ;
#endif
+// Generated by generate_about_rv.py
+extern const char* about_RV;
+
#ifdef PLATFORM_DARWIN
extern void (*sessionFromUrlPointer)(std::string);
extern void (*putUrlOnMacPasteboardPointer)(std::string, std::string);
@@ -619,7 +622,15 @@ namespace Rv
msgBox->setIconPixmap(icon.pixmap(size));
msgBox->setStandardButtons(QMessageBox::Close);
+ // Add a text box with detailed build and dependency information
+ QTextEdit* textBox = new QTextEdit();
+ textBox->setHtml(about_RV);
+ textBox->setReadOnly(true);
+ textBox->setMinimumHeight(250);
+ textBox->setMinimumWidth(500);
+
QGridLayout* grid = static_cast(msgBox->layout());
+ grid->addWidget(textBox, grid->rowCount() - 1, 0, 1, -1);
QDialogButtonBox* buttonBox = msgBox->findChild();
grid->removeWidget(buttonBox);
diff --git a/src/lib/app/RvCommon/generate_about_rv.py b/src/lib/app/RvCommon/generate_about_rv.py
new file mode 100755
index 000000000..efd58dcb1
--- /dev/null
+++ b/src/lib/app/RvCommon/generate_about_rv.py
@@ -0,0 +1,293 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2025 Autodesk, Inc. All Rights Reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Generate about_rv.cpp with build and dependency information
+
+import argparse
+import sys
+from datetime import datetime
+from pathlib import Path
+
+
+def get_git_info(git_hash_from_cmake=""):
+ """Get git commit hash from CMake"""
+ return git_hash_from_cmake if git_hash_from_cmake else "unknown"
+
+
+def parse_versions(versions_str):
+ """Parse the versions string into a dictionary"""
+ versions = {}
+ if versions_str:
+ for item in versions_str.split(","):
+ if ":" in item:
+ key, value = item.split(":", 1)
+ versions[key] = value
+ return versions
+
+
+def get_dependencies_info(versions, app_name, platform=""):
+ """Generate dependency information using detected versions"""
+
+ def get_version(key, default="Unknown"):
+ version = versions.get(key, default)
+ # Strip FFmpeg's 'n' prefix (e.g., n6.1.2 -> 6.1.2)
+ if key == "FFmpeg" and version.startswith("n"):
+ version = version[1:]
+ return version
+
+ # OpenRV uses LGPL, commercial RV uses Qt Commercial
+ is_commercial_rv = app_name == "RV"
+ qt_license = "Qt Commercial" if is_commercial_rv else "LGPL v3"
+ pyside_license = "Qt Commercial" if is_commercial_rv else "LGPL v3"
+
+ is_macos = "darwin" in platform.lower() or "macos" in platform.lower()
+
+ vfx_deps = [
+ ("Boost", get_version("Boost"), "Boost Software License"),
+ ("CMake", get_version("CMake"), "BSD 3-Clause"),
+ ("Imath", get_version("Imath"), "BSD 3-Clause"),
+ ("NumPy", get_version("numpy", "1.24+"), "BSD 3-Clause"),
+ ("OpenColorIO", get_version("OpenColorIO"), "BSD 3-Clause"),
+ ("OpenEXR", get_version("OpenEXR"), "BSD 3-Clause"),
+ ("OpenImageIO", get_version("OpenImageIO"), "Apache 2.0"),
+ ("OpenTimelineIO", get_version("otio"), "Apache 2.0"),
+ ("PySide", get_version("PySide"), pyside_license),
+ ("Python", get_version("Python"), "PSF License"),
+ ("Qt Framework", get_version("Qt"), qt_license),
+ ]
+
+ # RV-specific proprietary components (only for commercial RV, alphabetical order)
+ rv_specific_deps = []
+ if is_commercial_rv:
+ # Apple ProRes is only available on macOS (and not on ARM64 currently)
+ if is_macos:
+ prores_ver = get_version("prores", "Not Used")
+ rv_specific_deps.append(("Apple ProRes", prores_ver, "Apple Proprietary"))
+
+ # Always add these for commercial RV (version will show "Not Used" if not available)
+ rv_specific_deps.extend(
+ [
+ ("ARRI SDK", get_version("arriraw", "Not Used"), "ARRI Proprietary"),
+ ("NDI SDK", get_version("ndi", "Not Used"), "NDI Proprietary"),
+ ("RED R3D SDK", get_version("r3dsdk", "Not Used"), "RED Proprietary"),
+ ("x264", get_version("x264", "Not Used"), "x264 Commercial License"),
+ ]
+ )
+
+ # Other third-party components (alphabetical order)
+ other_deps = [
+ ("AJA NTV2 SDK", get_version("aja"), "MIT License"),
+ ("Blackmagic DeckLink SDK", get_version("bmd"), "Proprietary"),
+ ("Boehm GC", get_version("gc"), "MIT-style"),
+ ("dav1d", get_version("dav1d"), "BSD 2-Clause"),
+ ("Dear ImGui", get_version("imgui"), "MIT License"),
+ ("Expat", get_version("expat"), "MIT License"),
+ ("FFmpeg", get_version("FFmpeg"), "LGPL v2.1+"),
+ ("GLEW", get_version("GLEW"), "Modified BSD / MIT"),
+ ("libjpeg-turbo", get_version("jpegturbo"), "BSD-style"),
+ ("libpng", get_version("png"), "libpng License"),
+ ("LibRaw", get_version("raw"), "LGPL v2.1 / CDDL"),
+ ("libtiff", get_version("tiff"), "libtiff License"),
+ ("libwebp", get_version("webp"), "BSD 3-Clause"),
+ ("nanobind", get_version("nanobind"), "BSD 3-Clause"),
+ ("OpenJPEG", get_version("openjpeg"), "BSD 2-Clause"),
+ ("OpenJPH", get_version("openjph"), "BSD 2-Clause"),
+ ("OpenSSL", get_version("OpenSSL"), "Apache License 2.0"),
+ ("PCRE2", get_version("pcre2"), "BSD License"),
+ ("spdlog", get_version("spdlog"), "MIT License"),
+ ("yaml-cpp", get_version("yaml-cpp"), "MIT License"),
+ ("zlib", get_version("zlib"), "zlib License"),
+ ]
+
+ return vfx_deps, other_deps, rv_specific_deps
+
+
+def generate_about_cpp(
+ output_file,
+ compiler,
+ vfx_platform,
+ platform,
+ arch,
+ app_name,
+ versions_str="",
+ git_hash="",
+):
+ """Generate the about_rv.cpp file"""
+
+ git_commit = get_git_info(git_hash)
+ versions = parse_versions(versions_str)
+ vfx_deps, other_deps, rv_specific_deps = get_dependencies_info(versions, app_name, platform)
+ build_date = datetime.now().strftime("%B %d, %Y")
+
+ # Build the HTML content
+ html_content = []
+ html_content.append("")
+ html_content.append(f"{platform} {arch}")
+ html_content.append("
")
+ html_content.append("")
+ html_content.append(f"Compiled using {compiler}")
+ html_content.append("
")
+ html_content.append("")
+ html_content.append(f"Build identifier: {app_name}, HEAD={git_commit}")
+ html_content.append("
")
+ html_content.append("")
+ html_content.append(f"Built on: {build_date}")
+ html_content.append("
")
+
+ # Single table with both sections
+ html_content.append("
")
+ html_content.append("")
+ html_content.append('
')
+
+ # VFX Platform header row
+ if vfx_platform:
+ # Extract year from platform (e.g., "CY2024" -> "2024")
+ vfx_year = vfx_platform.replace("CY", "") if vfx_platform.startswith("CY") else vfx_platform
+ html_content.append("")
+ html_content.append(f'| VFX Reference Platform {vfx_year} | ')
+ html_content.append("
")
+
+ # Column headers
+ html_content.append("")
+ html_content.append("| Description | ")
+ html_content.append("Version | ")
+ html_content.append("License | ")
+ html_content.append("
")
+
+ # VFX Platform dependencies
+ for desc, version, license in vfx_deps:
+ html_content.append("")
+ html_content.append(f"| {desc} | ")
+ html_content.append(f"{version} | ")
+ html_content.append(f"{license} | ")
+ html_content.append("
")
+
+ # Empty row separator
+ html_content.append('| |
')
+
+ # Other Dependencies header row
+ html_content.append("")
+ html_content.append('| Other Dependencies | ')
+ html_content.append("
")
+
+ # Column headers for other dependencies
+ html_content.append("")
+ html_content.append("| Description | ")
+ html_content.append("Version | ")
+ html_content.append("License | ")
+ html_content.append("
")
+
+ # Other dependencies
+ for desc, version, license in other_deps:
+ html_content.append("")
+ html_content.append(f"| {desc} | ")
+ html_content.append(f"{version} | ")
+ html_content.append(f"{license} | ")
+ html_content.append("
")
+
+ # RV-Specific Components section (only for commercial RV)
+ if rv_specific_deps:
+ # Empty row separator
+ html_content.append('| |
')
+
+ # RV Components header row
+ html_content.append("")
+ html_content.append('| RV-Specific Components | ')
+ html_content.append("
")
+
+ # Column headers
+ html_content.append("")
+ html_content.append("| Description | ")
+ html_content.append("Version | ")
+ html_content.append("License | ")
+ html_content.append("
")
+
+ # RV-specific components
+ for desc, version, license in rv_specific_deps:
+ html_content.append("")
+ html_content.append(f"| {desc} | ")
+ html_content.append(f"{version} | ")
+ html_content.append(f"{license} | ")
+ html_content.append("
")
+
+ html_content.append("
")
+ html_content.append("")
+ html_content.append("
")
+ html_content.append("")
+ html_content.append("For detailed license information, please see the THIRD-PARTY.md file ")
+ html_content.append("included with this distribution or visit the Open RV GitHub repository.")
+ html_content.append("
")
+
+ # Join without newlines - HTML doesn't need them
+ html_str = "".join(html_content)
+
+ # Escape quotes for C++
+ html_str = html_str.replace('"', '\\"')
+
+ # Generate the C++ file
+ cpp_content = f'''//
+// Copyright (C) 2025 Autodesk, Inc. All Rights Reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// This file is auto-generated by generate_about_rv.py
+// DO NOT EDIT MANUALLY
+
+const char* about_RV = "{html_str}";
+'''
+
+ # Ensure the output directory exists
+ try:
+ output_path = Path(output_file)
+ print(f"Creating directory: {output_path.parent}")
+ output_path.parent.mkdir(parents=True, exist_ok=True)
+
+ print(f"Writing to: {output_path}")
+ with open(output_file, "w", encoding="utf-8", newline="\n") as f:
+ f.write(cpp_content)
+
+ # Verify the file was written
+ if not output_path.exists():
+ print(f"ERROR: File was not created: {output_file}", file=sys.stderr)
+ sys.exit(1)
+
+ file_size = output_path.stat().st_size
+ print(f"Generated {output_file} ({file_size} bytes)")
+
+ except Exception as e:
+ print(f"ERROR generating {output_file}: {e}", file=sys.stderr)
+ import traceback
+
+ traceback.print_exc()
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ description="Generate about_rv.cpp with build and dependency information"
+ )
+ parser.add_argument("output_file", help="Path to the output C++ file")
+ parser.add_argument("compiler", help="Compiler name and version")
+ parser.add_argument("vfx_platform", help="VFX Platform version (e.g., CY2024)")
+ parser.add_argument("platform", help="Target platform (e.g., macOS, Linux, Windows)")
+ parser.add_argument("arch", help="Target architecture (e.g., x86_64, arm64)")
+ parser.add_argument("app_name", nargs="?", default="Open RV", help="Application name")
+ parser.add_argument("versions", nargs="?", default="", help="Comma-separated dependency versions")
+ parser.add_argument("git_hash", nargs="?", default="", help="Git commit hash")
+
+ args = parser.parse_args()
+
+ print(f"=== generate_about_rv.py: generating {args.output_file} ===", flush=True)
+ generate_about_cpp(
+ args.output_file,
+ args.compiler,
+ args.vfx_platform,
+ args.platform,
+ args.arch,
+ args.app_name,
+ args.versions,
+ args.git_hash,
+ )