From 50dd616418679cc1681a83e749fb5f81553dbb31 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Fri, 11 Jul 2025 17:10:24 +0200 Subject: [PATCH] Enable pluginval integration --- CMakeLists.txt | 9 ++- cmake/yup.cmake | 1 + cmake/yup_audio_plugin.cmake | 5 ++ cmake/yup_pluginval.cmake | 140 +++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 cmake/yup_pluginval.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 217f1113a..cb35753e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,10 @@ set_property (GLOBAL PROPERTY USE_FOLDERS ON) # Options option (YUP_TARGET_ANDROID "Target Android project" OFF) option (YUP_TARGET_ANDROID_BUILD_GRADLE "When building for Android, build the gradle infrastructure" OFF) +option (YUP_EXPORT_MODULES "Export the modules to the parent project" ON) option (YUP_ENABLE_PROFILING "Enable the profiling code using Perfetto SDK" OFF) option (YUP_ENABLE_COVERAGE "Enable code coverage collection for tests" OFF) -option (YUP_EXPORT_MODULES "Export the modules to the parent project" ON) +option (YUP_ENABLE_PLUGINVAL "Enable pluginval validation for VST3 plugins" OFF) option (YUP_ENABLE_STATIC_PYTHON_LIBS "Use static Python libraries" OFF) option (YUP_BUILD_JAVA_SUPPORT "Build the Java support" OFF) option (YUP_BUILD_EXAMPLES "Build the examples" ${PROJECT_IS_TOP_LEVEL}) @@ -67,6 +68,12 @@ if (YUP_ENABLE_PROFILING) _yup_fetch_perfetto() endif() +# Setup pluginval +if (YUP_ENABLE_PLUGINVAL) + _yup_message (STATUS "Setting up pluginval") + yup_setup_pluginval() +endif() + # Targets if (YUP_BUILD_EXAMPLES) _yup_message (STATUS "Building examples") diff --git a/cmake/yup.cmake b/cmake/yup.cmake index 1e117b580..faa76bdbd 100644 --- a/cmake/yup.cmake +++ b/cmake/yup.cmake @@ -94,6 +94,7 @@ include (${CMAKE_CURRENT_LIST_DIR}/yup_audio_plugin.cmake) include (${CMAKE_CURRENT_LIST_DIR}/yup_embed_binary.cmake) include (${CMAKE_CURRENT_LIST_DIR}/yup_android_java.cmake) include (${CMAKE_CURRENT_LIST_DIR}/yup_python.cmake) +include (${CMAKE_CURRENT_LIST_DIR}/yup_pluginval.cmake) #============================================================================== diff --git a/cmake/yup_audio_plugin.cmake b/cmake/yup_audio_plugin.cmake index 4d80314c0..f3db31679 100644 --- a/cmake/yup_audio_plugin.cmake +++ b/cmake/yup_audio_plugin.cmake @@ -209,6 +209,11 @@ function (yup_audio_plugin) FOLDER "${YUP_ARG_TARGET_IDE_GROUP}" XCODE_GENERATE_SCHEME ON) + # Add pluginval validation if enabled + if (YUP_ENABLE_PLUGINVAL) + yup_validate_plugin (${target_name}_vst3_plugin "$") + endif() + yup_audio_plugin_copy_bundle (${target_name} vst3) endif() diff --git a/cmake/yup_pluginval.cmake b/cmake/yup_pluginval.cmake new file mode 100644 index 000000000..ff6a73fe0 --- /dev/null +++ b/cmake/yup_pluginval.cmake @@ -0,0 +1,140 @@ +# ============================================================================== +# +# This file is part of the YUP library. +# Copyright (c) 2025 - kunitoki@gmail.com +# +# YUP is an open source library subject to open-source licensing. +# +# The code included in this file is provided under the terms of the ISC license +# http://www.isc.org/downloads/software-support-policy/isc-license. Permission +# To use, copy, modify, and/or distribute this software for any purpose with or +# without fee is hereby granted provided that the above copyright notice and +# this permission notice appear in all copies. +# +# YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +# ============================================================================== + +set (PLUGINVAL_VERSION "v1.0.4") + +# ============================================================================== + +function (yup_setup_pluginval) + if (NOT YUP_ENABLE_PLUGINVAL) + return() + endif() + + # Only supported on desktop platforms + if (NOT YUP_PLATFORM_DESKTOP) + _yup_message (WARNING "pluginval is only supported on desktop platforms") + return() + endif() + + # Determine platform-specific download URL and executable name + if (YUP_PLATFORM_WINDOWS) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set (PLUGINVAL_PLATFORM "Windows") + set (PLUGINVAL_ARCHIVE "pluginval_Windows.zip") + else() + _yup_message (WARNING "pluginval does not support 32-bit Windows") + return() + endif() + set (PLUGINVAL_EXECUTABLE "pluginval.exe") + elseif (YUP_PLATFORM_MAC) + set (PLUGINVAL_PLATFORM "macOS") + set (PLUGINVAL_ARCHIVE "pluginval_macOS.zip") + set (PLUGINVAL_EXECUTABLE "pluginval.app/Contents/MacOS/pluginval") + elseif (YUP_PLATFORM_LINUX) + set (PLUGINVAL_PLATFORM "Linux") + set (PLUGINVAL_ARCHIVE "pluginval_Linux.zip") + set (PLUGINVAL_EXECUTABLE "pluginval") + else() + _yup_message (WARNING "Unsupported platform for pluginval") + return() + endif() + + # Set up download URL + set (PLUGINVAL_URL "https://github.com/Tracktion/pluginval/releases/download/${PLUGINVAL_VERSION}/${PLUGINVAL_ARCHIVE}") + + # Set up local paths + set (PLUGINVAL_DIR "${CMAKE_BINARY_DIR}/pluginval") + set (PLUGINVAL_ARCHIVE_PATH "${PLUGINVAL_DIR}/${PLUGINVAL_ARCHIVE}") + set (PLUGINVAL_EXECUTABLE_PATH "${PLUGINVAL_DIR}/${PLUGINVAL_EXECUTABLE}") + + # Create pluginval directory + file (MAKE_DIRECTORY "${PLUGINVAL_DIR}") + + # Download pluginval if not already present + if (NOT EXISTS "${PLUGINVAL_EXECUTABLE_PATH}") + _yup_message (STATUS "Downloading pluginval ${PLUGINVAL_VERSION} for ${PLUGINVAL_PLATFORM}") + + # Download the archive + file (DOWNLOAD "${PLUGINVAL_URL}" "${PLUGINVAL_ARCHIVE_PATH}" + SHOW_PROGRESS + STATUS DOWNLOAD_STATUS) + + # Check if download was successful + list (GET DOWNLOAD_STATUS 0 DOWNLOAD_ERROR) + if (NOT DOWNLOAD_ERROR EQUAL 0) + list (GET DOWNLOAD_STATUS 1 DOWNLOAD_ERROR_MESSAGE) + _yup_message (FATAL_ERROR "Failed to download pluginval: ${DOWNLOAD_ERROR_MESSAGE}") + endif() + + # Extract the archive + _yup_message (STATUS "Extracting pluginval archive") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf "${PLUGINVAL_ARCHIVE_PATH}" + WORKING_DIRECTORY "${PLUGINVAL_DIR}" + RESULT_VARIABLE EXTRACT_RESULT) + + if (NOT EXTRACT_RESULT EQUAL 0) + _yup_message (FATAL_ERROR "Failed to extract pluginval archive") + endif() + + # Make executable (Posix platforms) + if (YUP_PLATFORM_POSIX) + execute_process( + COMMAND chmod +x "${PLUGINVAL_EXECUTABLE_PATH}" + RESULT_VARIABLE CHMOD_RESULT) + + if (NOT CHMOD_RESULT EQUAL 0) + _yup_message (WARNING "Failed to make pluginval executable") + endif() + endif() + + # Clean up archive + file (REMOVE "${PLUGINVAL_ARCHIVE_PATH}") + endif() + + # Verify pluginval executable exists + if (NOT EXISTS "${PLUGINVAL_EXECUTABLE_PATH}") + _yup_message (FATAL_ERROR "pluginval executable not found at: ${PLUGINVAL_EXECUTABLE_PATH}") + endif() + + # Set global variable for use in other cmake files + set (PLUGINVAL_EXECUTABLE "${PLUGINVAL_EXECUTABLE_PATH}" CACHE INTERNAL "Path to pluginval executable") + + _yup_message (STATUS "pluginval is available at: ${PLUGINVAL_EXECUTABLE_PATH}") +endfunction() + +# ============================================================================== + +function (yup_validate_plugin target_name plugin_path) + if (NOT YUP_ENABLE_PLUGINVAL OR NOT PLUGINVAL_EXECUTABLE) + return() + endif() + + set (validation_target_name "${target_name}_pluginval") + + add_custom_command( + TARGET ${target_name} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "[PLUGINVAL] Starting validation of ${target_name}..." + COMMAND "${PLUGINVAL_EXECUTABLE}" --strictness-level 5 --validate-in-process --output-dir "${CMAKE_BINARY_DIR}/pluginval_reports" "${plugin_path}" + COMMAND ${CMAKE_COMMAND} -E echo "[PLUGINVAL] Validation of ${target_name} completed" + COMMENT "Running pluginval validation on ${target_name}" + VERBATIM) +endfunction()