From ece5644a2035013455a55de6f66a9880bee27c3a Mon Sep 17 00:00:00 2001 From: reuk Date: Sun, 15 Sep 2019 20:37:25 +0100 Subject: [PATCH] CMake: Add support for building JUCE projects with CMake --- .gitignore | 3 + CMakeLists.txt | 103 + examples/Assets/DemoUtilities.h | 2 + examples/Audio/CMakeLists.txt | 17 + examples/BLOCKS/CMakeLists.txt | 17 + examples/CMake/AudioPlugin/CMakeLists.txt | 104 + examples/CMake/AudioPlugin/PluginEditor.cpp | 33 + examples/CMake/AudioPlugin/PluginEditor.h | 22 + .../CMake/AudioPlugin/PluginProcessor.cpp | 186 ++ examples/CMake/AudioPlugin/PluginProcessor.h | 47 + examples/CMake/CMakeLists.txt | 19 + examples/CMake/ConsoleApp/CMakeLists.txt | 82 + examples/CMake/ConsoleApp/Main.cpp | 10 + examples/CMake/GuiApp/CMakeLists.txt | 95 + examples/CMake/GuiApp/Main.cpp | 101 + examples/CMake/GuiApp/MainComponent.cpp | 25 + examples/CMake/GuiApp/MainComponent.h | 29 + examples/CMake/readme.md | 513 +++++ examples/CMakeLists.txt | 35 + examples/DSP/CMakeLists.txt | 17 + .../app/src/main/assets/DemoUtilities.h | 2 + examples/DemoRunner/CMakeLists.txt | 64 + examples/GUI/CMakeLists.txt | 17 + examples/Plugins/AUv3SynthPluginDemo.h | 31 +- examples/Plugins/ArpeggiatorPluginDemo.h | 30 +- examples/Plugins/AudioPluginDemo.h | 32 +- examples/Plugins/CMakeLists.txt | 17 + .../Plugins/InterAppAudioEffectPluginDemo.h | 30 +- examples/Plugins/MultiOutSynthPluginDemo.h | 30 +- examples/Utilities/CMakeLists.txt | 17 + examples/Utilities/InAppPurchasesDemo.h | 1 + examples/Utilities/PushNotificationsDemo.h | 1 + extras/AudioPerformanceTest/CMakeLists.txt | 27 + extras/AudioPluginHost/CMakeLists.txt | 52 + extras/BinaryBuilder/CMakeLists.txt | 25 + extras/Build/CMake/JUCEConfig.cmake.in | 41 + extras/Build/CMake/JUCEUtils.cmake | 2014 +++++++++++++++++ extras/Build/CMake/LaunchScreen.storyboard | 16 + extras/Build/CMake/PIPAudioProcessor.cpp.in | 16 + .../CMake/PIPComponent.cpp.in} | 145 +- extras/Build/CMake/PIPConsole.cpp.in | 10 + .../CMake}/RecentFilesMenuTemplate.nib | Bin .../CMake/UnityPluginGUIScript.cs.in} | 32 +- extras/Build/CMake/copyDir.cmake | 17 + extras/Build/CMakeLists.txt | 20 + .../juce_build_tools/juce_build_tools.cpp | 40 + .../Build/juce_build_tools/juce_build_tools.h | 60 + .../utils/juce_BinaryResourceFile.cpp | 280 +++ .../utils/juce_BinaryResourceFile.h | 67 + .../utils/juce_BuildHelperFunctions.cpp | 344 +++ .../utils/juce_BuildHelperFunctions.h | 79 + .../utils/juce_CppTokeniserFunctions.cpp | 214 ++ .../utils/juce_Entitlements.cpp | 109 + .../utils/juce_Entitlements.h | 48 + .../juce_build_tools/utils/juce_Icons.cpp | 497 ++++ .../Build/juce_build_tools/utils/juce_Icons.h | 42 + .../utils/juce_PlistOptions.cpp | 354 +++ .../utils/juce_PlistOptions.h | 95 + .../juce_build_tools/utils/juce_ProjectType.h | 268 +++ .../utils/juce_RelativePath.h | 122 + .../utils/juce_ResourceFileHelpers.cpp | 84 + .../utils/juce_ResourceFileHelpers.h | 31 + .../utils/juce_ResourceRc.cpp | 88 + .../juce_build_tools/utils/juce_ResourceRc.h | 36 + .../utils/juce_VersionNumbers.cpp | 50 + .../utils/juce_VersionNumbers.h | 29 + extras/Build/juceaide/CMakeLists.txt | 90 + extras/Build/juceaide/Main.cpp | 507 +++++ extras/CMakeLists.txt | 22 + extras/NetworkGraphicsDemo/CMakeLists.txt | 30 + extras/Projucer/Builds/LinuxMakefile/Makefile | 10 +- extras/Projucer/Builds/MacOSX/Icon.icns | Bin 44839 -> 89670 bytes .../MacOSX/Projucer.xcodeproj/project.pbxproj | 119 +- .../VisualStudio2015/Projucer_App.vcxproj | 58 +- .../Projucer_App.vcxproj.filters | 102 +- .../VisualStudio2017/Projucer_App.vcxproj | 58 +- .../Projucer_App.vcxproj.filters | 102 +- .../VisualStudio2019/Projucer_App.vcxproj | 58 +- .../Projucer_App.vcxproj.filters | 102 +- extras/Projucer/CMakeLists.txt | 166 ++ extras/Projucer/JuceLibraryCode/AppConfig.h | 1 + .../Projucer/JuceLibraryCode/BinaryData.cpp | 932 ++++---- extras/Projucer/JuceLibraryCode/BinaryData.h | 29 +- extras/Projucer/JuceLibraryCode/JuceHeader.h | 1 + .../include_juce_build_tools.cpp | 9 + extras/Projucer/Projucer.jucer | 167 +- .../jucer_SVGPathDataWindowComponent.h | 2 +- .../Source/Application/jucer_CommandLine.cpp | 4 +- .../Source/Application/jucer_CommonHeaders.h | 1 - .../CodeEditor/jucer_SourceCodeEditor.cpp | 2 +- .../Components/jucer_ComponentTypeHandler.cpp | 4 +- .../jucer_GenericComponentHandler.h | 2 +- .../PaintElements/jucer_FillType.h | 2 +- .../jucer_ImageResourceProperty.h | 2 +- .../UI/jucer_RelativePositionedRectangle.h | 2 +- .../ComponentEditor/jucer_BinaryResources.cpp | 2 +- .../ComponentEditor/jucer_ComponentLayout.cpp | 8 +- .../ComponentEditor/jucer_GeneratedCode.cpp | 2 +- .../ComponentEditor/jucer_JucerDocument.cpp | 6 +- .../jucer_CompileEngineClient.cpp | 7 +- .../Projucer/Source/Project/jucer_Module.cpp | 21 +- extras/Projucer/Source/Project/jucer_Module.h | 8 +- .../Projucer/Source/Project/jucer_Project.cpp | 168 +- .../Projucer/Source/Project/jucer_Project.h | 19 +- .../Source/Project/jucer_ProjectType.h | 209 -- .../jucer_ProjectExport_Android.h | 437 ++-- .../ProjectSaving/jucer_ProjectExport_CLion.h | 146 +- .../jucer_ProjectExport_CodeBlocks.h | 110 +- .../ProjectSaving/jucer_ProjectExport_MSVC.h | 345 +-- .../ProjectSaving/jucer_ProjectExport_Make.h | 93 +- .../ProjectSaving/jucer_ProjectExport_Xcode.h | 920 ++------ .../ProjectSaving/jucer_ProjectExporter.cpp | 145 +- .../ProjectSaving/jucer_ProjectExporter.h | 69 +- .../ProjectSaving/jucer_ProjectSaver.cpp | 4 +- .../Source/ProjectSaving/jucer_ProjectSaver.h | 26 +- .../ProjectSaving/jucer_ResourceFile.cpp | 263 +-- .../Source/ProjectSaving/jucer_ResourceFile.h | 42 +- .../Utility/Helpers/jucer_CodeHelpers.cpp | 199 +- .../Utility/Helpers/jucer_CodeHelpers.h | 9 - .../Utility/Helpers/jucer_FileHelpers.cpp | 98 +- .../Utility/Helpers/jucer_FileHelpers.h | 19 +- .../Utility/Helpers/jucer_MiscUtilities.cpp | 122 +- .../Utility/Helpers/jucer_MiscUtilities.h | 7 - .../Source/Utility/Helpers/jucer_PresetIDs.h | 2 + .../Utility/Helpers/jucer_RelativePath.h | 121 - .../Utility/PIPs/jucer_PIPGenerator.cpp | 129 +- .../Source/Utility/PIPs/jucer_PIPGenerator.h | 1 - .../Source/Wizards/jucer_NewFileWizard.cpp | 6 +- .../Source/Wizards/jucer_NewProjectWizard.h | 18 +- .../Wizards/jucer_ProjectWizard_Animated.h | 10 +- .../Wizards/jucer_ProjectWizard_AudioApp.h | 10 +- .../Wizards/jucer_ProjectWizard_AudioPlugin.h | 12 +- .../Wizards/jucer_ProjectWizard_Blank.h | 2 +- .../Wizards/jucer_ProjectWizard_Console.h | 4 +- .../Source/Wizards/jucer_ProjectWizard_DLL.h | 2 +- .../Wizards/jucer_ProjectWizard_GUIApp.h | 10 +- .../jucer_ProjectWizard_StaticLibrary.h | 2 +- .../Wizards/jucer_ProjectWizard_openGL.h | 10 +- extras/UnitTestRunner/CMakeLists.txt | 36 + modules/CMakeLists.txt | 41 + .../Standalone/juce_StandaloneFilterWindow.h | 2 - .../juce_audio_plugin_client.h | 2 +- .../processors/juce_AudioProcessorEditor.cpp | 8 +- modules/juce_audio_utils/juce_audio_utils.h | 2 +- .../juce_blocks_basics/juce_blocks_basics.h | 2 +- .../javacore/app/com/roli/juce/JuceApp.java | 4 +- modules/juce_dsp/juce_dsp.h | 2 +- modules/juce_osc/juce_osc.h | 2 +- .../juce_product_unlocking.h | 2 +- 149 files changed, 9921 insertions(+), 3693 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 examples/Audio/CMakeLists.txt create mode 100644 examples/BLOCKS/CMakeLists.txt create mode 100644 examples/CMake/AudioPlugin/CMakeLists.txt create mode 100644 examples/CMake/AudioPlugin/PluginEditor.cpp create mode 100644 examples/CMake/AudioPlugin/PluginEditor.h create mode 100644 examples/CMake/AudioPlugin/PluginProcessor.cpp create mode 100644 examples/CMake/AudioPlugin/PluginProcessor.h create mode 100644 examples/CMake/CMakeLists.txt create mode 100644 examples/CMake/ConsoleApp/CMakeLists.txt create mode 100644 examples/CMake/ConsoleApp/Main.cpp create mode 100644 examples/CMake/GuiApp/CMakeLists.txt create mode 100644 examples/CMake/GuiApp/Main.cpp create mode 100644 examples/CMake/GuiApp/MainComponent.cpp create mode 100644 examples/CMake/GuiApp/MainComponent.h create mode 100644 examples/CMake/readme.md create mode 100644 examples/CMakeLists.txt create mode 100644 examples/DSP/CMakeLists.txt create mode 100644 examples/DemoRunner/CMakeLists.txt create mode 100644 examples/GUI/CMakeLists.txt create mode 100644 examples/Plugins/CMakeLists.txt create mode 100644 examples/Utilities/CMakeLists.txt create mode 100644 extras/AudioPerformanceTest/CMakeLists.txt create mode 100644 extras/AudioPluginHost/CMakeLists.txt create mode 100644 extras/BinaryBuilder/CMakeLists.txt create mode 100644 extras/Build/CMake/JUCEConfig.cmake.in create mode 100644 extras/Build/CMake/JUCEUtils.cmake create mode 100644 extras/Build/CMake/LaunchScreen.storyboard create mode 100644 extras/Build/CMake/PIPAudioProcessor.cpp.in rename extras/{Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp => Build/CMake/PIPComponent.cpp.in} (70%) create mode 100644 extras/Build/CMake/PIPConsole.cpp.in rename extras/{Projucer/Source/BinaryData => Build/CMake}/RecentFilesMenuTemplate.nib (100%) rename extras/{Projucer/Source/BinaryData/Templates/jucer_UnityPluginGUIScript.cs => Build/CMake/UnityPluginGUIScript.cs.in} (78%) create mode 100644 extras/Build/CMake/copyDir.cmake create mode 100644 extras/Build/CMakeLists.txt create mode 100644 extras/Build/juce_build_tools/juce_build_tools.cpp create mode 100644 extras/Build/juce_build_tools/juce_build_tools.h create mode 100644 extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.h create mode 100644 extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.h create mode 100644 extras/Build/juce_build_tools/utils/juce_CppTokeniserFunctions.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_Entitlements.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_Entitlements.h create mode 100644 extras/Build/juce_build_tools/utils/juce_Icons.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_Icons.h create mode 100644 extras/Build/juce_build_tools/utils/juce_PlistOptions.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_PlistOptions.h create mode 100644 extras/Build/juce_build_tools/utils/juce_ProjectType.h create mode 100644 extras/Build/juce_build_tools/utils/juce_RelativePath.h create mode 100644 extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.h create mode 100644 extras/Build/juce_build_tools/utils/juce_ResourceRc.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_ResourceRc.h create mode 100644 extras/Build/juce_build_tools/utils/juce_VersionNumbers.cpp create mode 100644 extras/Build/juce_build_tools/utils/juce_VersionNumbers.h create mode 100644 extras/Build/juceaide/CMakeLists.txt create mode 100644 extras/Build/juceaide/Main.cpp create mode 100644 extras/CMakeLists.txt create mode 100644 extras/NetworkGraphicsDemo/CMakeLists.txt create mode 100644 extras/Projucer/CMakeLists.txt create mode 100644 extras/Projucer/JuceLibraryCode/include_juce_build_tools.cpp delete mode 100644 extras/Projucer/Source/Project/jucer_ProjectType.h delete mode 100644 extras/Projucer/Source/Utility/Helpers/jucer_RelativePath.h create mode 100644 extras/UnitTestRunner/CMakeLists.txt create mode 100644 modules/CMakeLists.txt diff --git a/.gitignore b/.gitignore index fc1bc1fce4..c136ece7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,6 @@ profile **/doxygen/build **/.idea extras/Projucer/JUCECompileEngine.dylib + +.idea +**/cmake-build* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..4f1bac1b25 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,103 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +cmake_minimum_required(VERSION 3.12) + +project(JUCE VERSION 6.0.0 LANGUAGES C CXX) + +set_property(GLOBAL PROPERTY USE_FOLDERS YES) + +include(extras/Build/CMake/JUCEUtils.cmake) + +set_directory_properties(PROPERTIES + JUCE_COMPANY_NAME "JUCE" + JUCE_COMPANY_WEBSITE "juce.com" + JUCE_COMPANY_EMAIL "info@juce.com" + JUCE_COMPANY_COPYRIGHT "Copyright (c) 2020 - ROLI Ltd.") + +option(JUCE_COPY_PLUGIN_AFTER_BUILD + "Whether or not plugins should be installed to the system after building" OFF) +set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD ${JUCE_COPY_PLUGIN_AFTER_BUILD}) + +set(CMAKE_CXX_EXTENSIONS FALSE) + +add_subdirectory(modules) +add_subdirectory(extras/Build) + +# If you want to build the JUCE examples with VST2/AAX support, you'll need to make the VST2/AAX +# headers visible to the juce_audio_processors module. You can either set the paths on the command +# line, (e.g. -DJUCE_GLOBAL_AAX_SDK_PATH=/path/to/sdk) if you're just building the JUCE examples, or +# you can call the `juce_set_*_sdk_path` functions in your own CMakeLists after importing JUCE. + +if(JUCE_GLOBAL_AAX_SDK_PATH) + juce_set_aax_sdk_path("${JUCE_GLOBAL_AAX_SDK_PATH}") +endif() + +if(JUCE_GLOBAL_VST2_SDK_PATH) + juce_set_vst2_sdk_path("${JUCE_GLOBAL_VST2_SDK_PATH}") +endif() + +# We don't build anything other than the juceaide by default, because we want to keep configuration +# speedy and the number of targets low. If you want to add targets for the extra projects and +# example PIPs (there's a lot of them!), specify -DJUCE_BUILD_EXAMPLES=ON and/or +# -DJUCE_BUILD_EXTRAS=ON when initially generating your build tree. + +option(JUCE_BUILD_EXTRAS "Add build targets for the Projucer and other tools" OFF) + +if(JUCE_BUILD_EXTRAS) + add_subdirectory(extras) +endif() + +option(JUCE_BUILD_EXAMPLES "Add build targets for the DemoRunner and PIPs" OFF) + +if(JUCE_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +# ================================================================================================== +# Install configuration + +include(CMakePackageConfigHelpers) +write_basic_package_version_file("${JUCE_BINARY_DIR}/JUCEConfigVersion.cmake" + VERSION ${JUCE_VERSION} + COMPATIBILITY ExactVersion + ARCH_INDEPENDENT) + +set(JUCE_INSTALL_DESTINATION "lib/cmake/JUCE-${JUCE_VERSION}" CACHE STRING + "The location, relative to the install prefix, where the JUCE config file will be installed") + +install(EXPORT JUCE NAMESPACE juce:: DESTINATION "${JUCE_INSTALL_DESTINATION}") + +configure_package_config_file("${JUCE_CMAKE_UTILS_DIR}/JUCEConfig.cmake.in" + "${JUCE_BINARY_DIR}/JUCEConfig.cmake" + INSTALL_DESTINATION "${JUCE_INSTALL_DESTINATION}") + +install(FILES "${JUCE_BINARY_DIR}/JUCEConfigVersion.cmake" + "${JUCE_BINARY_DIR}/JUCEConfig.cmake" + "${JUCE_CMAKE_UTILS_DIR}/LaunchScreen.storyboard" + "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in" + "${JUCE_CMAKE_UTILS_DIR}/PIPComponent.cpp.in" + "${JUCE_CMAKE_UTILS_DIR}/PIPConsole.cpp.in" + "${JUCE_CMAKE_UTILS_DIR}/RecentFilesMenuTemplate.nib" + "${JUCE_CMAKE_UTILS_DIR}/UnityPluginGUIScript.cs.in" + "${JUCE_CMAKE_UTILS_DIR}/copyDir.cmake" + "${JUCE_CMAKE_UTILS_DIR}/JUCEUtils.cmake" + DESTINATION "${JUCE_INSTALL_DESTINATION}") + +install(FILES "${JUCE_SOURCE_DIR}/LICENSE.md" + DESTINATION "${JUCE_INSTALL_DESTINATION}" + RENAME COPYRIGHT) + diff --git a/examples/Assets/DemoUtilities.h b/examples/Assets/DemoUtilities.h index 829a883a87..70ab73f943 100644 --- a/examples/Assets/DemoUtilities.h +++ b/examples/Assets/DemoUtilities.h @@ -58,6 +58,8 @@ inline File getExamplesDirectory() noexcept jassert (success); return mo.toString(); + #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING + return File { PIP_JUCE_EXAMPLES_DIRECTORY_STRING }; #else auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile); auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples"); diff --git a/examples/Audio/CMakeLists.txt b/examples/Audio/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/Audio/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/BLOCKS/CMakeLists.txt b/examples/BLOCKS/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/BLOCKS/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/CMake/AudioPlugin/CMakeLists.txt b/examples/CMake/AudioPlugin/CMakeLists.txt new file mode 100644 index 0000000000..40b7a7c3cf --- /dev/null +++ b/examples/CMake/AudioPlugin/CMakeLists.txt @@ -0,0 +1,104 @@ +# Example Audio Plugin CMakeLists.txt + +# To get started on a new plugin, copy this entire folder (containing this file and C++ sources) to +# a convenient location, and then start making modifications. + +# The first line of any CMake project should be a call to `cmake_minimum_required`, which checks +# that the installed CMake will be able to understand the following CMakeLists, and ensures that +# CMake's behaviour is compatible with the named version. This is a standard CMake command, so more +# information can be found in the CMake docs. + +cmake_minimum_required(VERSION 3.15) + +# The top-level CMakeLists.txt file for a project must contain a literal, direct call to the +# `project()` command. `project()` sets up some helpful variables that describe source/binary +# directories, and the current project version. This is a standard CMake command. + +project(AUDIO_PLUGIN_EXAMPLE VERSION 0.0.1) + +# If you've installed JUCE somehow (via a package manager, or directly using the CMake install +# target), you'll need to tell this project that it depends on the installed copy of JUCE. If you've +# included JUCE directly in your source tree (perhaps as a submodule), you'll need to tell CMake to +# include that subdirectory as part of the build. + +# find_package(JUCE CONFIG REQUIRED) # If you've installed JUCE to your system +# or +# add_subdirectory(JUCE) # If you've put JUCE in a subdirectory called JUCE + +# If you are building a VST2 or AAX plugin, CMake needs to be told where to find these SDKs on your +# system. This setup should be done before calling `juce_add_plugin`. + +# juce_set_vst2_sdk_path(...) +# juce_set_aax_sdk_path(...) + +# `juce_add_plugin` adds a static library target with the name passed as the first argument +# (AudioPluginExample here). This target is a normal CMake target, but has a lot of extra properties set +# up by default. As well as this shared code static library, this function adds targets for each of +# the formats specified by the FORMATS arguments. This function accepts many optional arguments. +# Check the readme at `examples/CMake` in the JUCE repo for the full list. + +juce_add_plugin(AudioPluginExample + # VERSION ... # Set this if the plugin version is different to the project version + # ICON_BIG ... # ICON_* arguments specify a path to an image file to use as an icon for the Standalone + # ICON_SMALL ... + # COMPANY_NAME ... # Specify the name of the plugin's author + # IS_SYNTH TRUE/FALSE # Is this a synth or an effect? + # NEEDS_MIDI_INPUT TRUE/FALSE # Does the plugin need midi input? + # NEEDS_MIDI_OUTPUT TRUE/FALSE # Does the plugin need midi output? + # IS_MIDI_EFFECT TRUE/FALSE # Is this plugin a MIDI effect? + # EDITOR_WANTS_KEYBOARD_FOCUS TRUE/FALSE # Does the editor need keyboard focus? + # COPY_PLUGIN_AFTER_BUILD TRUE/FALSE # Should the plugin be installed to a default location after building? + PLUGIN_MANUFACTURER_CODE Juce # A four-character manufacturer id with at least one upper-case character + PLUGIN_CODE Dem0 # A unique four-character plugin id with at least one upper-case character + FORMATS AU VST3 Standalone # The formats to build. Other valid formats are: AAX Unity VST AU AUv3 + PRODUCT_NAME "Audio Plugin Example") # The name of the final executable, which can differ from the target name + +# `juce_generate_juce_header` will create a JuceHeader.h for a given target, which will be generated +# into your build tree. This should be included with `#include `. The include path for +# this header will be automatically added to the target. The main function of the JuceHeader is to +# include all your JUCE module headers; if you're happy to include module headers directly, you +# probably don't need to call this. + +# juce_generate_juce_header(AudioPluginExample) + +# `target_sources` adds source files to a target. We pass the target that needs the sources as the +# first argument, then a visibility parameter for the sources (PRIVATE is normally best practice, +# although it doesn't really affect executable targets). Finally, we supply a list of source files +# that will be built into the target. This is a standard CMake command. + +target_sources(AudioPluginExample PRIVATE + PluginEditor.cpp + PluginProcessor.cpp) + +# `target_compile_definitions` adds some preprocessor definitions to our target. In a Projucer +# project, these might be passed in the 'Preprocessor Definitions' field. JUCE modules also make use +# of compile definitions to switch certain features on/off, so if there's a particular feature you +# need that's not on by default, check the module header for the correct flag to set here. These +# definitions will be visible both to your code, and also the JUCE module code, so for new +# definitions, pick unique names that are unlikely to collide! This is a standard CMake command. + +target_compile_definitions(AudioPluginExample + PUBLIC + # JUCE_WEB_BROWSER and JUCE_USE_CURL would be on by default, but you might not need them. + JUCE_WEB_BROWSER=0 # If you remove this, add `NEEDS_WEB_BROWSER TRUE` to the `juce_add_plugin` call + JUCE_USE_CURL=0 # If you remove this, add `NEEDS_CURL TRUE` to the `juce_add_plugin` call + JUCE_VST3_CAN_REPLACE_VST2=0) + +# If your target needs extra binary assets, you can add them here. The first argument is the name of +# a new static library target that will include all the binary resources. There is an optional +# `NAMESPACE` argument that can specify the namespace of the generated binary data class. Finally, +# the SOURCES argument should be followed by a list of source files that should be built into the +# static library. These source files can be of any kind (wav data, images, fonts, icons etc.). +# Conversion to binary-data will happen when your target is built. + +# juce_add_binary_data(AudioPluginData SOURCES ...) + +# `target_link_libraries` links libraries and JUCE modules to other libraries or executables. Here, +# we're linking our executable target to the `juce::juce_audio_utils` module. Inter-module +# dependencies are resolved automatically, so `juce_core`, `juce_events` and so on will also be +# linked automatically. If we'd generated a binary data target above, we would need to link to it +# here too. This is a standard CMake command. + +target_link_libraries(AudioPluginExample PRIVATE + # AudioPluginData # If we'd created a binary data target, we'd link to it here + juce::juce_audio_utils) diff --git a/examples/CMake/AudioPlugin/PluginEditor.cpp b/examples/CMake/AudioPlugin/PluginEditor.cpp new file mode 100644 index 0000000000..50f8eb44b9 --- /dev/null +++ b/examples/CMake/AudioPlugin/PluginEditor.cpp @@ -0,0 +1,33 @@ +#include "PluginProcessor.h" +#include "PluginEditor.h" + +//============================================================================== +AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor (AudioPluginAudioProcessor& p) + : AudioProcessorEditor (&p), processorRef (p) +{ + juce::ignoreUnused (processorRef); + // Make sure that before the constructor has finished, you've set the + // editor's size to whatever you need it to be. + setSize (400, 300); +} + +AudioPluginAudioProcessorEditor::~AudioPluginAudioProcessorEditor() +{ +} + +//============================================================================== +void AudioPluginAudioProcessorEditor::paint (juce::Graphics& g) +{ + // (Our component is opaque, so we must completely fill the background with a solid colour) + g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); + + g.setColour (juce::Colours::white); + g.setFont (15.0f); + g.drawFittedText ("Hello World!", getLocalBounds(), juce::Justification::centred, 1); +} + +void AudioPluginAudioProcessorEditor::resized() +{ + // This is generally where you'll want to lay out the positions of any + // subcomponents in your editor.. +} diff --git a/examples/CMake/AudioPlugin/PluginEditor.h b/examples/CMake/AudioPlugin/PluginEditor.h new file mode 100644 index 0000000000..ef96e04a3a --- /dev/null +++ b/examples/CMake/AudioPlugin/PluginEditor.h @@ -0,0 +1,22 @@ +#pragma once + +#include "PluginProcessor.h" + +//============================================================================== +class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor +{ +public: + explicit AudioPluginAudioProcessorEditor (AudioPluginAudioProcessor&); + ~AudioPluginAudioProcessorEditor() override; + + //============================================================================== + void paint (juce::Graphics&) override; + void resized() override; + +private: + // This reference is provided as a quick way for your editor to + // access the processor object that created it. + AudioPluginAudioProcessor& processorRef; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginAudioProcessorEditor) +}; diff --git a/examples/CMake/AudioPlugin/PluginProcessor.cpp b/examples/CMake/AudioPlugin/PluginProcessor.cpp new file mode 100644 index 0000000000..31394624a9 --- /dev/null +++ b/examples/CMake/AudioPlugin/PluginProcessor.cpp @@ -0,0 +1,186 @@ +#include "PluginProcessor.h" +#include "PluginEditor.h" + +//============================================================================== +AudioPluginAudioProcessor::AudioPluginAudioProcessor() + : AudioProcessor (BusesProperties() + #if ! JucePlugin_IsMidiEffect + #if ! JucePlugin_IsSynth + .withInput ("Input", juce::AudioChannelSet::stereo(), true) + #endif + .withOutput ("Output", juce::AudioChannelSet::stereo(), true) + #endif + ) +{ +} + +AudioPluginAudioProcessor::~AudioPluginAudioProcessor() +{ +} + +//============================================================================== +const juce::String AudioPluginAudioProcessor::getName() const +{ + return JucePlugin_Name; +} + +bool AudioPluginAudioProcessor::acceptsMidi() const +{ + #if JucePlugin_WantsMidiInput + return true; + #else + return false; + #endif +} + +bool AudioPluginAudioProcessor::producesMidi() const +{ + #if JucePlugin_ProducesMidiOutput + return true; + #else + return false; + #endif +} + +bool AudioPluginAudioProcessor::isMidiEffect() const +{ + #if JucePlugin_IsMidiEffect + return true; + #else + return false; + #endif +} + +double AudioPluginAudioProcessor::getTailLengthSeconds() const +{ + return 0.0; +} + +int AudioPluginAudioProcessor::getNumPrograms() +{ + return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, + // so this should be at least 1, even if you're not really implementing programs. +} + +int AudioPluginAudioProcessor::getCurrentProgram() +{ + return 0; +} + +void AudioPluginAudioProcessor::setCurrentProgram (int index) +{ + juce::ignoreUnused (index); +} + +const juce::String AudioPluginAudioProcessor::getProgramName (int index) +{ + juce::ignoreUnused (index); + return {}; +} + +void AudioPluginAudioProcessor::changeProgramName (int index, const juce::String& newName) +{ + juce::ignoreUnused (index, newName); +} + +//============================================================================== +void AudioPluginAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) +{ + // Use this method as the place to do any pre-playback + // initialisation that you need.. + juce::ignoreUnused (sampleRate, samplesPerBlock); +} + +void AudioPluginAudioProcessor::releaseResources() +{ + // When playback stops, you can use this as an opportunity to free up any + // spare memory, etc. +} + +bool AudioPluginAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const +{ + #if JucePlugin_IsMidiEffect + juce::ignoreUnused (layouts); + return true; + #else + // This is the place where you check if the layout is supported. + // In this template code we only support mono or stereo. + if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() + && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) + return false; + + // This checks if the input layout matches the output layout + #if ! JucePlugin_IsSynth + if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) + return false; + #endif + + return true; + #endif +} + +void AudioPluginAudioProcessor::processBlock (juce::AudioBuffer& buffer, + juce::MidiBuffer& midiMessages) +{ + juce::ignoreUnused (midiMessages); + + juce::ScopedNoDenormals noDenormals; + auto totalNumInputChannels = getTotalNumInputChannels(); + auto totalNumOutputChannels = getTotalNumOutputChannels(); + + // In case we have more outputs than inputs, this code clears any output + // channels that didn't contain input data, (because these aren't + // guaranteed to be empty - they may contain garbage). + // This is here to avoid people getting screaming feedback + // when they first compile a plugin, but obviously you don't need to keep + // this code if your algorithm always overwrites all the output channels. + for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + + // This is the place where you'd normally do the guts of your plugin's + // audio processing... + // Make sure to reset the state if your inner loop is processing + // the samples and the outer loop is handling the channels. + // Alternatively, you can process the samples with the channels + // interleaved by keeping the same state. + for (int channel = 0; channel < totalNumInputChannels; ++channel) + { + auto* channelData = buffer.getWritePointer (channel); + juce::ignoreUnused (channelData); + // ..do something to the data... + } +} + +//============================================================================== +bool AudioPluginAudioProcessor::hasEditor() const +{ + return true; // (change this to false if you choose to not supply an editor) +} + +juce::AudioProcessorEditor* AudioPluginAudioProcessor::createEditor() +{ + return new AudioPluginAudioProcessorEditor (*this); +} + +//============================================================================== +void AudioPluginAudioProcessor::getStateInformation (juce::MemoryBlock& destData) +{ + // You should use this method to store your parameters in the memory block. + // You could do that either as raw data, or use the XML or ValueTree classes + // as intermediaries to make it easy to save and load complex data. + juce::ignoreUnused (destData); +} + +void AudioPluginAudioProcessor::setStateInformation (const void* data, int sizeInBytes) +{ + // You should use this method to restore your parameters from this memory block, + // whose contents will have been created by the getStateInformation() call. + juce::ignoreUnused (data, sizeInBytes); +} + +//============================================================================== +// This creates new instances of the plugin.. +juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new AudioPluginAudioProcessor(); +} diff --git a/examples/CMake/AudioPlugin/PluginProcessor.h b/examples/CMake/AudioPlugin/PluginProcessor.h new file mode 100644 index 0000000000..d686ef3e7b --- /dev/null +++ b/examples/CMake/AudioPlugin/PluginProcessor.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +//============================================================================== +class AudioPluginAudioProcessor : public juce::AudioProcessor +{ +public: + //============================================================================== + AudioPluginAudioProcessor(); + ~AudioPluginAudioProcessor() override; + + //============================================================================== + void prepareToPlay (double sampleRate, int samplesPerBlock) override; + void releaseResources() override; + + bool isBusesLayoutSupported (const BusesLayout& layouts) const override; + + void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; + + //============================================================================== + juce::AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; + + //============================================================================== + const juce::String getName() const override; + + bool acceptsMidi() const override; + bool producesMidi() const override; + bool isMidiEffect() const override; + double getTailLengthSeconds() const override; + + //============================================================================== + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram (int index) override; + const juce::String getProgramName (int index) override; + void changeProgramName (int index, const juce::String& newName) override; + + //============================================================================== + void getStateInformation (juce::MemoryBlock& destData) override; + void setStateInformation (const void* data, int sizeInBytes) override; + +private: + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginAudioProcessor) +}; diff --git a/examples/CMake/CMakeLists.txt b/examples/CMake/CMakeLists.txt new file mode 100644 index 0000000000..877cf383f1 --- /dev/null +++ b/examples/CMake/CMakeLists.txt @@ -0,0 +1,19 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +add_subdirectory(AudioPlugin) +add_subdirectory(ConsoleApp) +add_subdirectory(GuiApp) diff --git a/examples/CMake/ConsoleApp/CMakeLists.txt b/examples/CMake/ConsoleApp/CMakeLists.txt new file mode 100644 index 0000000000..23cc1e853e --- /dev/null +++ b/examples/CMake/ConsoleApp/CMakeLists.txt @@ -0,0 +1,82 @@ +# Example Console App CMakeLists.txt + +# To get started on a new console app, copy this entire folder (containing this file and C++ +# sources) to a convenient location, and then start making modifications. For other examples of +# CMakeLists for console apps, check `extras/BinaryBuilder` and `extras/UnitTestRunner` in the JUCE +# repo. + +# The first line of any CMake project should be a call to `cmake_minimum_required`, which checks +# that the installed CMake will be able to understand the following CMakeLists, and ensures that +# CMake's behaviour is compatible with the named version. This is a standard CMake command, so more +# information can be found in the CMake docs. + +cmake_minimum_required(VERSION 3.12) + +# The top-level CMakeLists.txt file for a project must contain a literal, direct call to the +# `project()` command. `project()` sets up some helpful variables that describe source/binary +# directories, and the current project version. This is a standard CMake command. + +project(CONSOLE_APP_EXAMPLE VERSION 0.0.1) + +# If you've installed JUCE somehow (via a package manager, or directly using the CMake install +# target), you'll need to tell this project that it depends on the installed copy of JUCE. If you've +# included JUCE directly in your source tree (perhaps as a submodule), you'll need to tell CMake to +# include that subdirectory as part of the build. + +# find_package(JUCE CONFIG REQUIRED) # If you've installed JUCE to your system +# or +# add_subdirectory(JUCE) # If you've put JUCE in a subdirectory called JUCE + +# `juce_add_console_app` adds an executable target with the name passed as the first argument +# (ConsoleAppExample here). This target is a normal CMake target, but has a lot of extra properties +# set up by default. This function accepts many optional arguments. Check the readme at +# `examples/CMake/readme.md` in the JUCE repo for the full list. + +juce_add_console_app(ConsoleAppExample + PRODUCT_NAME "Console App Example") # The name of the final executable, which can differ from the target name + +# `juce_generate_juce_header` will create a JuceHeader.h for a given target, which will be generated +# into the build tree. This header should be included with `#include `. The include +# path for this header will be automatically added to the target. The main function of the +# JuceHeader is to include all the JUCE module headers for a particular target; if you're happy to +# include module headers directly, you probably don't need to call this. + +# juce_generate_juce_header(ConsoleAppExample) + +# `target_sources` adds source files to a target. We pass the target that needs the sources as the +# first argument, then a visibility parameter for the sources (PRIVATE is normally best practice, +# although it doesn't really affect executable targets). Finally, we supply a list of source files +# that will be built into the target. This is a standard CMake command. + +target_sources(ConsoleAppExample PRIVATE + Main.cpp) + +# `target_compile_definitions` adds some preprocessor definitions to our target. In a Projucer +# project, these might be passed in the 'Preprocessor Definitions' field. JUCE modules also make use +# of compile definitions to switch certain features on/off, so if there's a particular feature you +# need that's not on by default, check the module header for the correct flag to set here. These +# definitions will be visible both to your code, and also the JUCE module code, so for new +# definitions, pick unique names that are unlikely to collide! This is a standard CMake command. + +target_compile_definitions(ConsoleAppExample PRIVATE + # JUCE_WEB_BROWSER and JUCE_USE_CURL would be on by default, but you might not need them. + JUCE_WEB_BROWSER=0 # If you remove this, add `NEEDS_WEB_BROWSER TRUE` to the `juce_add_console_app` call + JUCE_USE_CURL=0) # If you remove this, add `NEEDS_CURL TRUE` to the `juce_add_console_app` call + +# If the target needs extra binary assets, they can be added here. The first argument is the name of +# a new static library target that will include all the binary resources. There is an optional +# `NAMESPACE` argument that can specify the namespace of the generated binary data class. Finally, +# the SOURCES argument should be followed by a list of source files that should be built into the +# static library. These source files can be of any kind (wav data, images, fonts, icons etc.). +# Conversion to binary-data will happen when the target is built. + +# juce_add_binary_data(ConsoleAppData SOURCES ...) + +# `target_link_libraries` links libraries and JUCE modules to other libraries or executables. Here, +# we're linking our executable target to the `juce::juce_core` module. Inter-module dependencies are +# resolved automatically. If you'd generated a binary data target above, you would need to link to +# it here too. This is a standard CMake command. + +target_link_libraries(ConsoleAppExample PRIVATE + # ConsoleAppData # If you'd created a binary data target, you'd link to it here + juce::juce_core) diff --git a/examples/CMake/ConsoleApp/Main.cpp b/examples/CMake/ConsoleApp/Main.cpp new file mode 100644 index 0000000000..7663abd0d1 --- /dev/null +++ b/examples/CMake/ConsoleApp/Main.cpp @@ -0,0 +1,10 @@ +#include + +int main (int argc, char* argv[]) +{ + + // Your code goes here! + juce::ignoreUnused (argc, argv); + + return 0; +} diff --git a/examples/CMake/GuiApp/CMakeLists.txt b/examples/CMake/GuiApp/CMakeLists.txt new file mode 100644 index 0000000000..7570b0cfa2 --- /dev/null +++ b/examples/CMake/GuiApp/CMakeLists.txt @@ -0,0 +1,95 @@ +# Example GUI App CMakeLists.txt + +# To get started on a new GUI app, copy this entire folder (containing this file and C++ sources) to +# a convenient location, and then start making modifications. For other examples of CMakeLists for +# GUI apps, check `extras/Projucer` and `examples/DemoRunner` in the JUCE repo. + +# The first line of any CMake project should be a call to `cmake_minimum_required`, which checks +# that the installed CMake will be able to understand the following CMakeLists, and ensures that +# CMake's behaviour is compatible with the named version. This is a standard CMake command, so more +# information can be found in the CMake docs. + +cmake_minimum_required(VERSION 3.12) + +# The top-level CMakeLists.txt file for a project must contain a literal, direct call to the +# `project()` command. `project()` sets up some helpful variables that describe source/binary +# directories, and the current project version. This is a standard CMake command. + +project(GUI_APP_EXAMPLE VERSION 0.0.1) + +# If you've installed JUCE somehow (via a package manager, or directly using the CMake install +# target), you'll need to tell this project that it depends on the installed copy of JUCE. If you've +# included JUCE directly in your source tree (perhaps as a submodule), you'll need to tell CMake to +# include that subdirectory as part of the build. + +# find_package(JUCE CONFIG REQUIRED) # If you've installed JUCE to your system +# or +# add_subdirectory(JUCE) # If you've put JUCE in a subdirectory called JUCE + +# If your app depends the VST2 SDK, perhaps to host VST2 plugins, CMake needs to be told where +# to find the SDK on your system. This setup should be done before calling `juce_add_gui_app`. + +# juce_set_vst2_sdk_path(...) + +# `juce_add_gui_app` adds an executable target with the name passed as the first argument +# (GuiAppExample here). This target is a normal CMake target, but has a lot of extra properties set +# up by default. This function accepts many optional arguments. Check the readme at `examples/CMake` +# in the JUCE repo for the full list. + +juce_add_gui_app(GuiAppExample + # VERSION ... # Set this if the app version is different to the project version + # ICON_BIG ... # ICON_* arguments specify a path to an image file to use as an icon + # ICON_SMALL ... + # DOCUMENT_EXTENSIONS ... # Specify file extensions that should be associated with this app + # COMPANY_NAME ... # Specify the name of the app's author + PRODUCT_NAME "Gui App Example") # The name of the final executable, which can differ from the target name + +# `juce_generate_juce_header` will create a JuceHeader.h for a given target, which will be generated +# into your build tree. This should be included with `#include `. The include path for +# this header will be automatically added to the target. The main function of the JuceHeader is to +# include all your JUCE module headers; if you're happy to include module headers directly, you +# probably don't need to call this. + +# juce_generate_juce_header(GuiAppExample) + +# `target_sources` adds source files to a target. We pass the target that needs the sources as the +# first argument, then a visibility parameter for the sources (PRIVATE is normally best practice, +# although it doesn't really affect executable targets). Finally, we supply a list of source files +# that will be built into the target. This is a standard CMake command. + +target_sources(GuiAppExample PRIVATE + Main.cpp + MainComponent.cpp) + +# `target_compile_definitions` adds some preprocessor definitions to our target. In a Projucer +# project, these might be passed in the 'Preprocessor Definitions' field. JUCE modules also make use +# of compile definitions to switch certain features on/off, so if there's a particular feature you +# need that's not on by default, check the module header for the correct flag to set here. These +# definitions will be visible both to your code, and also the JUCE module code, so for new +# definitions, pick unique names that are unlikely to collide! This is a standard CMake command. + +target_compile_definitions(GuiAppExample PRIVATE + # JUCE_WEB_BROWSER and JUCE_USE_CURL would be on by default, but you might not need them. + JUCE_WEB_BROWSER=0 # If you remove this, add `NEEDS_WEB_BROWSER TRUE` to the `juce_add_gui_app` call + JUCE_USE_CURL=0 # If you remove this, add `NEEDS_CURL TRUE` to the `juce_add_gui_app` call + JUCE_APPLICATION_NAME_STRING="$" + JUCE_APPLICATION_VERSION_STRING="$") + +# If your target needs extra binary assets, you can add them here. The first argument is the name of +# a new static library target that will include all the binary resources. There is an optional +# `NAMESPACE` argument that can specify the namespace of the generated binary data class. Finally, +# the SOURCES argument should be followed by a list of source files that should be built into the +# static library. These source files can be of any kind (wav data, images, fonts, icons etc.). +# Conversion to binary-data will happen when your target is built. + +# juce_add_binary_data(GuiAppData SOURCES ...) + +# `target_link_libraries` links libraries and JUCE modules to other libraries or executables. Here, +# we're linking our executable target to the `juce::juce_gui_extra` module. Inter-module +# dependencies are resolved automatically, so `juce_core`, `juce_events` and so on will also be +# linked automatically. If we'd generated a binary data target above, we would need to link to it +# here too. This is a standard CMake command. + +target_link_libraries(GuiAppExample PRIVATE + # GuiAppData # If we'd created a binary data target, we'd link to it here + juce::juce_gui_extra) diff --git a/examples/CMake/GuiApp/Main.cpp b/examples/CMake/GuiApp/Main.cpp new file mode 100644 index 0000000000..72aa7bbd74 --- /dev/null +++ b/examples/CMake/GuiApp/Main.cpp @@ -0,0 +1,101 @@ +#include "MainComponent.h" + +//============================================================================== +class GuiAppApplication : public juce::JUCEApplication +{ +public: + //============================================================================== + GuiAppApplication() {} + + // We inject these as compile definitions from the CMakeLists.txt + // If you've enabled the juce header with `juce_generate_juce_header()` + // you could `#include ` and use `ProjectInfo::projectName` etc. instead. + const juce::String getApplicationName() override { return JUCE_APPLICATION_NAME_STRING; } + const juce::String getApplicationVersion() override { return JUCE_APPLICATION_VERSION_STRING; } + bool moreThanOneInstanceAllowed() override { return true; } + + //============================================================================== + void initialise (const juce::String& commandLine) override + { + // This method is where you should put your application's initialisation code.. + juce::ignoreUnused (commandLine); + + mainWindow.reset (new MainWindow (getApplicationName())); + } + + void shutdown() override + { + // Add your application's shutdown code here.. + + mainWindow = nullptr; // (deletes our window) + } + + //============================================================================== + void systemRequestedQuit() override + { + // This is called when the app is being asked to quit: you can ignore this + // request and let the app carry on running, or call quit() to allow the app to close. + quit(); + } + + void anotherInstanceStarted (const juce::String& commandLine) override + { + // When another instance of the app is launched while this one is running, + // this method is invoked, and the commandLine parameter tells you what + // the other instance's command-line arguments were. + juce::ignoreUnused (commandLine); + } + + //============================================================================== + /* + This class implements the desktop window that contains an instance of + our MainComponent class. + */ + class MainWindow : public juce::DocumentWindow + { + public: + explicit MainWindow (juce::String name) + : DocumentWindow (name, + juce::Desktop::getInstance().getDefaultLookAndFeel() + .findColour (ResizableWindow::backgroundColourId), + DocumentWindow::allButtons) + { + setUsingNativeTitleBar (true); + setContentOwned (new MainComponent(), true); + + #if JUCE_IOS || JUCE_ANDROID + setFullScreen (true); + #else + setResizable (true, true); + centreWithSize (getWidth(), getHeight()); + #endif + + setVisible (true); + } + + void closeButtonPressed() override + { + // This is called when the user tries to close this window. Here, we'll just + // ask the app to quit when this happens, but you can change this to do + // whatever you need. + JUCEApplication::getInstance()->systemRequestedQuit(); + } + + /* Note: Be careful if you override any DocumentWindow methods - the base + class uses a lot of them, so by overriding you might break its functionality. + It's best to do all your work in your content component instead, but if + you really have to override any DocumentWindow methods, make sure your + subclass also calls the superclass's method. + */ + + private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) + }; + +private: + std::unique_ptr mainWindow; +}; + +//============================================================================== +// This macro generates the main() routine that launches the app. +START_JUCE_APPLICATION (GuiAppApplication) diff --git a/examples/CMake/GuiApp/MainComponent.cpp b/examples/CMake/GuiApp/MainComponent.cpp new file mode 100644 index 0000000000..82fee61a18 --- /dev/null +++ b/examples/CMake/GuiApp/MainComponent.cpp @@ -0,0 +1,25 @@ +#include "MainComponent.h" + +//============================================================================== +MainComponent::MainComponent() +{ + setSize (600, 400); +} + +//============================================================================== +void MainComponent::paint (juce::Graphics& g) +{ + // (Our component is opaque, so we must completely fill the background with a solid colour) + g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); + + g.setFont (juce::Font (16.0f)); + g.setColour (juce::Colours::white); + g.drawText ("Hello World!", getLocalBounds(), juce::Justification::centred, true); +} + +void MainComponent::resized() +{ + // This is called when the MainComponent is resized. + // If you add any child components, this is where you should + // update their positions. +} diff --git a/examples/CMake/GuiApp/MainComponent.h b/examples/CMake/GuiApp/MainComponent.h new file mode 100644 index 0000000000..042c8cb6ac --- /dev/null +++ b/examples/CMake/GuiApp/MainComponent.h @@ -0,0 +1,29 @@ +#pragma once + +// CMake builds don't use an AppConfig.h, so it's safe to include juce module headers +// directly. If you need to remain compatible with Projucer-generated builds, and +// have called `juce_generate_juce_header()` in your CMakeLists.txt, +// you could `#include ` here instead, to make all your module headers visible. +#include + +//============================================================================== +/* + This component lives inside our window, and this is where you should put all + your controls and content. +*/ +class MainComponent : public juce::Component +{ +public: + //============================================================================== + MainComponent(); + + //============================================================================== + void paint (juce::Graphics&) override; + void resized() override; + +private: + //============================================================================== + // Your private member variables go here... + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent) +}; diff --git a/examples/CMake/readme.md b/examples/CMake/readme.md new file mode 100644 index 0000000000..32436d6b39 --- /dev/null +++ b/examples/CMake/readme.md @@ -0,0 +1,513 @@ +# CMake Template Projects + +This directory contains project templates which should help you get started using JUCE's CMake +support. + +## System Requirements + +- Console and GUI projects require CMake 3.12 or higher. +- Plugin projects require CMake 3.15 or higher. +- All iOS targets require CMake 3.14 or higher (3.15 or higher for plugins targeting iOS). +- Android targets are not currently supported. + +Most system package managers have packages for CMake, but we recommend using the most recent release +from https://cmake.org/download. You should always use a CMake that's newer than your build +toolchain, so that CMake can identify your build tools and understand how to invoke them. + +In addition to CMake you'll need a build toolchain for your platform, such as Xcode or MSVC. + +## Getting Started + +In this directory, you'll find example projects for a GUI app, a console app, and an audio plugin. +You can simply copy one of these subdirectories out of the JUCE repo, add JUCE as a submodule, and +uncomment the call to `add_subdirectory` where indicated in the CMakeLists.txt. Alternatively, if +you've installed JUCE using a package manager or the CMake install target, you can uncomment the +call to `find_package`. + +Once your project is set up, you can generate a build tree for it in the normal way. To get started, +you might invoke CMake like this, from the new directory you created. + +``` +cmake -Bbuild (-GgeneratorName) (-DJUCE_BUILD_EXTRAS=ON) (-DJUCE_BUILD_EXAMPLES=ON) +``` + +This will create a build tree in a directory named 'build', using the CMakeLists in the current +working directory, using the default generator (makefiles on mac/linux, and the most recent Visual +Studio on Windows). You can choose a specific generator to use with the `-G` flag (call `cmake -G` +to see a full list of generators on your platform). If you included JUCE as a subdirectory, you can +enable the Extras and Examples targets by including the last two arguments (they're off by default). +There's quite a lot of example projects, and generating project files might take a bit longer when +these options are on, so you probably won't want to include them most of the time. + +Then, to build the project: + +``` +cmake --build build (--target targetNameFromCMakeLists) (--config Release/Debug/...) +``` + +This tells cmake to build the target named `targetNameFromCMakeLists`, in the specified +configuration, using the appropriate tool. Of course, if you generated makefiles or ninja files, you +could call `make` or `ninja` in the build directory. If you generated an IDE project, like an Xcode +or Visual Studio project, then you could open the generated project in your IDE. + +### Building for iOS + +To build for iOS, you'll need CMake 3.14 or higher. Using the Xcode generator is highly recommended, +as other generators may not automatically find the correct SDK for the iPhone simulator, and may +fail to run certain parts of the build, such as compiling icons and processing the app's plist. By +default, CMake will build for the same system that originally configured the project, so to enable +cross-compilation for iOS, a few extra flags must be passed to the initial CMake invocation: + +``` +cmake -Bbuild-ios -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 +``` + +Here we create a build tree in the directory named 'build-ios', using the Xcode generator. The +`-DCMAKE_SYSTEM_NAME=iOS` option tells CMake to enable cross-compiling for iOS. The +`-DCMAKE_OSX_DEPLOYMENT_TARGET=9.3` option sets the minimum deployment target (it applies to iOS +despite the 'OSX' in the variable name!). + +Once the project has generated, we can open it as normal in Xcode (look for the project file in the +build directory). Alternatively, to build from the command-line, we could run this command: + +``` +cmake --build build-ios --target -- -sdk iphonesimulator +``` + +Here, we're building the target named `` from the build tree in the directory +`build-ios`. All the arguments after `--` are ignored by CMake, and are passed through to the +underlying build tool. In this case, the build tool will be `xcodebuild` because we used the Xcode +generator above. We tell xcodebuild that we're building the app for the iOS simulator, which doesn't +require special code signing. + +If we wanted to build for a real device, we would need to pass some extra signing details to the +initial CMake configuration command: + +``` +cmake -Bbuild-ios -GXcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 \ + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY="iPhone Developer" + -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=<10 character id> +``` + +The `CODE_SIGN_IDENTITY` is the kind of certificate you want to use (iPhone Developer is appropriate +for development) and `DEVELOPMENT_TEAM` is the 10-character ID that can be found by opening the +Keychain Access app, finding your development certificate, and checking its 'Organizational Unit' +info field. + +When building the target, you may also need to tell Xcode that it can automatically update +provisioning profiles, which is achieved by passing the `-allowProvisioningUpdates` flag: + +``` +cmake --build build-ios --target -- -allowProvisioningUpdates +``` + +## API Reference + +### `juce_add_` + +``` +juce_add_gui_app( [KEY value]...) +juce_add_console_app( [KEY value]...) +juce_add_plugin( [KEY value]...) +``` + +`juce_add_gui_app` and `juce_add_console_app` add an executable target with name ``. +`juce_add_plugin` adds a 'shared code' static library target with name ``, along with extra +targets for each of the specified plugin formats. Each of these functions also takes a number of +optional arguments in the form of a `KEY` followed by one or more `value`s which can be used to set +additional attributes of the target. If these optional arguments aren't specified, their values will +fall back to sensible defaults. + +Each of these arguments adds a property to the resulting target in the form `JUCE_paramName`, where +`paramName` is one of the parameter keys below. For example, after a call to +`juce_add_gui_app(my_target PRODUCT_NAME "Target")`, the target `my_target` will have a property +named `JUCE_PRODUCT_NAME` with the value `"Target"`. After creating a target with one of these +commands, properties beginning with `JUCE_` can be _queried_, but changing their values might not +have any effect (or might even break things in unexpected ways!), so always pass JUCE target +attributes directly to these creation functions, rather than adding them later. + +- `PRODUCT_NAME` + - The name of the output built by this target, similar to CMake's `OUTPUT_NAME` property. If not + specified, this will default to the target name. + +- `VERSION` + - A version number string in the format "major.minor.bugfix". If not specified, the `VERSION` of + the project containing the target will be used instead. + +- `BUNDLE_ID` + - An identifier string in the form "com.yourcompany.productname" which should uniquely identify + this target. Mainly used for macOS builds. If not specified, a default will be generated using + the target's `COMPANY_NAME` and `PRODUCT_NAME`. + +- `MICROPHONE_PERMISSION_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an app's Info.plist. + +- `MICROPHONE_PERMISSION_TEXT` + - The text your app will display when it requests microphone permissions. + +- `CAMERA_PERMISSION_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an app's Info.plist. + +- `CAMERA_PERMISSION_TEXT` + - The text your app will display when it requests camera permissions. + +- `BLUETOOTH_PERMISSION_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `BLUETOOTH_PERMISSION_TEXT` + - The text your iOS app will display when it requests bluetooth permissions. + +- `SEND_APPLE_EVENTS_PERMISSION_ENABLED` + - May be either TRUE or FALSE. Enable this to allow your app to send Apple events. + +- `SEND_APPLE_EVENTS_PERMISSION_TEXT` + - The text your app will display when it requests permission to send Apple events. + +- `FILE_SHARING_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `DOCUMENT_BROWSER_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `STATUS_BAR_HIDDEN` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `BACKGROUND_AUDIO_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `BACKGROUND_BLE_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's Info.plist. + +- `APP_GROUPS_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's entitlements. + +- `APP_GROUP_IDS` + - The app groups to which your iOS app belongs. These will be added to your app's entitlements. + +- `ICLOUD_PERMISSIONS_ENABLED` + - May be either TRUE or FALSE. Adds the appropriate entries to an iOS app's entitlements. + +- `IPHONE_SCREEN_ORIENTATIONS` + - May be, `portrait`, `landscape`, or both (separated by a space). Adds the appropriate entries to + an iPhone app's Info.plist. + +- `IPAD_SCREEN_ORIENTATIONS` + - May be, `portrait`, `landscape`, or both (separated by a space). Adds the appropriate entries to + an iPad app's Info.plist. + +- `LAUNCH_STORYBOARD_FILE` + - A custom launch storyboard file to use on iOS. If not supplied, a default storyboard will be + used. + +- `CUSTOM_XCASSETS_FOLDER` + - A path to an xcassets directory, containing icons and/or launch images for this target. If this + is specified, the ICON_BIG and ICON_SMALL arguments will not have an effect on iOS, and a launch + storyboard will not be used. + +- `ICON_BIG`, `ICON_SMALL` + - Paths to image files that will be used to generate app icons. If only one of these parameters + is specified, then that image will be used for all icon resolutions. If both arguments are + specified, then the appropriate image will be picked for each icon resolution. + +- `COMPANY_COPYRIGHT` + - Copyright text which will be added to the app/plugin's Info.plist. The value of this argument + will be inherited from the `JUCE_COMPANY_COPYRIGHT` property, so if you want to use the same + `COMPANY_COPYRIGHT` for several targets in a build tree, you can call + `set_directory_properties(PROPERTIES JUCE_COMPANY_COPYRIGHT ...)` after including JUCE but + before adding the targets, and then omit the `COMPANY_COPYRIGHT` argument when creating the + individual targets. + +- `COMPANY_NAME` + - The name of this target's author. Will be added to the app/plugin's Info.plist, and may be used + to generate part of the `BUNDLE_ID` if no ID was given explicitly. The value of this argument + will be inherited from the `JUCE_COMPANY_NAME` property, so if you want to use the same + `COMPANY_NAME` for several targets in a build tree, you can call + `set_directory_properties(PROPERTIES JUCE_COMPANY_NAME ...)` after including JUCE but before + adding the targets, and then omit the `COMPANY_NAME` argument when creating the individual + targets. + +- `COMPANY_WEBSITE` + - The address of a website related to this target in some way. The value of this argument will be + inherited from the `JUCE_COMPANY_WEBSITE` property, so if you want to use the same + `COMPANY_WEBSITE` for several targets in a build tree, you can call + `set_directory_properties(PROPERTIES JUCE_COMPANY_WEBSITE ...)` after including JUCE but before + adding the targets, and then omit the `COMPANY_WEBSITE` argument when creating the individual + targets. + +- `COMPANY_EMAIL` + - An email address for this target's author. The value of this argument will be inherited from the + `JUCE_COMPANY_EMAIL` property, so if you want to use the same `COMPANY_EMAIL` for several + targets in a build tree, you can call `set_directory_properties(PROPERTIES JUCE_COMPANY_EMAIL + ...)` after including JUCE but before adding the targets, and then omit the `COMPANY_EMAIL` + argument when creating the individual targets. + +- `DOCUMENT_EXTENSIONS` + - File extensions that should be associated with this target. For example, the Projucer passes + the string `jucer` because it wants to open `.jucer` files. If your target has several different + document types, you can pass them as multiple arguments, e.g. `DOCUMENT_EXTENSIONS wav mp3 aif`. + +- `NEEDS_CURL` + - On Linux, JUCE may or may not need to link to Curl depending on the compile definitions that are + set on a JUCE target. By default, we don't link Curl because you might not need it, but if you + get linker or include errors that reference Curl, just set this argument to `TRUE`. + +- `NEEDS_WEB_BROWSER` + - On Linux, JUCE may or may not need to link to Webkit depending on the compile definitions that + are set on a JUCE target. By default, we don't link Webkit because you might not need it, but + if you get linker or include errors that reference Webkit, just set this argument to `TRUE`. + +- `NEEDS_STORE_KIT` + - On macOS, JUCE may or may not need to link to StoreKit depending on the compile definitions that + are set on a JUCE target. By default, we don't link StoreKit because you might not need it, but + if you get linker or include errors that reference StoreKit, just set this argument to `TRUE`. + +- `PUSH_NOTIFICATIONS_ENABLED` + - Sets app entitlements to allow push notifications. False by default. + +- `HARDENED_RUNTIME_ENABLED` + - Enables macOS' hardened runtime for this target. Required for notarisation. False by default. + +- `HARDENED_RUNTIME_OPTIONS` + - A set of space-separated entitlement keys that will be added to this target's entitlements + plist if `HARDENED_RUNTIME_ENABLED` is `TRUE`. Each key should be in the form + `com.apple.security.*` where `*` is a specific entitlement. + +- `APP_SANDBOX_ENABLED` + - Enables macOS' app sandbox for this target. False by default. + +- `APP_SANDBOX_INHERIT` + - Allows child processes to inherit the static entitlements of their parent process. If this + is set to `TRUE`, no other app sandbox entitlements will be set on this target. + +- `APP_SANDBOX_OPTIONS` + - A set of space-separated entitlement keys that will be added to this target's entitlements + plist if `APP_SANDBOX_ENABLED` is `TRUE`. Each key should be in the form `com.apple.security.*` + where `*` is a specific entitlement. + +- `PLIST_TO_MERGE` + - A string to insert into an app/plugin's Info.plist. + +- `FORMATS` + - For plugin targets, specifies the plugin targets to build. Should be provided as a + space-separated list. Valid values are `Standalone Unity VST3 AU AUv3 AAX VST`. `AU` and `AUv3` + plugins will only be enabled when building on macOS. It is an error to pass `AAX` or `VST` + without first calling `juce_set_aax_sdk_path` or `juce_set_vst2_sdk_path` respectively. + +- `PLUGIN_MANUFACTURER_CODE` + - A four-character unique ID for your company. For AU compatibility, this must contain at least + one upper-case letter. + +- `PLUGIN_CODE` + - A four-character unique ID for your plugin. For AU compatibility, this must contain at least + one upper-case letter. + +- `DESCRIPTION` + - A short description of your plugin. + +- `IS_SYNTH` + - Whether the plugin is a synth. Will be used to set sensible plugin category values if they + are not provided explicitly. + +- `NEEDS_MIDI_INPUT` + - Whether the plugin should provide a midi input. + +- `NEEDS_MIDI_OUTPUT` + - Whether the plugin should provide a midi output. + +- `IS_MIDI_EFFECT` + - Whether the plugin is a MIDI effect (some hosts provide a special channel-strip location for + MIDI effect plugins). + +- `EDITOR_WANTS_KEYBOARD_FOCUS` + - Whether the plugin requires keyboard focus, or should defer all keyboard handling to the host. + +- `DISABLE_AAX_BYPASS` + - Whether the AAX bypass function should be disabled. + +- `DISABLE_AAX_MULTI_MONO` + - Whether the AAX multi mono bus layout should be disabled. + +- `AAX_IDENTIFIER` + - The bundle ID for the AAX plugin target. Matches the `BUNDLE_ID` by default. + +- `VST_NUM_MIDI_INS` + - For VST2 and VST3 plugins that accept midi, this allows you to configure the number of inputs. + +- `VST_NUM_MIDI_OUTS` + - For VST2 and VST3 plugins that produce midi, this allows you to configure the number of outputs. + +- `VST2_CATEGORY` + - Should be one of: `kPlugCategUnknown`, `kPlugCategEffect`, `kPlugCategSynth`, + `kPlugCategAnalysis`, `kPlugCategMatering`, `kPlugCategSpacializer`, `kPlugCategRoomFx`, + `kPlugSurroundFx`, `kPlugCategRestoration`, `kPlugCategOfflineProcess`, `kPlugCategShell`, + `kPlugCategGenerator`. + +- `VST3_CATEGORIES` + - Should be one or more, separated by spaces, of the following: `Fx`, `Instrument`, `Analyzer`, + `Delay`, `Distortion`, `Drum`, `Dynamics`, `EQ`, `External`, `Filter`, `Generator`, `Mastering`, + `Modulation`, `Mono`, `Network`, `NoOfflineProcess`, `OnlyOfflineProcess`, `OnlyRT`, + `Pitch Shift`, `Restoration`, `Reverb`, `Sampler`, `Spatial`, `Stereo`, `Surround`, `Synth`, + `Tools`, `Up-Downmix` + +- `AU_MAIN_TYPE` + - Should be one of: `kAudioUnitType_Effect`, `kAudioUnitType_FormatConverter`, + `kAudioUnitType_Generator`, `kAudioUnitType_MIDIProcessor`, `kAudioUnitType_Mixer`, + `kAudioUnitType_MusicDevice`, `kAudioUnitType_MusicEffect`, `kAudioUnitType_OfflineEffect`, + `kAudioUnitType_Output`, `kAudioUnitType_Panner` + +- `AU_EXPORT_PREFIX` + - A prefix for the names of entry-point functions that your component exposes. Typically this + will be a version of your plugin's name that can be used as part of a C++ token. Defaults + to your plugin's name with the suffix 'AU'. + +- `AU_SANDBOX_SAFE` + - May be either TRUE or FALSE. Adds the appropriate entries to an AU plugin's Info.plist. + +- `AAX_CATEGORY` + - Should be one of: `AAX_ePlugInCategory_None`, `AAX_ePlugInCategory_EQ`, + `AAX_ePlugInCategory_Dynamics`, `AAX_ePlugInCategory_PitchShift`, `AAX_ePlugInCategory_Reverb`, + `AAX_ePlugInCategory_Delay`, `AAX_ePlugInCategory_Modulation`, `AAX_ePlugInCategory_Harmonic`, + `AAX_ePlugInCategory_NoiseReduction`, `AAX_ePlugInCategory_Dither`, + `AAX_ePlugInCategory_SoundField`, `AAX_ePlugInCategory_HWGenerators`, + `AAX_ePlugInCategory_SWGenerators`, `AAX_ePlugInCategory_WrappedPlugin`, + `AAX_ePlugInCategory_Effect` + +- `COPY_PLUGIN_AFTER_BUILD` + - Whether or not to install the plugin to the current system after building. False by default. + If you want all of the plugins in a subdirectory to be installed automatically after building, + you can set the property `JUCE_COPY_PLUGIN_AFTER_BUILD` on the directory before adding the + plugins, rather than setting this argument on each individual target. Note that on Windows, + the default install locations may not be writable by normal user accounts. + +- `VST_COPY_DIR` + - The location to which VST2 (legacy) plugins will be copied after building if + `COPY_PLUGIN_AFTER_BUILD` is set on this target. If you want to install all of the VST2 plugins + in a subdirectory to a non-default location, you can set the `JUCE_VST_COPY_DIR` property on + the directory before adding the plugin targets, rather than setting this argument on each + individual target. + +- `VST3_COPY_DIR` + - The location to which VST3 plugins will be copied after building if `COPY_PLUGIN_AFTER_BUILD` + is set on this target. If you want to install all of the VST3 plugins in a subdirectory to a + non-default location, you can set the `JUCE_VST3_COPY_DIR` property on the directory before + adding the plugin targets, rather than setting this argument on each individual target. + +- `AAX_COPY_DIR` + - The location to which AAX plugins will be copied after building if `COPY_PLUGIN_AFTER_BUILD` + is set on this target. If you want to install all of the AAX plugins in a subdirectory to a + non-default location, you can set the `JUCE_AAX_COPY_DIR` property on the directory before + adding the plugin targets, rather than setting this argument on each individual target. + +- `AU_COPY_DIR` + - The location to which AU plugins will be copied after building if `COPY_PLUGIN_AFTER_BUILD` + is set on this target. If you want to install all of the AU plugins in a subdirectory to a + non-default location, you can set the `JUCE_AU_COPY_DIR` property on the directory before + adding the plugin targets, rather than setting this argument on each individual target. + +- `UNITY_COPY_DIR` + - The location to which Unity plugins will be copied after building if `COPY_PLUGIN_AFTER_BUILD` + is set on this target. If you want to install all of the Unity plugins in a subdirectory to a + non-default location, you can set the `JUCE_UNITY_COPY_DIR` property on the directory before + adding the plugin targets, rather than setting this argument on each individual target. + Unlike the other `COPY_DIR` arguments, this argument does not have a default value so be sure + to set it if you have enabled `COPY_PLUGIN_AFTER_BUILD` and the `Unity` format. + +### `juce_add_binary_data` + +``` +juce_add_binary_data( + [NAMESPACE ...] + SOURCES ...) +``` + +Create a static library that embeds the contents of the files passed as arguments to this function. +Adds a library target called `` which can be linked into other targets using +`target_link_libraries`. The `NAMESPACE` argument is optional. If not provided, the generated files +will use the default namespace `BinaryData`. Each of the files located at the paths following +`SOURCES` will be encoded and embedded in the resulting static library. This library can be linked +as normal using `target_link_libraries( PRIVATE )`, and the header can be +included using `#include `. + +### `juce_add_bundle_resources_directory` + +``` +juce_add_bundle_resources_directory( ) +``` + +Copy the entire directory at the location `` into an Apple bundle's resource directory, i.e. +the `Resources` directory for a macOS bundle, and the top-level directory of an iOS bundle. + +### `juce_generate_juce_header` + +``` +juce_generate_juce_header() +``` + +Introspects the JUCE modules that have been linked to `` and generates a `JuceHeader.h` +which contains `#include` statements for each of the module headers. This header also contains an +optional `using namespace juce` statement, and an optional `ProjectInfo` block, each of which can be +disabled by setting the compile definitions `DONT_SET_USING_JUCE_NAMESPACE` and +`JUCE_DONT_DECLARE_PROJECTINFO` respectively. The resulting header can be included with `#include +`. In plain CMake projects which don't require Projucer compatibility, the use of +JuceHeader.h is optional. Instead, module headers can be included directly in source files that +require them. + +### `juce_set__sdk_path` + +``` +juce_set_aax_sdk_path() +juce_set_vst2_sdk_path() +``` + +Call these functions from your CMakeLists to set up your local AAX and/or VST2 SDKs. These functions +should be called *before* adding any targets that may depend on the AAX/VST2 SDKs (plugin +hosts, VST2/AAX plugins etc.). + +### `juce_add_module` + +``` +juce_add_module() +juce_add_modules(...) +``` + +`juce_add_module` adds a library target for the JUCE module located at the provided path. `` +must be the path to a module directory (e.g. /Users/me/JUCE/modules/juce_core). This will add an +interface library with a name matching the directory name of the module. The resulting library can +be linked to other targets as normal, using `target_link_libraries`. + +Due to the way that `INTERFACE` libraries work in CMake, linking to a module added in this way +*must* be done using `PRIVATE` visibility. Using `PUBLIC` will cause the module sources to be added +both to the target's `SOURCES` and `INTERFACE_SOURCES`, which may result in many copies of the +module being built into a single target, which would cause build failures in the best case and +silent ODR violations in the worst case. Scary stuff! + +This command has a few optional arguments: `INSTALL_PATH` and `INSTALL_EXPORT` should be provided if +you want the module to be installable through the CMake installation mechanism. `INSTALL_PATH` is a +path, relative to the install prefix, to which the module sources will be copied. `INSTALL_EXPORT` +specifies the CMake export group for the installed module. ALIAS_NAMESPACE will add an alias for the +target(s) with the provided namespace. For example, the following invocation will add a module +target named `my_module`, along with an alias named `company::my_module`. +``` +juce_add_module(my_module ALIAS_NAMESPACE company)` +``` + +`juce_add_modules` is a convenience function that can be used to add multiple JUCE modules at once. +This version accepts many module paths, rather than just one. For an example of usage, see the +CMakeLists in the `modules` directory. + +### `juce_add_pip` + +``` +juce_add_pip(
) +``` + +This function parses the PIP metadata block in the provided header, and adds appropriate build +targets for a console app, GUI app, or audio plugin. For audio plugin targets, it builds as many +plugin formats as possible. To build AAX or VST2 targets, call `juce_set_aax_sdk_path` and/or +`juce_set_vst2_sdk_path` *before* calling `juce_add_pip`. + +This is mainly provided to build the built-in example projects in the JUCE repo, and for building +quick proof-of-concept demo apps with minimal set-up. For any use-case more complex than a +proof-of-concept, you should prefer the `juce_add_gui_app`, `juce_add_plugin`, or +`juce_add_console_app` functions, which provide more fine-grained control over the properties of +your target. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000000..4c4aef41bf --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,35 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +add_subdirectory(CMake) +add_subdirectory(DemoRunner) + +function(_juce_add_pips) + file(GLOB_RECURSE headers + CONFIGURE_DEPENDS LIST_DIRECTORIES false + "${CMAKE_CURRENT_SOURCE_DIR}/*.h") + + foreach(header IN ITEMS ${headers}) + juce_add_pip(${header}) + endforeach() +endfunction() + +add_subdirectory(Audio) +add_subdirectory(BLOCKS) +add_subdirectory(DSP) +add_subdirectory(GUI) +add_subdirectory(Plugins) +add_subdirectory(Utilities) diff --git a/examples/DSP/CMakeLists.txt b/examples/DSP/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/DSP/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h b/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h index 829a883a87..70ab73f943 100644 --- a/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h +++ b/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h @@ -58,6 +58,8 @@ inline File getExamplesDirectory() noexcept jassert (success); return mo.toString(); + #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING + return File { PIP_JUCE_EXAMPLES_DIRECTORY_STRING }; #else auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile); auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples"); diff --git a/examples/DemoRunner/CMakeLists.txt b/examples/DemoRunner/CMakeLists.txt new file mode 100644 index 0000000000..d93e607713 --- /dev/null +++ b/examples/DemoRunner/CMakeLists.txt @@ -0,0 +1,64 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_gui_app(DemoRunner + BUNDLE_ID com.juce.demorunner + ICON_BIG ${CMAKE_CURRENT_SOURCE_DIR}/Source/JUCEAppIcon.png + NEEDS_CURL TRUE + NEEDS_WEB_BROWSER TRUE + MICROPHONE_PERMISSION_ENABLED TRUE + CAMERA_PERMISSION_ENABLED TRUE + BLUETOOTH_PERMISSION_ENABLED TRUE + FILE_SHARING_ENABLED TRUE + DOCUMENT_BROWSER_ENABLED TRUE + IPHONE_SCREEN_ORIENTATIONS portrait landscape + IPAD_SCREEN_ORIENTATIONS portrait landscape) + +juce_generate_juce_header(DemoRunner) + +target_sources(DemoRunner PRIVATE + Source/Demos/DemoPIPs1.cpp + Source/Demos/DemoPIPs2.cpp + Source/Demos/JUCEDemos.cpp + Source/Main.cpp + Source/UI/DemoContentComponent.cpp + Source/UI/MainComponent.cpp) + +target_compile_definitions(DemoRunner PRIVATE + PIP_JUCE_EXAMPLES_DIRECTORY_STRING="${JUCE_SOURCE_DIR}/examples" + JUCE_ALLOW_STATIC_NULL_VARIABLES=0 + JUCE_DEMO_RUNNER=1 + JUCE_STRICT_REFCOUNTEDPOINTER=1 + JUCE_UNIT_TESTS=1 + JUCE_USE_CAMERA=1 + JUCE_USE_CURL=1 + JUCE_USE_MP3AUDIOFORMAT=1 + JUCE_WEB_BROWSER=1) + +target_link_libraries(DemoRunner PRIVATE + juce::juce_analytics + juce::juce_audio_utils + juce::juce_blocks_basics + juce::juce_box2d + juce::juce_dsp + juce::juce_opengl + juce::juce_osc + juce::juce_product_unlocking + juce::juce_video) + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + juce_add_bundle_resources_directory(DemoRunner ../Assets) +endif() diff --git a/examples/GUI/CMakeLists.txt b/examples/GUI/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/GUI/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/Plugins/AUv3SynthPluginDemo.h b/examples/Plugins/AUv3SynthPluginDemo.h index b4f6516293..c5f6f6a21d 100644 --- a/examples/Plugins/AUv3SynthPluginDemo.h +++ b/examples/Plugins/AUv3SynthPluginDemo.h @@ -23,24 +23,27 @@ BEGIN_JUCE_PIP_METADATA - name: AUv3SynthPlugin - version: 1.0.0 - vendor: JUCE - website: http://juce.com - description: AUv3 synthesiser audio plugin. + name: AUv3SynthPlugin + version: 1.0.0 + vendor: JUCE + website: http://juce.com + description: AUv3 synthesiser audio plugin. - dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, - juce_audio_plugin_client, juce_audio_processors, - juce_audio_utils, juce_core, juce_data_structures, - juce_events, juce_graphics, juce_gui_basics, juce_gui_extra - exporters: xcode_mac, xcode_iphone + dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, + juce_audio_plugin_client, juce_audio_processors, + juce_audio_utils, juce_core, juce_data_structures, + juce_events, juce_graphics, juce_gui_basics, juce_gui_extra + exporters: xcode_mac, xcode_iphone - moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 - type: AudioProcessor - mainClass: AUv3SynthProcessor + type: AudioProcessor + mainClass: AUv3SynthProcessor - useLocalCopy: 1 + useLocalCopy: 1 + + pluginCharacteristics: pluginIsSynth, pluginWantsMidiIn + extraPluginFormats: AUv3 END_JUCE_PIP_METADATA diff --git a/examples/Plugins/ArpeggiatorPluginDemo.h b/examples/Plugins/ArpeggiatorPluginDemo.h index 74e5c9c15d..2062d2de98 100644 --- a/examples/Plugins/ArpeggiatorPluginDemo.h +++ b/examples/Plugins/ArpeggiatorPluginDemo.h @@ -23,24 +23,26 @@ BEGIN_JUCE_PIP_METADATA - name: ArpeggiatorPlugin - version: 1.0.0 - vendor: JUCE - website: http://juce.com - description: Arpeggiator audio plugin. + name: ArpeggiatorPlugin + version: 1.0.0 + vendor: JUCE + website: http://juce.com + description: Arpeggiator audio plugin. - dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, - juce_audio_plugin_client, juce_audio_processors, - juce_audio_utils, juce_core, juce_data_structures, - juce_events, juce_graphics, juce_gui_basics, juce_gui_extra - exporters: xcode_mac, vs2019 + dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, + juce_audio_plugin_client, juce_audio_processors, + juce_audio_utils, juce_core, juce_data_structures, + juce_events, juce_graphics, juce_gui_basics, juce_gui_extra + exporters: xcode_mac, vs2019 - moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 - type: AudioProcessor - mainClass: Arpeggiator + type: AudioProcessor + mainClass: Arpeggiator - useLocalCopy: 1 + useLocalCopy: 1 + + pluginCharacteristics: pluginWantsMidiIn, pluginProducesMidiOut, pluginIsMidiEffectPlugin END_JUCE_PIP_METADATA diff --git a/examples/Plugins/AudioPluginDemo.h b/examples/Plugins/AudioPluginDemo.h index d6bc6ac9fe..05da3d0a2d 100644 --- a/examples/Plugins/AudioPluginDemo.h +++ b/examples/Plugins/AudioPluginDemo.h @@ -23,24 +23,28 @@ BEGIN_JUCE_PIP_METADATA - name: AudioPluginDemo - version: 1.0.0 - vendor: JUCE - website: http://juce.com - description: Synthesiser audio plugin. + name: AudioPluginDemo + version: 1.0.0 + vendor: JUCE + website: http://juce.com + description: Synthesiser audio plugin. - dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, - juce_audio_plugin_client, juce_audio_processors, - juce_audio_utils, juce_core, juce_data_structures, - juce_events, juce_graphics, juce_gui_basics, juce_gui_extra - exporters: xcode_mac, vs2017, vs2019, linux_make, xcode_iphone, androidstudio + dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, + juce_audio_plugin_client, juce_audio_processors, + juce_audio_utils, juce_core, juce_data_structures, + juce_events, juce_graphics, juce_gui_basics, juce_gui_extra + exporters: xcode_mac, vs2017, vs2019, linux_make, xcode_iphone, androidstudio - moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 - type: AudioProcessor - mainClass: JuceDemoPluginAudioProcessor + type: AudioProcessor + mainClass: JuceDemoPluginAudioProcessor - useLocalCopy: 1 + useLocalCopy: 1 + + pluginCharacteristics: pluginIsSynth, pluginWantsMidiIn, pluginProducesMidiOut, + pluginEditorRequiresKeys + extraPluginFormats: AUv3 END_JUCE_PIP_METADATA diff --git a/examples/Plugins/CMakeLists.txt b/examples/Plugins/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/Plugins/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/Plugins/InterAppAudioEffectPluginDemo.h b/examples/Plugins/InterAppAudioEffectPluginDemo.h index 9a008cf83b..30736ccf6f 100644 --- a/examples/Plugins/InterAppAudioEffectPluginDemo.h +++ b/examples/Plugins/InterAppAudioEffectPluginDemo.h @@ -23,24 +23,26 @@ BEGIN_JUCE_PIP_METADATA - name: InterAppAudioEffectPlugin - version: 1.0.0 - vendor: JUCE - website: http://juce.com - description: Inter-app audio effect plugin. + name: InterAppAudioEffectPlugin + version: 1.0.0 + vendor: JUCE + website: http://juce.com + description: Inter-app audio effect plugin. - dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, - juce_audio_plugin_client, juce_audio_processors, - juce_audio_utils, juce_core, juce_data_structures, - juce_events, juce_graphics, juce_gui_basics, juce_gui_extra - exporters: xcode_iphone + dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, + juce_audio_plugin_client, juce_audio_processors, + juce_audio_utils, juce_core, juce_data_structures, + juce_events, juce_graphics, juce_gui_basics, juce_gui_extra + exporters: xcode_iphone - moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 - type: AudioProcessor - mainClass: IAAEffectProcessor + type: AudioProcessor + mainClass: IAAEffectProcessor - useLocalCopy: 1 + useLocalCopy: 1 + + extraPluginFormats: IAA END_JUCE_PIP_METADATA diff --git a/examples/Plugins/MultiOutSynthPluginDemo.h b/examples/Plugins/MultiOutSynthPluginDemo.h index d10f51990e..d3c6ce7505 100644 --- a/examples/Plugins/MultiOutSynthPluginDemo.h +++ b/examples/Plugins/MultiOutSynthPluginDemo.h @@ -23,24 +23,26 @@ BEGIN_JUCE_PIP_METADATA - name: MultiOutSynthPlugin - version: 1.0.0 - vendor: JUCE - website: http://juce.com - description: Multi-out synthesiser audio plugin. + name: MultiOutSynthPlugin + version: 1.0.0 + vendor: JUCE + website: http://juce.com + description: Multi-out synthesiser audio plugin. - dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, - juce_audio_plugin_client, juce_audio_processors, - juce_audio_utils, juce_core, juce_data_structures, - juce_events, juce_graphics, juce_gui_basics, juce_gui_extra - exporters: xcode_mac, vs2019 + dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, + juce_audio_plugin_client, juce_audio_processors, + juce_audio_utils, juce_core, juce_data_structures, + juce_events, juce_graphics, juce_gui_basics, juce_gui_extra + exporters: xcode_mac, vs2019 - moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 - type: AudioProcessor - mainClass: MultiOutSynth + type: AudioProcessor + mainClass: MultiOutSynth - useLocalCopy: 1 + useLocalCopy: 1 + + pluginCharacteristics: pluginIsSynth, pluginWantsMidiIn END_JUCE_PIP_METADATA diff --git a/examples/Utilities/CMakeLists.txt b/examples/Utilities/CMakeLists.txt new file mode 100644 index 0000000000..fd3d2acf88 --- /dev/null +++ b/examples/Utilities/CMakeLists.txt @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +_juce_add_pips() diff --git a/examples/Utilities/InAppPurchasesDemo.h b/examples/Utilities/InAppPurchasesDemo.h index 1336974459..a762615ede 100644 --- a/examples/Utilities/InAppPurchasesDemo.h +++ b/examples/Utilities/InAppPurchasesDemo.h @@ -38,6 +38,7 @@ exporters: xcode_mac, xcode_iphone, androidstudio moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + JUCE_IN_APP_PURCHASES=1 type: Component mainClass: InAppPurchasesDemo diff --git a/examples/Utilities/PushNotificationsDemo.h b/examples/Utilities/PushNotificationsDemo.h index 1daf536e6d..941e0e0fd7 100644 --- a/examples/Utilities/PushNotificationsDemo.h +++ b/examples/Utilities/PushNotificationsDemo.h @@ -37,6 +37,7 @@ exporters: xcode_mac, vs2019, xcode_iphone, androidstudio moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1 + JUCE_PUSH_NOTIFICATIONS=1 type: Component mainClass: PushNotificationsDemo diff --git a/extras/AudioPerformanceTest/CMakeLists.txt b/extras/AudioPerformanceTest/CMakeLists.txt new file mode 100644 index 0000000000..dccc793d8b --- /dev/null +++ b/extras/AudioPerformanceTest/CMakeLists.txt @@ -0,0 +1,27 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_gui_app(AudioPerformanceTest BUNDLE_ID com.juce.AudioPerformanceTest) + +juce_generate_juce_header(AudioPerformanceTest) + +target_sources(AudioPerformanceTest PRIVATE + Source/Main.cpp) + +target_compile_definitions(AudioPerformanceTest PRIVATE + JUCE_USE_CURL=0 JUCE_WEB_BROWSER=0) + +target_link_libraries(AudioPerformanceTest PRIVATE juce::juce_audio_utils) diff --git a/extras/AudioPluginHost/CMakeLists.txt b/extras/AudioPluginHost/CMakeLists.txt new file mode 100644 index 0000000000..8ae21a49ed --- /dev/null +++ b/extras/AudioPluginHost/CMakeLists.txt @@ -0,0 +1,52 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_gui_app(AudioPluginHost + BUNDLE_ID com.juce.pluginhost + ICON_BIG "${CMAKE_CURRENT_SOURCE_DIR}/Source/JUCEAppIcon.png" + MICROPHONE_PERMISSION_ENABLED TRUE) + +juce_generate_juce_header(AudioPluginHost) + +target_sources(AudioPluginHost PRIVATE + Source/HostStartup.cpp + Source/Plugins/IOConfigurationWindow.cpp + Source/Plugins/InternalPlugins.cpp + Source/Plugins/PluginGraph.cpp + Source/UI/GraphEditorPanel.cpp + Source/UI/MainHostWindow.cpp) + +target_compile_definitions(AudioPluginHost PRIVATE + JUCE_ALSA=1 + JUCE_DIRECTSOUND=1 + JUCE_PLUGINHOST_AU=1 + JUCE_PLUGINHOST_LADSPA=1 + JUCE_PLUGINHOST_VST=0 + JUCE_PLUGINHOST_VST3=1 + JUCE_USE_CAMERA=0 + JUCE_USE_CDBURNER=0 + JUCE_USE_CDREADER=0 + JUCE_USE_CURL=0 + JUCE_USE_FLAC=0 + JUCE_USE_OGGVORBIS=0 + JUCE_WASAPI=1 + JUCE_WEB_BROWSER=0) + +target_link_libraries(AudioPluginHost PRIVATE + juce::juce_audio_utils + juce::juce_cryptography + juce::juce_opengl + juce::juce_video) diff --git a/extras/BinaryBuilder/CMakeLists.txt b/extras/BinaryBuilder/CMakeLists.txt new file mode 100644 index 0000000000..958daa5521 --- /dev/null +++ b/extras/BinaryBuilder/CMakeLists.txt @@ -0,0 +1,25 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_console_app(BinaryBuilder) + +juce_generate_juce_header(BinaryBuilder) + +target_sources(BinaryBuilder PRIVATE Source/Main.cpp) + +target_compile_definitions(BinaryBuilder PRIVATE JUCE_USE_CURL=0) + +target_link_libraries(BinaryBuilder PRIVATE juce::juce_core) diff --git a/extras/Build/CMake/JUCEConfig.cmake.in b/extras/Build/CMake/JUCEConfig.cmake.in new file mode 100644 index 0000000000..f147b6e733 --- /dev/null +++ b/extras/Build/CMake/JUCEConfig.cmake.in @@ -0,0 +1,41 @@ +# ============================================================================== +# +# This file is part of the JUCE library. +# Copyright (c) 2017 - ROLI Ltd. +# +# JUCE is an open source library subject to commercial or 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. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/JUCE.cmake") + +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +add_executable(juce::juceaide IMPORTED) +set_target_properties(juce::juceaide PROPERTIES + IMPORTED_LOCATION "${_IMPORT_PREFIX}/@JUCE_CMAKE_BINARY_BUILDER_NAME@") + +set(_IMPORT_PREFIX) + +check_required_components("@PROJECT_NAME@") + +include("${CMAKE_CURRENT_LIST_DIR}/JUCEUtils.cmake") diff --git a/extras/Build/CMake/JUCEUtils.cmake b/extras/Build/CMake/JUCEUtils.cmake new file mode 100644 index 0000000000..aa90534b30 --- /dev/null +++ b/extras/Build/CMake/JUCEUtils.cmake @@ -0,0 +1,2014 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +# ================================================================================================== +# JUCE/CMake Compatibility Module +# +# In this file, functions intended for use by end-users have the prefix `juce_`. +# Functions beginning with an underscore should be considered private and susceptible to +# change, so don't call them directly. +# +# See the readme at `examples/CMake` for more information about CMake usage, +# including documentation of the public functions in this file. +# ================================================================================================== + +include_guard(GLOBAL) +cmake_minimum_required(VERSION 3.12) + +define_property(TARGET PROPERTY JUCE_COMPANY_NAME INHERITED + BRIEF_DOCS "The company name for a particular target" + FULL_DOCS "This can be found in ProjectInfo::companyName in a generated JuceHeader.h") +set_property(GLOBAL PROPERTY JUCE_COMPANY_NAME "yourcompany") + +define_property(TARGET PROPERTY JUCE_COMPANY_WEBSITE INHERITED + BRIEF_DOCS "The company website for a particular target" + FULL_DOCS "This will be placed in the Info.plist for the target") +set_property(GLOBAL PROPERTY JUCE_COMPANY_WEBSITE "") + +define_property(TARGET PROPERTY JUCE_COMPANY_EMAIL INHERITED + BRIEF_DOCS "The company email address for a particular target" + FULL_DOCS "This will be placed in the Info.plist for the target") +set_property(GLOBAL PROPERTY JUCE_COMPANY_EMAIL "") + +define_property(TARGET PROPERTY JUCE_COMPANY_COPYRIGHT INHERITED + BRIEF_DOCS "The company copyright for a particular target" + FULL_DOCS "This will be placed in the Info.plist for the target") +set_property(GLOBAL PROPERTY JUCE_COMPANY_COPYRIGHT "") + +define_property(TARGET PROPERTY JUCE_VST_COPY_DIR INHERITED + BRIEF_DOCS "Install location for VST2 plugins" + FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled") + +define_property(TARGET PROPERTY JUCE_VST3_COPY_DIR INHERITED + BRIEF_DOCS "Install location for VST3 plugins" + FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled") + +define_property(TARGET PROPERTY JUCE_AU_COPY_DIR INHERITED + BRIEF_DOCS "Install location for AU plugins" + FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled") + +define_property(TARGET PROPERTY JUCE_AAX_COPY_DIR INHERITED + BRIEF_DOCS "Install location for AAX plugins" + FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled") + +define_property(TARGET PROPERTY JUCE_UNITY_COPY_DIR INHERITED + BRIEF_DOCS "Install location for Unity plugins" + FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled") + +define_property(TARGET PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD INHERITED + BRIEF_DOCS "Whether or not plugins should be copied after building" + FULL_DOCS "Whether or not plugins should be copied after building") +set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE) + +# ================================================================================================== + +function(_juce_add_interface_library target) + add_library(${target} INTERFACE) + target_sources(${target} INTERFACE ${ARGN}) +endfunction() + +# ================================================================================================== + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + find_package(PkgConfig REQUIRED) + pkg_check_modules(JUCE_CURL_LINUX_DEPS IMPORTED_TARGET libcurl) + pkg_check_modules(JUCE_BROWSER_LINUX_DEPS IMPORTED_TARGET webkit2gtk-4.0 gtk+-x11-3.0) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + find_program(JUCE_RC_COMPILER Rez NO_DEFAULT_PATHS PATHS "/Applications/Xcode.app/Contents/Developer/usr/bin") + + if(NOT JUCE_RC_COMPILER) + message(WARNING "failed to find Rez; older resource-based AU plug-ins may not work correctly") + endif() +endif() + +set(JUCE_CMAKE_UTILS_DIR ${CMAKE_CURRENT_LIST_DIR} + CACHE INTERNAL "The path to the folder holding this file and other resources") + +# We set up default/fallback copy dirs here. If you need different copy dirs, use +# set_directory_properties or set_target_properties to adjust the values of `JUCE_*_COPY_DIR` at +# the appropriate scope. + +function(_juce_set_default_properties) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST") + set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3") + set_property(GLOBAL PROPERTY JUCE_AU_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components") + set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "/Library/Application Support/Avid/Audio/Plug-Ins") + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(is_x64 $) + + set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR + "$/Steinberg/Vstplugins") + + set(prefix "$") + set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "${prefix}/VST3") + set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "${prefix}/Avid/Audio/Plug-Ins") + endif() +endfunction() + +_juce_set_default_properties() + +# ================================================================================================== + +function(_juce_add_standard_defs juce_target) + target_compile_definitions(${juce_target} INTERFACE + JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1 + $,DEBUG=1 _DEBUG=1,NDEBUG=1 _NDEBUG=1> + $<$:JUCE_ANDROID=1>) +endfunction() + +# ================================================================================================== + +macro(_juce_make_absolute path) + if(NOT IS_ABSOLUTE "${${path}}") + get_filename_component("${path}" "${${path}}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + endif() +endmacro() + +macro(_juce_make_absolute_and_check path) + _juce_make_absolute("${path}") + + if(NOT EXISTS "${${path}}") + message(FATAL_ERROR "No file at path ${${path}}") + endif() +endmacro() + +# ================================================================================================== + +function(juce_add_bundle_resources_directory target folder) + _juce_make_absolute(folder) + + if(NOT EXISTS "${folder}") + message(FATAL_ERROR "Could not find resource folder ${folder}") + endif() + + get_filename_component(folder_parent_path "${folder}" DIRECTORY) + file(GLOB_RECURSE resources RELATIVE "${folder_parent_path}" "${folder}/*") + + foreach(file IN ITEMS ${resources}) + target_sources(${target} PRIVATE "${folder_parent_path}/${file}") + get_filename_component(resource_parent_path "${file}" DIRECTORY) + set_source_files_properties("${folder_parent_path}/${file}" PROPERTIES + HEADER_FILE_ONLY TRUE + MACOSX_PACKAGE_LOCATION "Resources/${resource_parent_path}") + endforeach() +endfunction() + +# ================================================================================================== + +# This creates an imported interface library with a random name, and then adds +# the fields from a JUCE module header to the target as INTERFACE_ properties. +# We can extract properties later using `_juce_get_metadata`. +# This way, the interface library ends up behaving a bit like a dictionary, +# and we don't have to parse the module header from scratch every time we +# want to find a specific key. +function(_juce_extract_metadata_block delim_str file_with_block out_dict) + string(RANDOM LENGTH 16 random_string) + set(target_name "${random_string}_dict") + set(${out_dict} "${target_name}" PARENT_SCOPE) + add_library(${target_name} INTERFACE IMPORTED) + + if(NOT EXISTS ${file_with_block}) + message(FATAL_ERROR "Unable to find file ${file_with_block}") + endif() + + file(STRINGS ${file_with_block} module_header_contents) + + set(last_written_key) + set(append NO) + + foreach(line IN ITEMS ${module_header_contents}) + if(NOT append) + if(line MATCHES " *BEGIN_${delim_str} *") + set(append YES) + endif() + + continue() + endif() + + if(append AND (line MATCHES " *END_${delim_str} *")) + break() + endif() + + if(line MATCHES "^ *([a-zA-Z]+):") + set(last_written_key "${CMAKE_MATCH_1}") + endif() + + string(REGEX REPLACE "^ *${last_written_key}: *" "" line "${line}") + string(REGEX REPLACE "[ ,]+" ";" line "${line}") + + set_property(TARGET ${target_name} APPEND PROPERTY + "INTERFACE_JUCE_${last_written_key}" "${line}") + endforeach() +endfunction() + +# Fetches properties attached to a metadata target. +function(_juce_get_metadata target key out_var) + get_target_property(content "${target}" "INTERFACE_JUCE_${key}") + + if(NOT "${content}" STREQUAL "content-NOTFOUND") + set(${out_var} "${content}" PARENT_SCOPE) + endif() +endfunction() + +# ================================================================================================== + +function(_juce_module_sources module_path output_path out_var) + get_filename_component(module_parent_path ${module_path} DIRECTORY) + get_filename_component(module_glob ${module_path} NAME) + + file(GLOB module_cpp + CONFIGURE_DEPENDS LIST_DIRECTORIES false + RELATIVE "${module_parent_path}" + "${module_path}/${module_glob}*.cpp") + + if(APPLE) + file(GLOB module_mm + CONFIGURE_DEPENDS LIST_DIRECTORIES false + RELATIVE "${module_parent_path}" + "${module_path}/${module_glob}*.mm" + "${module_path}/${module_glob}*.r") + + if(module_mm) + set(module_mm_replaced ${module_mm}) + list(TRANSFORM module_mm_replaced REPLACE "\\.mm$" ".cpp") + list(REMOVE_ITEM module_cpp ${module_mm_replaced}) + list(APPEND module_cpp ${module_mm}) + endif() + endif() + + list(TRANSFORM module_cpp PREPEND "${output_path}/") + + set(${out_var} ${module_cpp} PARENT_SCOPE) +endfunction() + +# ================================================================================================== + +function(_juce_get_all_plugin_kinds out) + set(${out} AU AUv3 AAX Standalone Unity VST VST3 PARENT_SCOPE) +endfunction() + +function(_juce_get_platform_plugin_kinds out) + set(result Standalone) + + if(APPLE) + list(APPEND result AUv3) + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + list(APPEND result AU) + endif() + + if(NOT CMAKE_SYSTEM_NAME STREQUAL "iOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android") + list(APPEND result AAX Unity VST VST3) + endif() + + set(${out} ${result} PARENT_SCOPE) +endfunction() + +function(_juce_add_plugin_definitions target visibility) + _juce_get_all_plugin_kinds(options) + cmake_parse_arguments(JUCE_ARG "${options}" "" "" ${ARGN}) + + foreach(opt IN ITEMS ${options}) + set(flag_value 0) + + if(JUCE_ARG_${opt}) + set(flag_value 1) + endif() + + target_compile_definitions(${target} ${visibility} "JucePlugin_Build_${opt}=${flag_value}") + endforeach() +endfunction() + +# ================================================================================================== + +function(_juce_add_au_resource_fork shared_code_target au_target) + if(NOT JUCE_RC_COMPILER) + return() + endif() + + get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME) + get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES) + + list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$") + + if(NOT module_sources) + message(FATAL_ERROR "Failed to find AU resource file input") + endif() + + list(GET module_sources 0 au_rez_sources) + + get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY) + # We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it + set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret") + set(secret_au_appconfig "${secret_au_resource_dir}/AppConfig.h") + + set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc") + + target_sources(${au_target} PRIVATE "${au_rez_output}") + set_source_files_properties("${au_rez_output}" PROPERTIES + GENERATED TRUE + MACOSX_PACKAGE_LOCATION Resources) + + set(defs_file $>) + + # Passing all our compile definitions using generator expressions is really painful + # because some of the definitions have pipes and quotes and dollars and goodness-knows + # what else that the shell would very much like to claim for itself, thank you very much. + # CMake definitely knows how to escape all these things, because it's perfectly happy to pass + # them to compiler invocations, but I have no idea how to get it to escape them + # in a custom command. + # In the end, it's simplest to generate a special single-purpose appconfig just for the + # resource compiler. + add_custom_command(OUTPUT "${secret_au_appconfig}" + COMMAND juce::juceaide auappconfig "${defs_file}" "${secret_au_appconfig}" + DEPENDS "${defs_file}" + VERBATIM) + + add_custom_command(OUTPUT "${au_rez_output}" + COMMAND "${JUCE_RC_COMPILER}" + -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" + -I "${secret_au_resource_dir}" + -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers" + -I "/Applications/Xcode/app/Contents/Developer/Extras/CoreAudio/AudioUnits/AUPublic/AUBase" + -I "/Applications/Xcode/app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AudioUnit.framework/Headers" + -isysroot "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" + "${au_rez_sources}" + -o "${au_rez_output}" + DEPENDS "${au_rez_input}" "${secret_au_appconfig}" + VERBATIM) +endfunction() + +# ================================================================================================== + +function(_juce_add_plugin_wrapper_target) + set(one_value_args FORMAT PATH OUT_PATH INSTALL_EXPORT) + cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN}) + + _juce_module_sources("${JUCE_ARG_PATH}" "${JUCE_ARG_OUT_PATH}" out_var) + list(FILTER out_var EXCLUDE REGEX "/juce_audio_plugin_client_utils.cpp$") + set(target_name juce_audio_plugin_client_${JUCE_ARG_FORMAT}) + + _juce_add_interface_library("${target_name}" ${out_var}) + _juce_add_plugin_definitions("${target_name}" INTERFACE ${JUCE_ARG_FORMAT}) + _juce_add_standard_defs("${target_name}") + + target_compile_features("${target_name}" INTERFACE cxx_std_11) + add_library("juce::${target_name}" ALIAS "${target_name}") + + install(TARGETS "${target_name}" EXPORT "${JUCE_ARG_INSTALL_EXPORT}") + + if(JUCE_ARG_FORMAT STREQUAL "AUv3") + find_library(AUv3_AVFoundation AVFoundation REQUIRED) + target_link_libraries("${target_name}" INTERFACE ${AUv3_AVFoundation}) + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + find_library(AUv3_AudioUnit AudioUnit REQUIRED) + target_link_libraries("${target_name}" INTERFACE ${AUv3_AudioUnit}) + endif() + endif() +endfunction() + +# ================================================================================================== + +function(juce_add_module module_path) + set(one_value_args INSTALL_PATH INSTALL_EXPORT ALIAS_NAMESPACE) + cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN}) + + _juce_make_absolute(module_path) + + get_filename_component(module_name ${module_path} NAME) + get_filename_component(module_parent_path ${module_path} DIRECTORY) + + set(installed_module_path "${JUCE_ARG_INSTALL_PATH}") + + set(base_path "$$") + set(module_header "${base_path}/${module_name}/${module_name}.h") + + list(APPEND all_module_sources ${module_header}) + + set(install_export_args) + + if(JUCE_ARG_INSTALL_EXPORT) + set(install_export_args INSTALL_EXPORT "${JUCE_ARG_INSTALL_EXPORT}") + endif() + + if(${module_name} STREQUAL "juce_audio_plugin_client") + _juce_get_platform_plugin_kinds(plugin_kinds) + + foreach(kind IN ITEMS ${plugin_kinds}) + _juce_add_plugin_wrapper_target(FORMAT ${kind} + PATH "${module_path}" + OUT_PATH "${base_path}" + ${install_export_args}) + endforeach() + + list(APPEND all_module_sources "${base_path}/${module_name}/juce_audio_plugin_client_utils.cpp") + else() + _juce_module_sources("${module_path}" "${base_path}" globbed_sources) + list(APPEND all_module_sources ${globbed_sources}) + endif() + + _juce_add_interface_library(${module_name} ${all_module_sources}) + + if(${module_name} STREQUAL "juce_core") + _juce_add_standard_defs(${module_name}) + + if(CMAKE_SYSTEM_NAME STREQUAL "Android") + target_sources(juce_core INTERFACE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") + target_include_directories(juce_core INTERFACE "${ANDROID_NDK}/sources/android/cpufeatures") + target_link_libraries(juce_core INTERFACE android log) + endif() + endif() + + source_group(Modules FILES ${all_module_sources}) + + if(${module_name} STREQUAL "juce_audio_processors") + add_library(juce_vst3_headers INTERFACE) + target_include_directories(juce_vst3_headers INTERFACE + "${base_path}/juce_audio_processors/format_types/VST3_SDK") + target_link_libraries(juce_audio_processors INTERFACE juce_vst3_headers) + + if(JUCE_ARG_INSTALL_EXPORT) + install(TARGETS juce_vst3_headers EXPORT "${JUCE_ARG_INSTALL_EXPORT}") + endif() + + if(JUCE_ARG_ALIAS_NAMESPACE) + add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_vst3_headers ALIAS juce_vst3_headers) + endif() + endif() + + target_include_directories(${module_name} INTERFACE ${base_path}) + + target_compile_definitions(${module_name} INTERFACE JUCE_MODULE_AVAILABLE_${module_name}=1) + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + target_compile_definitions(${module_name} INTERFACE LINUX=1) + endif() + + _juce_extract_metadata_block(JUCE_MODULE_DECLARATION + "${module_path}/${module_name}.h" + metadata_dict) + + _juce_get_metadata("${metadata_dict}" minimumCppStandard module_cpp_standard) + + if(module_cpp_standard) + target_compile_features(${module_name} INTERFACE cxx_std_${module_cpp_standard}) + else() + target_compile_features(${module_name} INTERFACE cxx_std_11) + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + _juce_get_metadata("${metadata_dict}" OSXFrameworks module_osxframeworks) + + foreach(module_framework IN ITEMS ${module_osxframeworks}) + find_library("${module_name}_${module_framework}" ${module_framework} REQUIRED) + target_link_libraries(${module_name} INTERFACE "${${module_name}_${module_framework}}") + endforeach() + elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + _juce_get_metadata("${metadata_dict}" iOSFrameworks module_iosframeworks) + + foreach(module_framework IN ITEMS ${module_iosframeworks}) + find_library("${module_name}_${module_framework}" ${module_framework} REQUIRED) + target_link_libraries(${module_name} INTERFACE "${${module_name}_${module_framework}}") + endforeach() + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + find_package(PkgConfig REQUIRED) + + _juce_get_metadata("${metadata_dict}" linuxPackages module_linuxpackages) + + if(module_linuxpackages) + pkg_check_modules(${module_name}_LINUX_DEPS REQUIRED IMPORTED_TARGET + ${module_linuxpackages}) + target_link_libraries(${module_name} INTERFACE PkgConfig::${module_name}_LINUX_DEPS) + endif() + + _juce_get_metadata("${metadata_dict}" linuxLibs module_linuxlibs) + + if(module_linuxlibs) + target_link_libraries(${module_name} INTERFACE ${module_linuxlibs}) + endif() + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_compile_options(${module_name} INTERFACE /bigobj) + endif() + + _juce_get_metadata("${metadata_dict}" dependencies module_dependencies) + target_link_libraries(${module_name} INTERFACE ${module_dependencies}) + + if(JUCE_ARG_INSTALL_PATH OR JUCE_ARG_INSTALL_EXPORT) + install(DIRECTORY "${module_path}" DESTINATION "${installed_module_path}") + install(TARGETS ${module_name} EXPORT "${JUCE_ARG_INSTALL_EXPORT}") + endif() + + if(JUCE_ARG_ALIAS_NAMESPACE) + add_library(${JUCE_ARG_ALIAS_NAMESPACE}::${module_name} ALIAS ${module_name}) + endif() +endfunction() + +function(juce_add_modules) + set(one_value_args INSTALL_PATH INSTALL_EXPORT ALIAS_NAMESPACE) + cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN}) + + foreach(path IN ITEMS ${JUCE_ARG_UNPARSED_ARGUMENTS}) + juce_add_module(${path} + INSTALL_PATH "${JUCE_ARG_INSTALL_PATH}" + INSTALL_EXPORT "${JUCE_ARG_INSTALL_EXPORT}" + ALIAS_NAMESPACE "${JUCE_ARG_ALIAS_NAMESPACE}") + endforeach() +endfunction() + +# ================================================================================================== + +# Ideally, we'd check the preprocessor defs on the target to see whether +# JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off, +# and then link libraries as appropriate. +# Unfortunately, this doesn't work, because linking a new library (curl/webkit/StoreKit) +# updates the target's compile defs, which results in a recursion/circular-dependency. +# Instead, we ask the user to explicitly request curl/webkit/StoreKit linking if they +# know they need it. Otherwise, we won't link anything. +# See the NEEDS_CURL, NEEDS_WEB_BROWSER, and NEEDS_STORE_KIT options in the CMake/readme.md. +function(_juce_link_optional_libraries target) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + get_target_property(needs_curl ${target} JUCE_NEEDS_CURL) + + if(needs_curl) + target_link_libraries(${target} PRIVATE PkgConfig::JUCE_CURL_LINUX_DEPS) + endif() + + get_target_property(needs_browser ${target} JUCE_NEEDS_WEB_BROWSER) + + if(needs_browser) + target_link_libraries(${target} PRIVATE PkgConfig::JUCE_BROWSER_LINUX_DEPS) + endif() + elseif(APPLE) + get_target_property(needs_storekit ${target} JUCE_NEEDS_STORE_KIT) + + if(needs_storekit) + find_library(${target}_StoreKit StoreKit REQUIRED) + target_link_libraries(${target} PRIVATE ${${target}_StoreKit}) + endif() + + get_target_property(needs_camera ${target} JUCE_CAMERA_PERMISSION_ENABLED) + + if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND needs_camera) + find_library(${target}_ImageIO ImageIO REQUIRED) + target_link_libraries(${target} PRIVATE ${${target}_ImageIO}) + endif() + endif() +endfunction() + +# ================================================================================================== + +function(_juce_get_module_definitions target filter out_var) + set(compile_defs $>) + + if(filter) + set(${out_var} $ PARENT_SCOPE) + else() + set(${out_var} ${compile_defs} PARENT_SCOPE) + endif() +endfunction() + +function(_juce_append_record output key) + string(ASCII 30 RS) + string(ASCII 31 US) + set(${output} "${${output}}${key}${US}${ARGN}${RS}" PARENT_SCOPE) +endfunction() + +function(_juce_append_target_property output key target property) + get_target_property(prop ${target} ${property}) + + if(prop STREQUAL "prop-NOTFOUND") + set(prop) + endif() + + _juce_append_record(${output} ${key} ${prop}) + set(${output} "${${output}}" PARENT_SCOPE) +endfunction() + +# This is all info that should be known at configure time (i.e. no generator expressions here!) +# We use this info to generate plists and entitlements files, also at configure time. +function(_juce_write_configure_time_info target) + _juce_append_target_property(file_content EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME) + _juce_append_target_property(file_content VERSION ${target} JUCE_VERSION) + _juce_append_target_property(file_content PLIST_TO_MERGE ${target} JUCE_PLIST_TO_MERGE) + _juce_append_target_property(file_content BUNDLE_ID ${target} JUCE_BUNDLE_ID) + _juce_append_target_property(file_content XCODE_EXTRA_PLIST_ENTRIES ${target} JUCE_XCODE_EXTRA_PLIST_ENTRIES) + _juce_append_target_property(file_content MICROPHONE_PERMISSION_ENABLED ${target} JUCE_MICROPHONE_PERMISSION_ENABLED) + _juce_append_target_property(file_content MICROPHONE_PERMISSION_TEXT ${target} JUCE_MICROPHONE_PERMISSION_TEXT) + _juce_append_target_property(file_content CAMERA_PERMISSION_ENABLED ${target} JUCE_CAMERA_PERMISSION_ENABLED) + _juce_append_target_property(file_content CAMERA_PERMISSION_TEXT ${target} JUCE_CAMERA_PERMISSION_TEXT) + _juce_append_target_property(file_content BLUETOOTH_PERMISSION_ENABLED ${target} JUCE_BLUETOOTH_PERMISSION_ENABLED) + _juce_append_target_property(file_content BLUETOOTH_PERMISSION_TEXT ${target} JUCE_BLUETOOTH_PERMISSION_TEXT) + _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_ENABLED ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_ENABLED) + _juce_append_target_property(file_content SEND_APPLE_EVENTS_PERMISSION_TEXT ${target} JUCE_SEND_APPLE_EVENTS_PERMISSION_TEXT) + _juce_append_target_property(file_content SHOULD_ADD_STORYBOARD ${target} JUCE_SHOULD_ADD_STORYBOARD) + _juce_append_target_property(file_content LAUNCH_STORYBOARD_FILE ${target} JUCE_LAUNCH_STORYBOARD_FILE) + _juce_append_target_property(file_content ICON_FILE ${target} JUCE_ICON_FILE) + _juce_append_target_property(file_content PROJECT_NAME ${target} JUCE_PRODUCT_NAME) + _juce_append_target_property(file_content COMPANY_COPYRIGHT ${target} JUCE_COMPANY_COPYRIGHT) + _juce_append_target_property(file_content COMPANY_NAME ${target} JUCE_COMPANY_NAME) + _juce_append_target_property(file_content DOCUMENT_EXTENSIONS ${target} JUCE_DOCUMENT_EXTENSIONS) + _juce_append_target_property(file_content FILE_SHARING_ENABLED ${target} JUCE_FILE_SHARING_ENABLED) + _juce_append_target_property(file_content DOCUMENT_BROWSER_ENABLED ${target} JUCE_DOCUMENT_BROWSER_ENABLED) + _juce_append_target_property(file_content STATUS_BAR_HIDDEN ${target} JUCE_STATUS_BAR_HIDDEN) + _juce_append_target_property(file_content BACKGROUND_AUDIO_ENABLED ${target} JUCE_BACKGROUND_AUDIO_ENABLED) + _juce_append_target_property(file_content BACKGROUND_BLE_ENABLED ${target} JUCE_BACKGROUND_BLE_ENABLED) + _juce_append_target_property(file_content PUSH_NOTIFICATIONS_ENABLED ${target} JUCE_PUSH_NOTIFICATIONS_ENABLED) + _juce_append_target_property(file_content PLUGIN_MANUFACTURER_CODE ${target} JUCE_PLUGIN_MANUFACTURER_CODE) + _juce_append_target_property(file_content PLUGIN_CODE ${target} JUCE_PLUGIN_CODE) + _juce_append_target_property(file_content IPHONE_SCREEN_ORIENTATIONS ${target} JUCE_IPHONE_SCREEN_ORIENTATIONS) + _juce_append_target_property(file_content IPAD_SCREEN_ORIENTATIONS ${target} JUCE_IPAD_SCREEN_ORIENTATIONS) + _juce_append_target_property(file_content PLUGIN_NAME ${target} JUCE_PRODUCT_NAME) + _juce_append_target_property(file_content PLUGIN_MANUFACTURER ${target} JUCE_COMPANY_NAME) + _juce_append_target_property(file_content PLUGIN_DESCRIPTION ${target} JUCE_DESCRIPTION) + _juce_append_target_property(file_content PLUGIN_AU_EXPORT_PREFIX ${target} JUCE_AU_EXPORT_PREFIX) + _juce_append_target_property(file_content PLUGIN_AU_MAIN_TYPE ${target} JUCE_AU_MAIN_TYPE) + _juce_append_target_property(file_content IS_AU_SANDBOX_SAFE ${target} JUCE_AU_SANDBOX_SAFE) + _juce_append_target_property(file_content IS_PLUGIN_SYNTH ${target} JUCE_IS_SYNTH) + _juce_append_target_property(file_content HARDENED_RUNTIME_ENABLED ${target} JUCE_HARDENED_RUNTIME_ENABLED) + _juce_append_target_property(file_content APP_SANDBOX_ENABLED ${target} JUCE_APP_SANDBOX_ENABLED) + _juce_append_target_property(file_content APP_SANDBOX_INHERIT ${target} JUCE_APP_SANDBOX_INHERIT) + _juce_append_target_property(file_content HARDENED_RUNTIME_OPTIONS ${target} JUCE_HARDENED_RUNTIME_OPTIONS) + _juce_append_target_property(file_content APP_SANDBOX_OPTIONS ${target} JUCE_APP_SANDBOX_OPTIONS) + _juce_append_target_property(file_content APP_GROUPS_ENABLED ${target} JUCE_APP_GROUPS_ENABLED) + _juce_append_target_property(file_content APP_GROUP_IDS ${target} JUCE_APP_GROUP_IDS) + _juce_append_target_property(file_content IS_PLUGIN ${target} JUCE_IS_PLUGIN) + _juce_append_target_property(file_content ICLOUD_PERMISSIONS_ENABLED ${target} JUCE_ICLOUD_PERMISSIONS_ENABLED) + + if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + _juce_append_record(file_content IS_IOS 1) + else() + _juce_append_record(file_content IS_IOS 0) + endif() + + get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY) + + set(info_file "${juce_library_code}/Info.txt") + file(WRITE "${info_file}" "${file_content}") + set_target_properties(${target} PROPERTIES JUCE_INFO_FILE "${info_file}") +endfunction() + +# In this file, we put things that CMake is only able to divine at generate time, like preprocessor definitions. +# We use the target preprocessor definitions to work out which JUCE modules should go in the JuceHeader.h. +function(_juce_write_generate_time_info target) + _juce_get_module_definitions(${target} OFF module_defs) + _juce_append_record(defs MODULE_DEFINITIONS ${module_defs}) + + _juce_append_target_property(defs EXECUTABLE_NAME ${target} JUCE_PRODUCT_NAME) + _juce_append_target_property(defs PROJECT_NAME ${target} JUCE_PRODUCT_NAME) + _juce_append_target_property(defs VERSION ${target} JUCE_VERSION) + _juce_append_target_property(defs COMPANY_NAME ${target} JUCE_COMPANY_NAME) + + get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY) + + set(defs_file "${juce_library_code}/$/Defs.txt") + file(GENERATE OUTPUT "${defs_file}" CONTENT "${defs}") + set_target_properties(${target} PROPERTIES JUCE_DEFS_FILE "${defs_file}") +endfunction() + +# ================================================================================================== + +function(juce_add_binary_data target) + set(one_value_args NAMESPACE) + set(multi_value_args SOURCES) + cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN}) + + list(LENGTH JUCE_ARG_SOURCES num_binary_files) + + if(${num_binary_files} LESS 1) + message(FATAL_ERROR "juce_add_binary_data must be passed at least one file to encode") + endif() + + add_library(${target} STATIC) + + set(juce_binary_data_folder "${CMAKE_CURRENT_BINARY_DIR}/juce_binarydata_${target}/JuceLibraryCode") + + list(APPEND binary_file_names "${juce_binary_data_folder}/BinaryData.h") + + foreach(index RANGE 1 ${num_binary_files}) + list(APPEND binary_file_names "${juce_binary_data_folder}/BinaryData${index}.cpp") + endforeach() + + file(MAKE_DIRECTORY ${juce_binary_data_folder}) + + if(JUCE_ARG_NAMESPACE) + set(namespace_opt --namespace=${JUCE_ARG_NAMESPACE}) + endif() + + add_custom_command(OUTPUT ${binary_file_names} + COMMAND juce::juceaide binarydata ${namespace_opt} ${juce_binary_data_folder} ${JUCE_ARG_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + VERBATIM) + + target_sources(${target} PRIVATE "${binary_file_names}") + target_compile_definitions(${target} INTERFACE JUCE_TARGET_HAS_BINARY_DATA=1) + target_include_directories(${target} INTERFACE ${juce_binary_data_folder}) + target_compile_features(${target} PRIVATE cxx_std_11) +endfunction() + +# ================================================================================================== + +# math(EXPR ... OUTPUT_FORMAT HEXADECIMAL) wasn't added until 3.13, but we need 3.12 for vcpkg +# compatibility +function(_juce_dec_to_hex num out_var) + while(num) + math(EXPR digit "${num} % 16") + math(EXPR num "${num} / 16") + + if(digit GREATER_EQUAL 10) + math(EXPR ascii_code "${digit} + 55") + string(ASCII "${ascii_code}" digit) + endif() + + set(result "${digit}${result}") + endwhile() + + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() + +function(_juce_version_code version_in out_var) + string(REGEX REPLACE "\\." ";" version_list ${version_in}) + list(LENGTH version_list num_version_components) + + set(version_major 0) + set(version_minor 0) + set(version_patch 0) + + if(num_version_components GREATER 0) + list(GET version_list 0 version_major) + endif() + + if(num_version_components GREATER 1) + list(GET version_list 1 version_minor) + endif() + + if(num_version_components GREATER 2) + list(GET version_list 2 version_patch) + endif() + + math(EXPR decimal "(${version_major} << 16) + (${version_minor} << 8) + ${version_patch}") + _juce_dec_to_hex(${decimal} hex) + set(${out_var} "${hex}" PARENT_SCOPE) +endfunction() + +function(_juce_to_char_literal str out_var) + string(APPEND str " ") # Make sure there are at least 4 characters in the string. + + # Round-tripping through a file is the simplest way to convert a string to hex... + string(SUBSTRING "${str}" 0 4 four_chars) + string(RANDOM LENGTH 16 random_string) + set(scratch_file "${CMAKE_CURRENT_BINARY_DIR}/${random_string}_ascii_conversion.txt") + + file(WRITE "${scratch_file}" "${four_chars}") + file(READ "${scratch_file}" four_chars_hex HEX) + file(REMOVE "${scratch_file}") + + set(${out_var} ${four_chars_hex} PARENT_SCOPE) +endfunction() + +# ================================================================================================== + +function(juce_generate_juce_header target) + get_target_property(juce_library_code ${target} JUCE_GENERATED_SOURCES_DIRECTORY) + + if(NOT juce_library_code) + message(FATAL_ERROR "Target ${target} does not have a generated sources directory. Ensure it was created with a juce_add_* function") + endif() + + set(juce_header ${juce_library_code}/JuceHeader.h) + target_sources(${target} PRIVATE ${juce_header}) + + set(defs_file $>) + + add_custom_command(OUTPUT "${juce_header}" + COMMAND juce::juceaide header "${defs_file}" "${juce_header}" + DEPENDS "${defs_file}" + VERBATIM) +endfunction() + +# ================================================================================================== + +function(_juce_execute_juceaide) + if(NOT TARGET juce::juceaide) + message(FATAL_ERROR "The juceaide target does not exist") + endif() + + get_target_property(juceaide_location juce::juceaide IMPORTED_LOCATION) + + if(NOT EXISTS "${juceaide_location}") + message(FATAL_ERROR "juceaide was imported, but it doesn't exist!") + endif() + + execute_process(COMMAND "${juceaide_location}" ${ARGN} RESULT_VARIABLE result_variable) + + if(result_variable) + message(FATAL_ERROR "Running juceaide failed") + endif() +endfunction() + +function(_juce_set_output_name target name) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android") + set_target_properties(${target} PROPERTIES + OUTPUT_NAME ${name} + XCODE_ATTRIBUTE_PRODUCT_NAME ${name}) + endif() +endfunction() + +function(_juce_generate_icon source_target dest_target) + get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY) + get_target_property(juce_property_icon_big ${source_target} JUCE_ICON_BIG) + get_target_property(juce_property_icon_small ${source_target} JUCE_ICON_SMALL) + + if(NOT (juce_property_icon_big OR juce_property_icon_small)) + return() + endif() + + set(icon_args) + + if(juce_property_icon_big) + list(APPEND icon_args "${juce_property_icon_big}") + endif() + + if(juce_property_icon_small) + list(APPEND icon_args "${juce_property_icon_small}") + endif() + + set(generated_icon) + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(generated_icon "${juce_library_code}/Icon.icns") + add_custom_command(OUTPUT "${generated_icon}" + COMMAND juce::juceaide macicon "${generated_icon}" ${icon_args} + VERBATIM) + set_source_files_properties(${generated_icon} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(generated_icon "${juce_library_code}/icon.ico") + add_custom_command(OUTPUT ${generated_icon} + COMMAND juce::juceaide winicon "${generated_icon}" ${icon_args} + VERBATIM) + elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") + get_target_property(generated_icon ${source_target} JUCE_CUSTOM_XCASSETS_FOLDER) + + if(NOT generated_icon) + set(out_path "${juce_library_code}/${dest_target}") + set(generated_icon "${out_path}/Images.xcassets") + + # To get compiled properly, we need iOS assets at configure time! + _juce_execute_juceaide(iosassets "${out_path}" ${icon_args}) + endif() + + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon") + + get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD) + + if(NOT add_storyboard) + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME "LaunchImage") + endif() + endif() + + if(generated_icon) + target_sources(${dest_target} PRIVATE ${generated_icon}) + set_target_properties(${source_target} PROPERTIES + JUCE_ICON_FILE "${generated_icon}" + RESOURCE "${generated_icon}") + endif() +endfunction() + +function(_juce_add_xcode_entitlements source_target dest_target) + get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING) + get_target_property(input_info_file ${source_target} JUCE_INFO_FILE) + + get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY) + set(entitlements_file "${juce_library_code}/${dest_target}.entitlements") + + _juce_execute_juceaide(entitlements "${juce_kind_string}" "${input_info_file}" "${entitlements_file}") + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${entitlements_file}") +endfunction() + +function(_juce_configure_bundle source_target dest_target) + _juce_generate_icon(${source_target} ${dest_target}) + _juce_write_configure_time_info(${source_target}) + + if(NOT APPLE) + return() + endif() + + get_target_property(generated_icon ${source_target} JUCE_ICON_FILE) + set(icon_dependency) + + if(generated_icon) + set(icon_dependency "${generated_icon}") + endif() + + get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY) + get_target_property(input_info_file ${source_target} JUCE_INFO_FILE) + + set(this_output_info_dir "${juce_library_code}/${dest_target}") + set(this_output_pkginfo "${this_output_info_dir}/PkgInfo") + set(this_output_plist "${this_output_info_dir}/Info.plist") + + get_target_property(juce_kind_string ${dest_target} JUCE_TARGET_KIND_STRING) + + _juce_execute_juceaide(plist "${juce_kind_string}" "${input_info_file}" "${this_output_plist}") + set_target_properties(${dest_target} PROPERTIES + BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST "${this_output_plist}") + + add_custom_command(OUTPUT "${this_output_pkginfo}" + COMMAND juce::juceaide pkginfo "${juce_kind_string}" "${this_output_pkginfo}" + VERBATIM) + + set(output_folder "$") + + target_sources(${dest_target} PRIVATE "${this_output_pkginfo}") + set_source_files_properties("${this_output_pkginfo}" PROPERTIES + HEADER_FILE_ONLY TRUE + GENERATED TRUE) + add_custom_command(TARGET ${dest_target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${this_output_pkginfo}" "${output_folder}" + DEPENDS "${this_output_pkginfo}" + VERBATIM) + + _juce_add_xcode_entitlements(${source_target} ${dest_target}) + + if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + get_target_property(add_storyboard ${source_target} JUCE_SHOULD_ADD_STORYBOARD) + + if(add_storyboard) + get_target_property(storyboard_file ${source_target} JUCE_LAUNCH_STORYBOARD_FILE) + + if(NOT EXISTS "${storyboard_file}") + message(FATAL_ERROR "Could not find storyboard file: ${storyboard_file}") + endif() + + target_sources(${dest_target} PRIVATE "${storyboard_file}") + set_property(TARGET ${dest_target} APPEND PROPERTY RESOURCE "${storyboard_file}") + endif() + endif() + + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME + $) + + if(juce_kind_string STREQUAL "AUv3 AppExtension") + get_target_property(source_bundle_id ${source_target} JUCE_BUNDLE_ID) + + if(source_bundle_id MATCHES "\\.(.*)$") + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER + "${source_bundle_id}.${CMAKE_MATCH_1}AUv3") + else() + message(FATAL_ERROR "Bundle ID should contain at least one `.`!") + endif() + else() + set_target_properties(${dest_target} PROPERTIES + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER + $) + endif() +endfunction() + +function(_juce_add_resources_rc source_target dest_target) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + return() + endif() + + get_target_property(juce_library_code ${source_target} JUCE_GENERATED_SOURCES_DIRECTORY) + set(input_info_file "$") + + get_target_property(generated_icon ${source_target} JUCE_ICON_FILE) + set(dependency) + + if(generated_icon) + set(dependency DEPENDS "${generated_icon}") + endif() + + set(resource_rc_file "${juce_library_code}/resources.rc") + + add_custom_command(OUTPUT "${resource_rc_file}" + COMMAND juce::juceaide rcfile "${input_info_file}" "${resource_rc_file}" + ${dependency} + VERBATIM) + + target_sources(${dest_target} PRIVATE "${resource_rc_file}") +endfunction() + +function(_juce_configure_app_bundle source_target dest_target) + set_target_properties(${dest_target} PROPERTIES + JUCE_TARGET_KIND_STRING "App" + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE) + + _juce_add_resources_rc(${source_target} ${dest_target}) + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(nib_path "${JUCE_CMAKE_UTILS_DIR}/RecentFilesMenuTemplate.nib") + target_sources("${dest_target}" PRIVATE "${nib_path}") + set_source_files_properties("${nib_path}" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + endif() +endfunction() + +# ================================================================================================== + +function(_juce_create_windows_package source_target dest_target extension default_icon x32folder x64folder) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + return() + endif() + + get_target_property(products_folder ${source_target} LIBRARY_OUTPUT_DIRECTORY) + + set(product_name $) + set(output_folder "${products_folder}/${product_name}.${extension}") + + set(is_x64 $) + set(arch_string $) + + set_target_properties(${dest_target} + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${output_folder}/Contents/${arch_string}") + + get_target_property(icon_file ${source_target} JUCE_ICON_FILE) + + if(NOT icon_file) + set(icon_file "${default_icon}") + endif() + + if(icon_file) + set(desktop_ini "${output_folder}/desktop.ini") + set(plugin_ico "${output_folder}/Plugin.ico") + + file(GENERATE OUTPUT "${desktop_ini}" + CONTENT + "[.ShellClassInfo]\nIconResource=Plugin.ico,0\nIconFile=Plugin.ico\nIconIndex=0\n") + add_custom_command(TARGET ${dest_target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${icon_file}" "${plugin_ico}" + COMMAND attrib +s "${desktop_ini}" + COMMAND attrib +s "${output_folder}" + DEPENDS "${icon_file}" "${desktop_ini}" + VERBATIM) + endif() +endfunction() + +# ================================================================================================== + +function(_juce_add_unity_plugin_prefix_if_necessary name out_var) + string(TOLOWER "${name}" lower) + + if(NOT lower MATCHES "^audioplugin") + set(${out_var} "audioplugin_${name}" PARENT_SCOPE) + else() + set(${out_var} "${name}" PARENT_SCOPE) + endif() +endfunction() + +function(_juce_add_unity_script_file shared_target out_var) + set(script_in "${JUCE_CMAKE_UTILS_DIR}/UnityPluginGUIScript.cs.in") + + get_target_property(plugin_name ${shared_target} JUCE_PRODUCT_NAME) + get_target_property(plugin_vendor ${shared_target} JUCE_COMPANY_NAME) + get_target_property(plugin_description ${shared_target} JUCE_DESCRIPTION) + + string(REGEX REPLACE " +" "_" plugin_class_name "${plugin_name}") + + get_target_property(juce_library_code ${shared_target} JUCE_GENERATED_SOURCES_DIRECTORY) + _juce_add_unity_plugin_prefix_if_necessary("${plugin_name}" script_prefix) + set(script_out "${juce_library_code}/${script_prefix}_UnityScript.cs") + configure_file(${script_in} ${script_out}) + set(${out_var} "${script_out}" PARENT_SCOPE) +endfunction() + +# ================================================================================================== + +function(_juce_copy_dir target from to) + # This is a shim to make CMake copy a whole directory, rather than just + # the contents of a directory + add_custom_command(TARGET ${target} POST_BUILD + COMMAND "${CMAKE_COMMAND}" + "-Dsrc=${from}" + "-Ddest=${to}" + "-P" "${JUCE_CMAKE_UTILS_DIR}/copyDir.cmake" + VERBATIM) +endfunction() + +function(_juce_copy_after_build shared_code target from to) + get_target_property(wants_copy ${shared_code} JUCE_COPY_PLUGIN_AFTER_BUILD) + + if(wants_copy) + _juce_copy_dir(${target} "${from}" "$>") + endif() +endfunction() + +function(_juce_set_plugin_target_properties shared_code_target kind) + set(target_name ${shared_code_target}_${kind}) + + set_target_properties(${target_name} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "$>" + LIBRARY_OUTPUT_DIRECTORY "$>" + RUNTIME_OUTPUT_DIRECTORY "$>") + + get_target_property(products_folder ${shared_code_target} LIBRARY_OUTPUT_DIRECTORY) + set(product_name $) + + if(kind STREQUAL "VST3") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION vst3 + PREFIX "" + SUFFIX .vst3 + BUNDLE TRUE + XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst3 + XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + + _juce_create_windows_package(${shared_code_target} ${target_name} vst3 "" x86-win x86_64-win) + + set(output_path "${products_folder}/${product_name}.vst3") + + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # On linux we assume that the output arch is the same as the that of the host platform + set(is_platform_x64 $) + set(arch_string $) + + set_target_properties(${target_name} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${output_path}/Contents/${arch_string}-linux") + endif() + + _juce_copy_after_build(${shared_code_target} ${target_name} "${output_path}" JUCE_VST3_COPY_DIR) + elseif(kind STREQUAL "VST") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION vst + BUNDLE TRUE + XCODE_ATTRIBUTE_WRAPPER_EXTENSION vst + XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + + set(output_path "$") + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(output_path "$") + endif() + + _juce_copy_after_build(${shared_code_target} ${target_name} "${output_path}" JUCE_VST_COPY_DIR) + elseif(kind STREQUAL "AU") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION component + XCODE_ATTRIBUTE_WRAPPER_EXTENSION component + BUNDLE TRUE + XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + + set(output_path "$") + _juce_copy_after_build(${shared_code_target} ${target_name} "${output_path}" JUCE_AU_COPY_DIR) + elseif(kind STREQUAL "AUv3") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION appex + XCODE_ATTRIBUTE_WRAPPER_EXTENSION appex + XCODE_ATTRIBUTE_PRODUCT_TYPE "com.apple.product-type.app-extension" + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + elseif(kind STREQUAL "AAX") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION aaxplugin + PREFIX "" + SUFFIX .aaxplugin + XCODE_ATTRIBUTE_WRAPPER_EXTENSION aaxplugin + BUNDLE TRUE + XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + + get_target_property(default_icon juce_aax_sdk INTERFACE_JUCE_AAX_DEFAULT_ICON) + _juce_create_windows_package(${shared_code_target} ${target_name} aaxplugin "${default_icon}" Win32 x64) + + set(output_path "${products_folder}/${product_name}.aaxplugin") + _juce_copy_after_build(${shared_code_target} ${target_name} "${output_path}" JUCE_AAX_COPY_DIR) + elseif(kind STREQUAL "Unity") + set_target_properties(${target_name} PROPERTIES + BUNDLE_EXTENSION bundle + XCODE_ATTRIBUTE_WRAPPER_EXTENSION bundle + BUNDLE TRUE + XCODE_ATTRIBUTE_LIBRARY_STYLE Bundle + XCODE_ATTRIBUTE_GENERATE_PKGINFO_FILE YES) + + _juce_add_unity_script_file(${shared_code_target} script_file) + target_sources(${target_name} PRIVATE "${script_file}") + set_source_files_properties("${script_file}" PROPERTIES + GENERATED TRUE + MACOSX_PACKAGE_LOCATION Resources) + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(output_path "$") + _juce_copy_after_build(${shared_code_target} ${target_name} "${output_path}" JUCE_UNITY_COPY_DIR) + else() + # On windows and linux, the gui script needs to be copied next to the unity output + add_custom_command(TARGET ${target_name} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy "${script_file}" "${products_folder}" + DEPENDS "${script_file}" + VERBATIM) + + _juce_copy_after_build(${shared_code_target} + ${target_name} + "$" + JUCE_UNITY_COPY_DIR) + _juce_copy_after_build(${shared_code_target} + ${target_name} + "${script_file}" + JUCE_UNITY_COPY_DIR) + endif() + endif() +endfunction() + +# Convert the cmake plugin kind ids to strings understood by ProjectType::Target::typeFromName +function(_juce_get_plugin_kind_name kind out_var) + if(kind STREQUAL "AU") + set(${out_var} "AU" PARENT_SCOPE) + elseif(kind STREQUAL "AUv3") + set(${out_var} "AUv3 AppExtension" PARENT_SCOPE) + elseif(kind STREQUAL "AAX") + set(${out_var} "AAX" PARENT_SCOPE) + elseif(kind STREQUAL "Standalone") + set(${out_var} "Standalone Plugin" PARENT_SCOPE) + elseif(kind STREQUAL "Unity") + set(${out_var} "Unity Plugin" PARENT_SCOPE) + elseif(kind STREQUAL "VST") + set(${out_var} "VST" PARENT_SCOPE) + elseif(kind STREQUAL "VST3") + set(${out_var} "VST3" PARENT_SCOPE) + endif() +endfunction() + +function(_juce_link_plugin_wrapper shared_code_target kind) + set(target_name ${shared_code_target}_${kind}) + + if(CMAKE_SYSTEM_NAME STREQUAL "Android") + add_library(${target_name} SHARED) + elseif((kind STREQUAL "Standalone") OR (kind STREQUAL "AUv3")) + add_executable(${target_name} WIN32 MACOSX_BUNDLE) + else() + add_library(${target_name} MODULE) + endif() + + # We re-export the shared code's private include dirs, because the wrapper targets need to + # see the module headers. We don't just link publicly, because that would introduce + # conflicting macro definitions. + target_include_directories(${target_name} PRIVATE + $) + + target_link_libraries(${target_name} PRIVATE + ${shared_code_target} + juce::juce_audio_plugin_client_${kind}) + + _juce_set_output_name(${target_name} $) + + _juce_get_plugin_kind_name(${kind} juce_kind_string) + set_target_properties(${target_name} PROPERTIES + XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO + XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES YES + POSITION_INDEPENDENT_CODE TRUE + VISIBILITY_INLINES_HIDDEN TRUE + C_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden + FOLDER ${shared_code_target} + JUCE_TARGET_KIND_STRING "${juce_kind_string}") + add_dependencies(${shared_code_target}_All ${target_name}) + + _juce_configure_bundle(${shared_code_target} ${target_name}) + _juce_set_plugin_target_properties(${shared_code_target} ${kind}) +endfunction() + +# ================================================================================================== + +function(_juce_get_vst3_category_string target out_var) + get_target_property(vst3_categories ${target} JUCE_VST3_CATEGORIES) + + if((NOT Fx IN_LIST vst3_categories) AND (NOT Instrument IN_LIST vst3_categories)) + get_target_property(is_synth ${target} JUCE_IS_SYNTH) + + if(is_synth) + set(first_type Instrument) + else() + set(first_type Fx) + endif() + + list(INSERT vst3_categories 0 ${first_type}) + else() + if(Instrument IN_LIST vst3_categories) + list(REMOVE_ITEM vst3_categories Instrument) + list(INSERT vst3_categories 0 Instrument) + endif() + + if(Fx IN_LIST vst3_categories) + list(REMOVE_ITEM vst3_categories Fx) + list(INSERT vst3_categories 0 Fx) + endif() + endif() + + string(REGEX REPLACE ";" "|" result "${vst3_categories}") + set(${out_var} ${result} PARENT_SCOPE) +endfunction() + +function(_juce_get_iaa_type_code target out_var) + get_target_property(wants_midi_input ${target} JUCE_NEEDS_MIDI_INPUT) + get_target_property(is_synth ${target} JUCE_IS_SYNTH) + + set(result) + + if(wants_midi_input) + if(is_synth) + set(result "auri") + else() + set(result "aurm") + endif() + else() + if(is_synth) + set(result "aurg") + else() + set(result "aurx") + endif() + endif() + + set(${out_var} ${result} PARENT_SCOPE) +endfunction() + +function(_juce_configure_plugin_targets target) + if(${CMAKE_VERSION} VERSION_LESS "3.15.0") + message(FATAL_ERROR "Plugin targets require CMake 3.15 or higher") + endif() + + target_link_libraries(${target} PRIVATE juce::juce_audio_plugin_client) + + _juce_set_output_name(${target} $_SharedCode) + + get_target_property(enabled_formats ${target} JUCE_FORMATS) + + if((VST IN_LIST enabled_formats) AND (NOT TARGET juce_vst2_sdk)) + message(FATAL_ERROR "Use juce_set_vst2_sdk_path to set up the VST sdk before adding VST targets") + elseif((AAX IN_LIST enabled_formats) AND (NOT TARGET juce_aax_sdk)) + message(FATAL_ERROR "Use juce_set_aax_sdk_path to set up the AAX sdk before adding AAX targets") + endif() + + _juce_add_plugin_definitions(${target} PRIVATE ${enabled_formats}) + + # The plugin wrappers need to know what other modules are available, especially + # juce_audio_utils and juce_gui_basics. We achieve this by searching for + # JUCE_MODULE_AVAILABLE_ private compile definitions, and reexporting them in + # the interface compile definitions. + # Unfortunately this requires CMake 3.15. + _juce_get_module_definitions(${target} ON enabled_modules) + target_compile_definitions(${target} INTERFACE ${enabled_modules}) + + target_compile_definitions(${target} PRIVATE JUCE_SHARED_CODE=1) + + get_target_property(project_version_string ${target} JUCE_VERSION) + _juce_version_code(${project_version_string} project_version_hex) + + get_target_property(project_manufacturer_code ${target} JUCE_PLUGIN_MANUFACTURERER_CODE) + get_target_property(project_plugin_code ${target} JUCE_PLUGIN_CODE) + + _juce_to_char_literal(${project_manufacturer_code} project_manufacturer_code) + _juce_to_char_literal(${project_plugin_code} project_plugin_code) + + _juce_get_vst3_category_string(${target} vst3_category_string) + _juce_get_iaa_type_code(${target} iaa_type_code) + + target_compile_definitions(${target} PUBLIC + JUCE_STANDALONE_APPLICATION=JucePlugin_Build_Standalone + JucePlugin_IsSynth=$> + JucePlugin_ManufacturerCode=0x${project_manufacturer_code} + JucePlugin_Manufacturer="$" + JucePlugin_ManufacturerWebsite="$" + JucePlugin_ManufacturerEmail="$" + JucePlugin_PluginCode=0x${project_plugin_code} + JucePlugin_ProducesMidiOutput=$> + JucePlugin_IsMidiEffect=$> + JucePlugin_WantsMidiInput=$> + JucePlugin_EditorRequiresKeyboardFocus=$> + JucePlugin_Name="$" + JucePlugin_Desc="$" + JucePlugin_Version=${project_version_string} + JucePlugin_VersionString="${project_version_string}" + JucePlugin_VersionCode=0x${project_version_hex} + JucePlugin_VSTUniqueID=JucePlugin_PluginCode + JucePlugin_VSTCategory=$ + JucePlugin_Vst3Category="${vst3_category_string}" + JucePlugin_AUMainType=$ + JucePlugin_AUSubType=JucePlugin_PluginCode + JucePlugin_AUExportPrefix=$ + JucePlugin_AUExportPrefixQuoted="$" + JucePlugin_AUManufacturerCode=JucePlugin_ManufacturerCode + JucePlugin_CFBundleIdentifier="$" + JucePlugin_AAXIdentifier=$ + JucePlugin_AAXManufacturerCode=JucePlugin_ManufacturerCode + JucePlugin_AAXProductId=JucePlugin_PluginCode + JucePlugin_AAXCategory=$ + JucePlugin_AAXDisableBypass=$> + JucePlugin_AAXDisableMultiMono=$> + JucePlugin_VSTNumMidiInputs=$ + JucePlugin_VSTNumMidiOutputs=$) + + set_target_properties(${target} PROPERTIES + POSITION_INDEPENDENT_CODE TRUE + INTERFACE_POSITION_INDEPENDENT_CODE TRUE + VISIBILITY_INLINES_HIDDEN TRUE + C_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden) + + # A convenience target for building all plugin variations at once + add_custom_target(${target}_All) + set_target_properties(${target}_All PROPERTIES FOLDER ${target}) + + _juce_get_platform_plugin_kinds(plugin_kinds) + + foreach(kind IN ITEMS ${plugin_kinds}) + if(kind IN_LIST enabled_formats) + _juce_link_plugin_wrapper(${target} ${kind}) + endif() + endforeach() + + if(TARGET ${target}_Standalone) + _juce_configure_app_bundle(${target} ${target}_Standalone) + endif() + + if(TARGET ${target}_AU) + _juce_add_au_resource_fork(${target} ${target}_AU) + endif() + + if(TARGET ${target}_AAX) + target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk) + endif() + + if(TARGET ${target}_AUv3) + target_link_options(${target}_AUv3 PUBLIC -fapplication-extension -e _NSExtensionMain) + endif() + + if((TARGET ${target}_AUv3) AND (TARGET ${target}_Standalone)) + add_dependencies(${target}_Standalone ${target}_AUv3) + # Copy the AUv3 into the Standalone app bundle + _juce_copy_dir(${target}_Standalone + "$" + "$/PlugIns") + endif() +endfunction() + +# ================================================================================================== + +function(_juce_set_property_if_not_set target property) + list(LENGTH ARGN num_extra_args) + + if(num_extra_args EQUAL 0) + return() + endif() + + set(existing_property) + get_target_property(existing_property ${target} JUCE_${property}) + + if(${existing_property} STREQUAL "existing_property-NOTFOUND") + set_target_properties(${target} PROPERTIES JUCE_${property} "${ARGN}") + endif() +endfunction() + +function(_juce_make_valid_4cc out_var) + string(RANDOM LENGTH 1 ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" head) + string(RANDOM LENGTH 3 ALPHABET "abcdefghijklmnopqrstuvwxyz" tail) + set(${out_var} "${head}${tail}" PARENT_SCOPE) +endfunction() + +# This function adds some default properties that plugin targets expect to be +# set, in order to generate the correct compile definitions. +function(_juce_set_fallback_properties target) + _juce_set_property_if_not_set(${target} PRODUCT_NAME ${target}) + + get_target_property(output_name ${target} JUCE_PRODUCT_NAME) + _juce_set_property_if_not_set(${target} DESCRIPTION "${output_name}") + + get_target_property(real_company_name ${target} JUCE_COMPANY_NAME) + _juce_set_property_if_not_set(${target} BUNDLE_ID "com.${real_company_name}.${target}") + + _juce_set_property_if_not_set(${target} VERSION ${PROJECT_VERSION}) + + get_target_property(final_version ${target} JUCE_VERSION) + + if(NOT final_version) + message(FATAL_ERROR "Target ${target} must have its VERSION argument set, or must be part of a project with a PROJECT_VERSION") + endif() + + get_target_property(custom_xcassets ${target} JUCE_CUSTOM_XCASSETS_FOLDER) + + set(needs_storyboard TRUE) + + if(custom_xcassets) + set(needs_storyboard FALSE) + endif() + + set_target_properties(${target} PROPERTIES JUCE_SHOULD_ADD_STORYBOARD ${needs_storyboard}) + + _juce_set_property_if_not_set(${target} + LAUNCH_STORYBOARD_FILE "${JUCE_CMAKE_UTILS_DIR}/LaunchScreen.storyboard") + + _juce_set_property_if_not_set(${target} PLUGIN_MANUFACTURER_CODE "Manu") + + # The plugin code will change on each run, unless you specify one manually! + _juce_make_valid_4cc(random_code) + _juce_set_property_if_not_set(${target} PLUGIN_CODE ${random_code}) + + _juce_set_property_if_not_set(${target} IS_SYNTH FALSE) + _juce_set_property_if_not_set(${target} NEEDS_MIDI_INPUT FALSE) + _juce_set_property_if_not_set(${target} NEEDS_MIDI_OUTPUT FALSE) + _juce_set_property_if_not_set(${target} IS_MIDI_EFFECT FALSE) + _juce_set_property_if_not_set(${target} EDITOR_WANTS_KEYBOARD_FOCUS FALSE) + _juce_set_property_if_not_set(${target} DISABLE_AAX_BYPASS FALSE) + _juce_set_property_if_not_set(${target} DISABLE_AAX_MULTI_MONO FALSE) + + get_target_property(bundle_id ${target} JUCE_BUNDLE_ID) + _juce_set_property_if_not_set(${target} AAX_IDENTIFIER ${bundle_id}) + + _juce_set_property_if_not_set(${target} VST_NUM_MIDI_INS 16) + _juce_set_property_if_not_set(${target} VST_NUM_MIDI_OUTS 16) + + _juce_set_property_if_not_set(${target} AU_SANDBOX_SAFE FALSE) + + _juce_set_property_if_not_set(${target} HARDENED_RUNTIME_ENABLED NO) + _juce_set_property_if_not_set(${target} APP_SANDBOX_ENABLED NO) + _juce_set_property_if_not_set(${target} APP_SANDBOX_INHERIT NO) + + get_target_property(is_synth ${target} JUCE_IS_SYNTH) + + # VST3_CATEGORIES + if(is_synth) + _juce_set_property_if_not_set(${target} VST3_CATEGORIES Instrument Synth) + else() + _juce_set_property_if_not_set(${target} VST3_CATEGORIES Fx) + endif() + + # VST2_CATEGORY + if(is_synth) + _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategSynth) + else() + _juce_set_property_if_not_set(${target} VST2_CATEGORY kPlugCategEffect) + endif() + + get_target_property(is_midi_effect ${target} JUCE_IS_MIDI_EFFECT) + get_target_property(needs_midi_input ${target} JUCE_NEEDS_MIDI_INPUT) + + # AU MAIN TYPE + if(is_midi_effect) + _juce_set_property_if_not_set(${target} AU_MAIN_TYPE 'aumi') + elseif(is_synth) + _juce_set_property_if_not_set(${target} AU_MAIN_TYPE 'aumu') + elseif(needs_midi_input) + _juce_set_property_if_not_set(${target} AU_MAIN_TYPE 'aumf') + else() + _juce_set_property_if_not_set(${target} AU_MAIN_TYPE 'aufx') + endif() + + # AU export prefix + string(MAKE_C_IDENTIFIER ${output_name} au_prefix) + set(au_prefix "${au_prefix}AU") + _juce_set_property_if_not_set(${target} AU_EXPORT_PREFIX ${au_prefix}) + + # AAX category + set(aax_category_ints + 0x00000000 + 0x00000001 + 0x00000002 + 0x00000004 + 0x00000008 + 0x00000010 + 0x00000020 + 0x00000040 + 0x00000080 + 0x00000100 + 0x00000200 + 0x00000400 + 0x00000800 + 0x00001000 + 0x00002000) + + set(aax_category_strings + ePlugInCategory_None + ePlugInCategory_EQ + ePlugInCategory_Dynamics + ePlugInCategory_PitchShift + ePlugInCategory_Reverb + ePlugInCategory_Delay + ePlugInCategory_Modulation + ePlugInCategory_Harmonic + ePlugInCategory_NoiseReduction + ePlugInCategory_Dither + ePlugInCategory_SoundField + ePlugInCategory_HWGenerators + ePlugInCategory_SWGenerators + ePlugInCategory_WrappedPlugin + ePlugInCategory_Effect) + + if(is_synth) + set(default_aax_category ePlugInCategory_SWGenerators) + else() + set(default_aax_category ePlugInCategory_None) + endif() + + _juce_set_property_if_not_set(${target} AAX_CATEGORY ${default_aax_category}) + + # Replace AAX category string with its integral representation + get_target_property(actual_aax_category ${target} JUCE_AAX_CATEGORY) + list(FIND aax_category_strings ${actual_aax_category} aax_index) + + if(aax_index GREATER_EQUAL 0) + list(GET aax_category_ints ${aax_index} aax_int_representation) + set_target_properties(${target} PROPERTIES JUCE_AAX_CATEGORY ${aax_int_representation}) + endif() +endfunction() + +# ================================================================================================== + +function(_juce_initialise_target target) + set(one_value_args + VERSION + PRODUCT_NAME + PLIST_TO_MERGE + BUNDLE_ID + MICROPHONE_PERMISSION_ENABLED + MICROPHONE_PERMISSION_TEXT + CAMERA_PERMISSION_ENABLED + CAMERA_PERMISSION_TEXT + SEND_APPLE_EVENTS_PERMISSION_ENABLED + SEND_APPLE_EVENTS_PERMISSION_TEXT + BLUETOOTH_PERMISSION_ENABLED # iOS only + BLUETOOTH_PERMISSION_TEXT # iOS only + FILE_SHARING_ENABLED # iOS only + DOCUMENT_BROWSER_ENABLED # iOS only + LAUNCH_STORYBOARD_FILE # iOS only + APP_GROUPS_ENABLED # iOS only + ICLOUD_PERMISSIONS_ENABLED # iOS only + STATUS_BAR_HIDDEN # iOS only + BACKGROUND_AUDIO_ENABLED # iOS only + BACKGROUND_BLE_ENABLED # iOS only + CUSTOM_XCASSETS_FOLDER # iOS only + ICON_BIG + ICON_SMALL + COMPANY_COPYRIGHT + COMPANY_NAME + COMPANY_WEBSITE + COMPANY_EMAIL + NEEDS_CURL # Set this true if you want to link curl on Linux + NEEDS_WEB_BROWSER # Set this true if you want to link webkit on Linux + NEEDS_STORE_KIT # Set this true if you want in-app-purchases on Mac + PUSH_NOTIFICATIONS_ENABLED + HARDENED_RUNTIME_ENABLED + APP_SANDBOX_ENABLED + APP_SANDBOX_INHERIT + + PLUGIN_MANUFACTURER_CODE + PLUGIN_CODE + DESCRIPTION + IS_SYNTH + NEEDS_MIDI_INPUT + NEEDS_MIDI_OUTPUT + IS_MIDI_EFFECT + EDITOR_WANTS_KEYBOARD_FOCUS + DISABLE_AAX_BYPASS + DISABLE_AAX_MULTI_MONO + AAX_IDENTIFIER + VST_NUM_MIDI_INS + VST_NUM_MIDI_OUTS + VST2_CATEGORY + AU_MAIN_TYPE + AU_EXPORT_PREFIX + AU_SANDBOX_SAFE + AAX_CATEGORY + + VST_COPY_DIR + VST3_COPY_DIR + AAX_COPY_DIR + AU_COPY_DIR + UNITY_COPY_DIR + COPY_PLUGIN_AFTER_BUILD) + + set(multi_value_args + FORMATS + VST3_CATEGORIES + HARDENED_RUNTIME_OPTIONS + APP_SANDBOX_OPTIONS + DOCUMENT_EXTENSIONS + IPHONE_SCREEN_ORIENTATIONS # iOS only + IPAD_SCREEN_ORIENTATIONS # iOS only + APP_GROUP_IDS) # iOS only + + cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN}) + + set(base_folder "${CMAKE_CURRENT_BINARY_DIR}/${target}_artefacts") + set(products_folder "${base_folder}/$") + set(juce_library_code "${base_folder}/JuceLibraryCode") + + set_target_properties(${target} PROPERTIES JUCE_GENERATED_SOURCES_DIRECTORY "${juce_library_code}") + + set_target_properties(${target} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${products_folder}" + LIBRARY_OUTPUT_DIRECTORY "${products_folder}" + RUNTIME_OUTPUT_DIRECTORY "${products_folder}") + + if(JUCE_ARG_ICON_BIG) + _juce_make_absolute_and_check(JUCE_ARG_ICON_BIG) + endif() + + if(JUCE_ARG_ICON_SMALL) + _juce_make_absolute_and_check(JUCE_ARG_ICON_SMALL) + endif() + + # Add each of the function arguments as target properties, so that it's easier to + # extract them in other functions + foreach(arg_string IN ITEMS ${one_value_args} ${multi_value_args}) + _juce_set_property_if_not_set(${target} ${arg_string} "${JUCE_ARG_${arg_string}}") + endforeach() + + _juce_set_fallback_properties(${target}) + + target_include_directories(${target} PRIVATE + $) + target_link_libraries(${target} PUBLIC $<$:juce_vst2_sdk>) + + _juce_write_generate_time_info(${target}) + _juce_link_optional_libraries(${target}) +endfunction() + +# ================================================================================================== + +function(juce_add_console_app target) + add_executable(${target}) + target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1) + _juce_initialise_target(${target} ${ARGN}) +endfunction() + +function(juce_add_gui_app target) + if(CMAKE_SYSTEM_NAME STREQUAL "Android") + add_library(${target} SHARED) + else() + add_executable(${target}) + endif() + + target_compile_definitions(${target} PRIVATE JUCE_STANDALONE_APPLICATION=1) + _juce_initialise_target(${target} ${ARGN}) + _juce_set_output_name(${target} $) + set_target_properties(${target} PROPERTIES JUCE_TARGET_KIND_STRING "App") + _juce_configure_bundle(${target} ${target}) + _juce_configure_app_bundle(${target} ${target}) +endfunction() + +function(juce_add_plugin target) + add_library(${target} STATIC) + set_target_properties(${target} PROPERTIES JUCE_IS_PLUGIN TRUE) + _juce_initialise_target(${target} ${ARGN}) + _juce_configure_plugin_targets(${target}) +endfunction() + +# ================================================================================================== + +function(_juce_target_args_from_plugin_characteristics out_var) + set(pairs + "pluginIsSynth\;IS_SYNTH" + "pluginWantsMidiIn\;NEEDS_MIDI_INPUT" + "pluginProducesMidiOut\;NEEDS_MIDI_OUTPUT" + "pluginIsMidiEffectPlugin\;IS_MIDI_EFFECT" + "pluginEditorRequiresKeys\;EDITOR_WANTS_KEYBOARD_FOCUS") + + set(result) + + foreach(pair IN ITEMS ${pairs}) + list(GET pair 0 old_key) + + if("${old_key}" IN_LIST ARGN) + list(GET pair 1 new_key) + list(APPEND result ${new_key} TRUE) + endif() + endforeach() + + set(${out_var} ${result} PARENT_SCOPE) +endfunction() + +# ================================================================================================== + +function(_juce_get_pip_targets pip out_var) + set(test_targets "${pip}") + + _juce_get_all_plugin_kinds(plugin_kinds) + + foreach(plugin_kind IN ITEMS ${plugin_kinds}) + list(APPEND test_targets "${JUCE_PIP_NAME}_${plugin_kind}") + endforeach() + + set(${out_var} ${test_targets} PARENT_SCOPE) +endfunction() + +function(juce_add_pip header) + _juce_make_absolute(header) + + _juce_extract_metadata_block(JUCE_PIP_METADATA "${header}" metadata_dict) + + _juce_get_metadata("${metadata_dict}" name JUCE_PIP_NAME) + + if(NOT JUCE_PIP_NAME) + message(FATAL_ERROR "PIP headers must declare a `name` field") + endif() + + string(MAKE_C_IDENTIFIER "${JUCE_PIP_NAME}" pip_name_sanitised) + + if(NOT JUCE_PIP_NAME STREQUAL pip_name_sanitised) + message(FATAL_ERROR "PIP `name` value '${JUCE_PIP_NAME}' must be a valid C identifier") + endif() + + if(TARGET "${JUCE_PIP_NAME}") + # We already added a target with this name, let's try using the filename instead + get_filename_component(JUCE_PIP_NAME "${header}" NAME_WE) + endif() + + if(TARGET "${JUCE_PIP_NAME}") + message(FATAL_ERROR "Could not create a unique target name for PIP ${header}") + endif() + + _juce_get_metadata("${metadata_dict}" type pip_kind) + + if(NOT pip_kind) + message(FATAL_ERROR "PIP headers must declare a `type` field") + endif() + + _juce_get_metadata("${metadata_dict}" pluginCharacteristics pip_charateristics) + + _juce_target_args_from_plugin_characteristics(extra_target_args ${pip_charateristics}) + + list(APPEND extra_target_args + NEEDS_CURL TRUE + NEEDS_WEB_BROWSER TRUE) + + _juce_get_metadata("${metadata_dict}" moduleFlags pip_moduleflags) + + if("JUCE_IN_APP_PURCHASES=1" IN_LIST pip_moduleflags) + list(APPEND extra_target_args + BUNDLE_ID "com.roli.juceInAppPurchaseSample" + NEEDS_STORE_KIT TRUE) + endif() + + if(pip_kind STREQUAL "AudioProcessor") + set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in") + + # We add AAX/VST2 targets too, if the user has set up those SDKs + + set(extra_formats) + + if(TARGET juce_aax_sdk) + list(APPEND extra_formats AAX) + endif() + + if(TARGET juce_vst2_sdk) + list(APPEND extra_formats VST) + endif() + + # Standalone plugins might want to access the mic + list(APPEND extra_target_args MICROPHONE_PERMISSION_ENABLED TRUE) + + juce_add_plugin(${JUCE_PIP_NAME} + FORMATS AU AUv3 VST3 Unity Standalone ${extra_formats} + ${extra_target_args}) + elseif(pip_kind STREQUAL "Component") + set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPComponent.cpp.in") + juce_add_gui_app(${JUCE_PIP_NAME} ${extra_target_args}) + elseif(pip_kind STREQUAL "Console") + set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPConsole.cpp.in") + juce_add_console_app(${JUCE_PIP_NAME} ${extra_target_args}) + else() + message(FATAL_ERROR "PIP kind must be either AudioProcessor, Component, or Console") + endif() + + # Generate Main.cpp + _juce_get_metadata("${metadata_dict}" mainClass JUCE_PIP_MAIN_CLASS) + get_target_property(juce_library_code ${JUCE_PIP_NAME} JUCE_GENERATED_SOURCES_DIRECTORY) + set(pip_main "${juce_library_code}/Main.cpp") + + set(JUCE_PIP_HEADER "${header}") + configure_file(${source_main} ${pip_main}) + target_sources(${JUCE_PIP_NAME} PRIVATE ${pip_main}) + + _juce_get_metadata("${metadata_dict}" dependencies pip_dependencies) + + juce_generate_juce_header(${JUCE_PIP_NAME}) + + foreach(module IN ITEMS ${pip_dependencies}) + set(discovered_module) + + # If we're building a PIP from outside the current build tree, the JUCE modules + # might be namespaced, so we try adding a namespace if we can't find a target with + # the name given in the metadata block. + if(TARGET "${module}") + set(discovered_module "${module}") + elseif(TARGET "juce::${module}") + set(discovered_module "juce::${module}") + else() + message(FATAL_ERROR "No such module: ${module}") + endif() + + target_link_libraries(${JUCE_PIP_NAME} PRIVATE ${discovered_module}) + endforeach() + + target_compile_definitions(${JUCE_PIP_NAME} + PRIVATE ${pip_moduleflags} + PUBLIC JUCE_VST3_CAN_REPLACE_VST2=0) + + _juce_get_pip_targets(${JUCE_PIP_NAME} pip_targets) + + # This keeps the PIPs slightly better organised in the JUCE megaproject + if((DEFINED JUCE_SOURCE_DIR) AND (header MATCHES "^${JUCE_SOURCE_DIR}")) + file(RELATIVE_PATH folder "${JUCE_SOURCE_DIR}" "${header}") + get_filename_component(folder_parent "${folder}" DIRECTORY) + + foreach(target_name IN ITEMS ${pip_targets} ${JUCE_PIP_NAME}_All) + if(TARGET "${target_name}") + set_target_properties("${target_name}" PROPERTIES + FOLDER "${folder_parent}/${JUCE_PIP_NAME}") + endif() + endforeach() + endif() + + # We're building JUCE itself + if(DEFINED JUCE_SOURCE_DIR) + # PIPs need to know about the resources folder + target_compile_definitions(${JUCE_PIP_NAME} PRIVATE + PIP_JUCE_EXAMPLES_DIRECTORY_STRING="${JUCE_SOURCE_DIR}/examples") + + get_filename_component(pip_parent_path "${header}" DIRECTORY) + target_include_directories(${JUCE_PIP_NAME} PRIVATE "${pip_parent_path}") + + if((CMAKE_SYSTEM_NAME STREQUAL "iOS") AND (header MATCHES "^${JUCE_SOURCE_DIR}")) + foreach(target_name IN ITEMS ${pip_targets}) + if(TARGET "${target_name}") + juce_add_bundle_resources_directory("${target_name}" "${JUCE_SOURCE_DIR}/examples/Assets") + endif() + endforeach() + endif() + endif() +endfunction() + +# ================================================================================================== + +function(juce_set_aax_sdk_path path) + if(TARGET juce_aax_sdk) + message(FATAL_ERROR "juce_set_aax_sdk_path should only be called once") + endif() + + _juce_make_absolute(path) + + if((NOT EXISTS "${path}") + OR (NOT EXISTS "${path}/Interfaces") + OR (NOT EXISTS "${path}/Interfaces/ACF")) + message(FATAL_ERROR "Could not find AAX SDK at the specified path: ${path}") + endif() + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + add_library(juce_aax_sdk STATIC IMPORTED) + set_target_properties(juce_aax_sdk PROPERTIES + IMPORTED_LOCATION_DEBUG "${path}/Libs/Debug/libAAXLibrary_libcpp.a" + IMPORTED_LOCATION "${path}/Libs/Release/libAAXLibrary_libcpp.a") + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + add_library(juce_aax_sdk INTERFACE IMPORTED) + else() + return() + endif() + + target_include_directories(juce_aax_sdk INTERFACE + "${path}" + "${path}/Interfaces" + "${path}/Interfaces/ACF") + target_compile_definitions(juce_aax_sdk INTERFACE JucePlugin_AAXLibs_path="${path}/Libs") + set_target_properties(juce_aax_sdk PROPERTIES INTERFACE_JUCE_AAX_DEFAULT_ICON "${path}/Utilities/PlugIn.ico") +endfunction() + +function(juce_set_vst2_sdk_path path) + if(TARGET juce_vst2_sdk) + message(FATAL_ERROR "juce_set_vst2_sdk_path should only be called once") + endif() + + _juce_make_absolute(path) + + if(NOT EXISTS "${path}") + message(FATAL_ERROR "Could not find VST2 SDK at the specified path: ${path}") + endif() + + add_library(juce_vst2_sdk INTERFACE IMPORTED) + + # This is a bit of a hack, but we really need the VST2 paths to always follow the VST3 paths. + target_include_directories(juce_vst2_sdk INTERFACE + $ + "${path}") +endfunction() diff --git a/extras/Build/CMake/LaunchScreen.storyboard b/extras/Build/CMake/LaunchScreen.storyboard new file mode 100644 index 0000000000..ce0d6fd7a7 --- /dev/null +++ b/extras/Build/CMake/LaunchScreen.storyboard @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/extras/Build/CMake/PIPAudioProcessor.cpp.in b/extras/Build/CMake/PIPAudioProcessor.cpp.in new file mode 100644 index 0000000000..52c79a0c4e --- /dev/null +++ b/extras/Build/CMake/PIPAudioProcessor.cpp.in @@ -0,0 +1,16 @@ +/* + ============================================================================== + + This file was auto-generated and contains the startup code for a PIP. + + ============================================================================== +*/ + +#include +#include "${JUCE_PIP_HEADER}" + +//============================================================================== +AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new ${JUCE_PIP_MAIN_CLASS}(); +} diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp b/extras/Build/CMake/PIPComponent.cpp.in similarity index 70% rename from extras/Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp rename to extras/Build/CMake/PIPComponent.cpp.in index da0677bdd1..52347dd8c2 100644 --- a/extras/Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp +++ b/extras/Build/CMake/PIPComponent.cpp.in @@ -1,77 +1,68 @@ -/* - ============================================================================== - - This file was auto-generated and contains the startup code for a PIP. - - ============================================================================== -*/ - -%%include_juce%% -#include "%%filename%%" - -%%component_begin%% -class Application : public JUCEApplication -{ -public: - //============================================================================== - Application() {} - - const String getApplicationName() override { return "%%project_name%%"; } - const String getApplicationVersion() override { return "%%project_version%%"; } - - void initialise (const String&) override { %%startup%% } - void shutdown() override { %%shutdown%% } - -private: - class MainWindow : public DocumentWindow - { - public: - MainWindow (const String& name, Component* c, JUCEApplication& a) - : DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel() - .findColour (ResizableWindow::backgroundColourId), - DocumentWindow::allButtons), - app (a) - { - setUsingNativeTitleBar (true); - setContentOwned (c, true); - - #if JUCE_ANDROID || JUCE_IOS - setFullScreen (true); - #else - setResizable (true, false); - setResizeLimits (300, 250, 10000, 10000); - centreWithSize (getWidth(), getHeight()); - #endif - - setVisible (true); - } - - void closeButtonPressed() override - { - app.systemRequestedQuit(); - } - - private: - JUCEApplication& app; - - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) - }; - - std::unique_ptr mainWindow; -}; - -//============================================================================== -START_JUCE_APPLICATION (Application) -%%component_end%% - -%%audioprocessor_begin%% -//============================================================================== -AudioProcessor* JUCE_CALLTYPE createPluginFilter() -{ - return new %%class_name%%(); -} -%%audioprocessor_end%% - -%%console_begin%% -%%console_end%% +/* + ============================================================================== + + This file was auto-generated and contains the startup code for a PIP. + + ============================================================================== +*/ + +#include +#include "${JUCE_PIP_HEADER}" + +class Application : public JUCEApplication +{ +public: + //============================================================================== + Application() {} + + const String getApplicationName() override { return "${JUCE_PIP_NAME}"; } + const String getApplicationVersion() override { return "${PROJECT_VERSION}"; } + + void initialise (const String&) override + { + mainWindow.reset (new MainWindow ("${JUCE_PIP_NAME}", new ${JUCE_PIP_MAIN_CLASS}, *this)); + } + + void shutdown() override { mainWindow = nullptr; } + +private: + class MainWindow : public DocumentWindow + { + public: + MainWindow (const String& name, Component* c, JUCEApplication& a) + : DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel() + .findColour (ResizableWindow::backgroundColourId), + DocumentWindow::allButtons), + app (a) + { + setUsingNativeTitleBar (true); + setContentOwned (c, true); + + #if JUCE_ANDROID || JUCE_IOS + setFullScreen (true); + #else + setResizable (true, false); + setResizeLimits (300, 250, 10000, 10000); + centreWithSize (getWidth(), getHeight()); + #endif + + setVisible (true); + } + + void closeButtonPressed() override + { + app.systemRequestedQuit(); + } + + private: + JUCEApplication& app; + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) + }; + + std::unique_ptr mainWindow; +}; + +//============================================================================== +START_JUCE_APPLICATION (Application) diff --git a/extras/Build/CMake/PIPConsole.cpp.in b/extras/Build/CMake/PIPConsole.cpp.in new file mode 100644 index 0000000000..ee311ad08d --- /dev/null +++ b/extras/Build/CMake/PIPConsole.cpp.in @@ -0,0 +1,10 @@ +/* + ============================================================================== + + This file was auto-generated and contains the startup code for a PIP. + + ============================================================================== +*/ + +#include +#include "${JUCE_PIP_HEADER}" diff --git a/extras/Projucer/Source/BinaryData/RecentFilesMenuTemplate.nib b/extras/Build/CMake/RecentFilesMenuTemplate.nib similarity index 100% rename from extras/Projucer/Source/BinaryData/RecentFilesMenuTemplate.nib rename to extras/Build/CMake/RecentFilesMenuTemplate.nib diff --git a/extras/Projucer/Source/BinaryData/Templates/jucer_UnityPluginGUIScript.cs b/extras/Build/CMake/UnityPluginGUIScript.cs.in similarity index 78% rename from extras/Projucer/Source/BinaryData/Templates/jucer_UnityPluginGUIScript.cs rename to extras/Build/CMake/UnityPluginGUIScript.cs.in index 3b15b1f87e..3f00b9083a 100644 --- a/extras/Projucer/Source/BinaryData/Templates/jucer_UnityPluginGUIScript.cs +++ b/extras/Build/CMake/UnityPluginGUIScript.cs.in @@ -6,24 +6,24 @@ using UnityEngine; using System.Collections.Generic; using System.Runtime.InteropServices; -public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI +public class ${plugin_class_name}GUI : IAudioEffectPluginGUI { - public override string Name { get { return "%%plugin_name%%"; } } - public override string Description { get { return "%%plugin_description%%"; } } - public override string Vendor { get { return "%%plugin_vendor%%"; } } + public override string Name { get { return "${plugin_name}"; } } + public override string Description { get { return "${plugin_description}"; } } + public override string Vendor { get { return "${plugin_vendor}"; } } //============================================================================== - [DllImport("%%plugin_name%%")] static extern System.IntPtr getRenderCallback(); + [DllImport("${plugin_name}")] static extern System.IntPtr getRenderCallback(); - [DllImport("%%plugin_name%%")] static extern void unityInitialiseTexture (int id, System.IntPtr texture, int width, int height); + [DllImport("${plugin_name}")] static extern void unityInitialiseTexture (int id, System.IntPtr texture, int width, int height); - [DllImport("%%plugin_name%%")] static extern void unityMouseDown (int id, float x, float y, EventModifiers mods, int button); - [DllImport("%%plugin_name%%")] static extern void unityMouseDrag (int id, float x, float y, EventModifiers mods, int button); - [DllImport("%%plugin_name%%")] static extern void unityMouseUp (int id, float x, float y, EventModifiers mods); + [DllImport("${plugin_name}")] static extern void unityMouseDown (int id, float x, float y, EventModifiers mods, int button); + [DllImport("${plugin_name}")] static extern void unityMouseDrag (int id, float x, float y, EventModifiers mods, int button); + [DllImport("${plugin_name}")] static extern void unityMouseUp (int id, float x, float y, EventModifiers mods); - [DllImport("%%plugin_name%%")] static extern void unityKeyEvent (int id, KeyCode code, EventModifiers mods, string name); + [DllImport("${plugin_name}")] static extern void unityKeyEvent (int id, KeyCode code, EventModifiers mods, string name); - [DllImport("%%plugin_name%%")] static extern void unitySetScreenBounds (int id, float x, float y, float w, float h); + [DllImport("${plugin_name}")] static extern void unitySetScreenBounds (int id, float x, float y, float w, float h); //============================================================================== private class PluginGUIInstance @@ -38,10 +38,10 @@ public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI } public void repaint (Rect r) - { + { Vector2 newScreenPosition = GUIUtility.GUIToScreenPoint (r.position); - if (bounds != r + if (bounds != r || screenPosition != newScreenPosition) { screenPosition = newScreenPosition; @@ -51,7 +51,7 @@ public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI setupTexture(); } - GL.IssuePluginEvent (getRenderCallback(), instanceID); + GL.IssuePluginEvent (getRenderCallback(), instanceID); texture.SetPixels32 (pixels); texture.Apply(); @@ -69,7 +69,7 @@ public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI Vector2 relativePos = new Vector2 (mousePos.x - bounds.x, mousePos.y - bounds.y); - if (eventType == EventType.MouseDown) + if (eventType == EventType.MouseDown) { unityMouseDown (instanceID, relativePos.x, relativePos.y, mods, Event.current.button); GUIUtility.hotControl = GUIUtility.GetControlID (FocusType.Passive); @@ -79,7 +79,7 @@ public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI unityMouseUp (instanceID, relativePos.x, relativePos.y, mods); GUIUtility.hotControl = 0; } - else if (eventType == EventType.MouseDrag) + else if (eventType == EventType.MouseDrag) { unityMouseDrag (instanceID, relativePos.x, relativePos.y, mods, Event.current.button); } diff --git a/extras/Build/CMake/copyDir.cmake b/extras/Build/CMake/copyDir.cmake new file mode 100644 index 0000000000..e50ebbf5ad --- /dev/null +++ b/extras/Build/CMake/copyDir.cmake @@ -0,0 +1,17 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +file(INSTALL ${src} DESTINATION ${dest}) diff --git a/extras/Build/CMakeLists.txt b/extras/Build/CMakeLists.txt new file mode 100644 index 0000000000..24b3e42043 --- /dev/null +++ b/extras/Build/CMakeLists.txt @@ -0,0 +1,20 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_module(juce_build_tools ALIAS_NAMESPACE juce) + +add_subdirectory(juceaide) + diff --git a/extras/Build/juce_build_tools/juce_build_tools.cpp b/extras/Build/juce_build_tools/juce_build_tools.cpp new file mode 100644 index 0000000000..3cf86744bf --- /dev/null +++ b/extras/Build/juce_build_tools/juce_build_tools.cpp @@ -0,0 +1,40 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +#ifdef JUCE_BUILD_TOOLS_H_INCLUDED + /* When you add this cpp file to your project, you mustn't include it in a file where you've + already included any other headers - just put it inside a file on its own, possibly with your config + flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix + header files that the compiler may be using. + */ + #error "Incorrect use of JUCE cpp file" +#endif + +#include "juce_build_tools.h" + +#include + +#include "utils/juce_CppTokeniserFunctions.cpp" +#include "utils/juce_BuildHelperFunctions.cpp" +#include "utils/juce_BinaryResourceFile.cpp" +#include "utils/juce_Icons.cpp" +#include "utils/juce_PlistOptions.cpp" +#include "utils/juce_ResourceFileHelpers.cpp" +#include "utils/juce_ResourceRc.cpp" +#include "utils/juce_VersionNumbers.cpp" +#include "utils/juce_Entitlements.cpp" diff --git a/extras/Build/juce_build_tools/juce_build_tools.h b/extras/Build/juce_build_tools/juce_build_tools.h new file mode 100644 index 0000000000..af7844e268 --- /dev/null +++ b/extras/Build/juce_build_tools/juce_build_tools.h @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +/******************************************************************************* + The block below describes the properties of this module, and is read by + the Projucer to automatically generate project code that uses it. + For details about the syntax and how to create or use a module, see the + JUCE Module Format.txt file. + + + BEGIN_JUCE_MODULE_DECLARATION + + ID: juce_build_tools + vendor: juce + version: 6.0.0 + name: JUCE Build Tools + description: Classes for generating intermediate files for JUCE projects. + website: http://www.juce.com/juce + license: GPL/Commercial + + dependencies: juce_gui_basics + + END_JUCE_MODULE_DECLARATION + +*******************************************************************************/ + +// This module is shared by juceaide and the Projucer, but should not be +// considered 'public'. That is, its API, functionality, and contents (and +// existence!) may change between releases without warning. + +#pragma once +#define JUCE_BUILD_TOOLS_H_INCLUDED + +#include + +#include "utils/juce_ProjectType.h" +#include "utils/juce_BuildHelperFunctions.h" +#include "utils/juce_BinaryResourceFile.h" +#include "utils/juce_RelativePath.h" +#include "utils/juce_Icons.h" +#include "utils/juce_PlistOptions.h" +#include "utils/juce_ResourceFileHelpers.h" +#include "utils/juce_ResourceRc.h" +#include "utils/juce_VersionNumbers.h" +#include "utils/juce_Entitlements.h" diff --git a/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.cpp b/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.cpp new file mode 100644 index 0000000000..9c2d65cc3a --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.cpp @@ -0,0 +1,280 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + static const char* resourceFileIdentifierString = "JUCER_BINARY_RESOURCE"; + + //============================================================================== + void ResourceFile::setClassName (const String& name) + { + className = name; + } + + void ResourceFile::addFile (const File& file) + { + files.add (file); + + auto variableNameRoot = makeBinaryDataIdentifierName (file); + auto variableName = variableNameRoot; + + int suffix = 2; + + while (variableNames.contains (variableName)) + variableName = variableNameRoot + String (suffix++); + + variableNames.add (variableName); + } + + String ResourceFile::getDataVariableFor (const File& file) const + { + const auto index = files.indexOf (file); + jassert (index >= 0); + return variableNames[index]; + } + + String ResourceFile::getSizeVariableFor (const File& file) const + { + return getDataVariableFor (file) + "Size"; + } + + int64 ResourceFile::getTotalDataSize() const + { + return std::accumulate (files.begin(), + files.end(), + int64 { 0 }, + [] (int64 acc, const File& f) { return acc + f.getSize(); }); + } + + static void writeComment (MemoryOutputStream& mo) + { + mo << newLine << newLine + << " This is an auto-generated file: Any edits you make may be overwritten!" << newLine + << newLine + << "*/" << newLine + << newLine; + } + + Result ResourceFile::writeHeader (MemoryOutputStream& header) + { + header << "/* ========================================================================================="; + writeComment (header); + header << "#pragma once" << newLine + << newLine + << "namespace " << className << newLine + << "{" << newLine; + + for (int i = 0; i < files.size(); ++i) + { + auto& file = files.getReference(i); + + if (! file.existsAsFile()) + return Result::fail ("Can't open resource file: " + file.getFullPathName()); + + auto dataSize = file.getSize(); + + auto variableName = variableNames[i]; + + FileInputStream fileStream (file); + + if (fileStream.openedOk()) + { + header << " extern const char* " << variableName << ";" << newLine; + header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine; + } + } + + header << " // Number of elements in the namedResourceList and originalFileNames arrays." << newLine + << " const int namedResourceListSize = " << files.size() << ";" << newLine + << newLine + << " // Points to the start of a list of resource names." << newLine + << " extern const char* namedResourceList[];" << newLine + << newLine + << " // Points to the start of a list of resource filenames." << newLine + << " extern const char* originalFilenames[];" << newLine + << newLine + << " // If you provide the name of one of the binary resource variables above, this function will" << newLine + << " // return the corresponding data and its size (or a null pointer if the name isn't found)." << newLine + << " const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes);" << newLine + << newLine + << " // If you provide the name of one of the binary resource variables above, this function will" << newLine + << " // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found)." << newLine + << " const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine + << "}" << newLine; + + return Result::ok(); + } + + Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize) + { + bool isFirstFile = (i == 0); + + cpp << "/* ==================================== " << resourceFileIdentifierString << " ===================================="; + writeComment (cpp); + cpp << "namespace " << className << newLine + << "{" << newLine; + + while (i < files.size()) + { + auto& file = files.getReference(i); + auto variableName = variableNames[i]; + + FileInputStream fileStream (file); + + if (fileStream.openedOk()) + { + auto tempVariable = "temp_binary_data_" + String (i); + + cpp << newLine << "//================== " << file.getFileName() << " ==================" << newLine + << "static const unsigned char " << tempVariable << "[] =" << newLine; + + { + MemoryBlock data; + fileStream.readIntoMemoryBlock (data); + writeDataAsCppLiteral (data, cpp, true, true); + } + + cpp << newLine << newLine + << "const char* " << variableName << " = (const char*) " << tempVariable << ";" << newLine; + } + + ++i; + + if (cpp.getPosition() > maxFileSize) + break; + } + + if (isFirstFile) + { + if (i < files.size()) + { + cpp << newLine + << "}" << newLine + << newLine + << "#include \"" << headerFile.getFileName() << "\"" << newLine + << newLine + << "namespace " << className << newLine + << "{"; + } + + cpp << newLine + << newLine + << "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)" << newLine + << "{" << newLine; + + StringArray returnCodes; + for (auto& file : files) + { + auto dataSize = file.getSize(); + returnCodes.add ("numBytes = " + String (dataSize) + "; return " + variableNames[files.indexOf (file)] + ";"); + } + + createStringMatcher (cpp, "resourceNameUTF8", variableNames, returnCodes, 4); + + cpp << " numBytes = 0;" << newLine + << " return nullptr;" << newLine + << "}" << newLine + << newLine; + + cpp << "const char* namedResourceList[] =" << newLine + << "{" << newLine; + + for (int j = 0; j < files.size(); ++j) + cpp << " " << variableNames[j].quoted() << (j < files.size() - 1 ? "," : "") << newLine; + + cpp << "};" << newLine << newLine; + + cpp << "const char* originalFilenames[] =" << newLine + << "{" << newLine; + + for (auto& f : files) + cpp << " " << f.getFileName().quoted() << (files.indexOf (f) < files.size() - 1 ? "," : "") << newLine; + + cpp << "};" << newLine << newLine; + + cpp << "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8)" << newLine + << "{" << newLine + << " for (unsigned int i = 0; i < (sizeof (namedResourceList) / sizeof (namedResourceList[0])); ++i)" << newLine + << " {" << newLine + << " if (namedResourceList[i] == resourceNameUTF8)" << newLine + << " return originalFilenames[i];" << newLine + << " }" << newLine + << newLine + << " return nullptr;" << newLine + << "}" << newLine + << newLine; + } + + cpp << "}" << newLine; + + return Result::ok(); + } + + ResourceFile::WriteResult ResourceFile::write (int maxFileSize, + String projectLineFeed, + File headerFile, + std::function getCppFile) + { + Array filesCreated; + + { + MemoryOutputStream mo; + mo.setNewLineString (projectLineFeed); + + auto r = writeHeader (mo); + + if (r.failed()) + return { r }; + + if (! overwriteFileWithNewDataIfDifferent (headerFile, mo)) + return { Result::fail ("Can't write to file: " + headerFile.getFullPathName()) }; + + filesCreated.add (headerFile); + } + + int i = 0; + int fileIndex = 0; + + for (;;) + { + auto cpp = getCppFile (fileIndex); + + MemoryOutputStream mo; + mo.setNewLineString (projectLineFeed); + + auto r = writeCpp (mo, headerFile, i, maxFileSize); + + if (r.failed()) + return { r, std::move (filesCreated) }; + + if (! overwriteFileWithNewDataIfDifferent (cpp, mo)) + return { Result::fail ("Can't write to file: " + cpp.getFullPathName()), std::move (filesCreated) }; + + filesCreated.add (cpp); + ++fileIndex; + + if (i >= files.size()) + break; + } + + return { Result::ok(), std::move (filesCreated) }; + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.h b/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.h new file mode 100644 index 0000000000..000dc42c42 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_BinaryResourceFile.h @@ -0,0 +1,67 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + class ResourceFile + { + public: + ResourceFile() = default; + + void setClassName (const String& className); + + String getClassName() const { return className; } + + void addFile (const File& file); + + String getDataVariableFor (const File& file) const; + + String getSizeVariableFor (const File& file) const; + + int getNumFiles() const { return files.size (); } + + const File& getFile (int index) const { return files.getReference (index); } + + int64 getTotalDataSize() const; + + struct WriteResult + { + Result result; + Array filesCreated; + }; + + WriteResult write (int maxFileSize, + String projectLineFeed, + File headerFile, + std::function getCppFile); + + private: + Array files; + StringArray variableNames; + String className { "BinaryData" }; + + Result writeHeader (MemoryOutputStream&); + + Result writeCpp (MemoryOutputStream&, const File&, int&, int); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResourceFile) + }; +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.cpp b/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.cpp new file mode 100644 index 0000000000..3d711ae6a5 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.cpp @@ -0,0 +1,344 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData) + { + if (! overwriteFileWithNewDataIfDifferent (file, newData)) + throw SaveError (file); + } + + void overwriteFileIfDifferentOrThrow (const File& file, const String& newData) + { + if (! overwriteFileWithNewDataIfDifferent (file, newData)) + throw SaveError (file); + } + + String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString) + { + for (int i = 0; i < definitions.size(); ++i) + { + const String key (definitions.getAllKeys()[i]); + const String value (definitions.getAllValues()[i]); + + sourceString = sourceString.replace ("${" + key + "}", value); + } + + return sourceString; + } + + String getXcodePackageType (ProjectType::Target::Type type) + { + switch (type) + { + case ProjectType::Target::Type::GUIApp: + case ProjectType::Target::Type::StandalonePlugIn: + return "APPL"; + + case ProjectType::Target::Type::VSTPlugIn: + case ProjectType::Target::Type::VST3PlugIn: + case ProjectType::Target::Type::AudioUnitPlugIn: + case ProjectType::Target::Type::UnityPlugIn: + return "BNDL"; + + case ProjectType::Target::Type::AudioUnitv3PlugIn: + return "XPC!"; + + case ProjectType::Target::Type::AAXPlugIn: + case ProjectType::Target::Type::RTASPlugIn: + return "TDMw"; + + case ProjectType::Target::Type::ConsoleApp: + case ProjectType::Target::Type::StaticLibrary: + case ProjectType::Target::Type::DynamicLibrary: + case ProjectType::Target::Type::SharedCodeTarget: + case ProjectType::Target::Type::AggregateTarget: + case ProjectType::Target::Type::unspecified: + default: + return {}; + } + } + + String getXcodeBundleSignature (ProjectType::Target::Type type) + { + switch (type) + { + case ProjectType::Target::Type::GUIApp: + case ProjectType::Target::Type::VSTPlugIn: + case ProjectType::Target::Type::VST3PlugIn: + case ProjectType::Target::Type::AudioUnitPlugIn: + case ProjectType::Target::Type::StandalonePlugIn: + case ProjectType::Target::Type::AudioUnitv3PlugIn: + case ProjectType::Target::Type::UnityPlugIn: + return "????"; + + case ProjectType::Target::Type::AAXPlugIn: + case ProjectType::Target::Type::RTASPlugIn: + return "PTul"; + + case ProjectType::Target::Type::ConsoleApp: + case ProjectType::Target::Type::StaticLibrary: + case ProjectType::Target::Type::DynamicLibrary: + case ProjectType::Target::Type::SharedCodeTarget: + case ProjectType::Target::Type::AggregateTarget: + case ProjectType::Target::Type::unspecified: + default: + return {}; + } + } + + static unsigned int calculateHash (const String& s, const unsigned int hashMultiplier) + { + auto t = s.toUTF8(); + unsigned int hash = 0; + + while (*t != 0) + hash = hashMultiplier * hash + (unsigned int) *t++; + + return hash; + } + + static unsigned int findBestHashMultiplier (const StringArray& strings) + { + unsigned int v = 31; + + for (;;) + { + SortedSet hashes; + bool collision = false; + + for (int i = strings.size(); --i >= 0;) + { + auto hash = calculateHash (strings[i], v); + + if (hashes.contains (hash)) + { + collision = true; + break; + } + + hashes.add (hash); + } + + if (! collision) + break; + + v += 2; + } + + return v; + } + + String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates, bool allowAsterisks) + { + if (s.isEmpty()) + return "unknown"; + + if (removeColons) + s = s.replaceCharacters (".,;:/@", "______"); + else + s = s.replaceCharacters (".,;/@", "_____"); + + for (int i = s.length(); --i > 0;) + if (CharacterFunctions::isLetter (s[i]) + && CharacterFunctions::isLetter (s[i - 1]) + && CharacterFunctions::isUpperCase (s[i]) + && ! CharacterFunctions::isUpperCase (s[i - 1])) + s = s.substring (0, i) + " " + s.substring (i); + + String allowedChars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789"); + if (allowTemplates) + allowedChars += "<>"; + + if (! removeColons) + allowedChars += ":"; + + if (allowAsterisks) + allowedChars += "*"; + + StringArray words; + words.addTokens (s.retainCharacters (allowedChars), false); + words.trim(); + + auto n = words[0]; + + if (capitalise) + n = n.toLowerCase(); + + for (int i = 1; i < words.size(); ++i) + { + if (capitalise && words[i].length() > 1) + n << words[i].substring (0, 1).toUpperCase() + << words[i].substring (1).toLowerCase(); + else + n << words[i]; + } + + if (CharacterFunctions::isDigit (n[0])) + n = "_" + n; + + if (isReservedKeyword (n)) + n << '_'; + + return n; + } + + String makeBinaryDataIdentifierName (const File& file) + { + return makeValidIdentifier (file.getFileName() + .replaceCharacters (" .", "__") + .retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"), + false, true, false); + } + + void writeDataAsCppLiteral (const MemoryBlock& mb, OutputStream& out, + bool breakAtNewLines, bool allowStringBreaks) + { + const int maxCharsOnLine = 250; + + auto data = (const unsigned char*) mb.getData(); + int charsOnLine = 0; + + bool canUseStringLiteral = mb.getSize() < 32768; // MS compilers can't handle big string literals.. + + if (canUseStringLiteral) + { + unsigned int numEscaped = 0; + + for (size_t i = 0; i < mb.getSize(); ++i) + { + auto num = (unsigned int) data[i]; + + if (! ((num >= 32 && num < 127) || num == '\t' || num == '\r' || num == '\n')) + { + if (++numEscaped > mb.getSize() / 4) + { + canUseStringLiteral = false; + break; + } + } + } + } + + if (! canUseStringLiteral) + { + out << "{ "; + + for (size_t i = 0; i < mb.getSize(); ++i) + { + auto num = (int) (unsigned int) data[i]; + out << num << ','; + + charsOnLine += 2; + + if (num >= 10) + { + ++charsOnLine; + + if (num >= 100) + ++charsOnLine; + } + + if (charsOnLine >= maxCharsOnLine) + { + charsOnLine = 0; + out << newLine; + } + } + + out << "0,0 };"; + } + else + { + out << "\""; + writeEscapeChars (out, (const char*) data, (int) mb.getSize(), + maxCharsOnLine, breakAtNewLines, false, allowStringBreaks); + out << "\";"; + } + } + + void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, + const StringArray& strings, const StringArray& codeToExecute, const int indentLevel) + { + jassert (strings.size() == codeToExecute.size()); + auto indent = String::repeatedString (" ", indentLevel); + auto hashMultiplier = findBestHashMultiplier (strings); + + out << indent << "unsigned int hash = 0;" << newLine + << newLine + << indent << "if (" << utf8PointerVariable << " != nullptr)" << newLine + << indent << " while (*" << utf8PointerVariable << " != 0)" << newLine + << indent << " hash = " << (int) hashMultiplier << " * hash + (unsigned int) *" << utf8PointerVariable << "++;" << newLine + << newLine + << indent << "switch (hash)" << newLine + << indent << "{" << newLine; + + for (int i = 0; i < strings.size(); ++i) + { + out << indent << " case 0x" << hexString8Digits ((int) calculateHash (strings[i], hashMultiplier)) + << ": " << codeToExecute[i] << newLine; + } + + out << indent << " default: break;" << newLine + << indent << "}" << newLine << newLine; + } + + String unixStylePath (const String& path) { return path.replaceCharacter ('\\', '/'); } + String windowsStylePath (const String& path) { return path.replaceCharacter ('/', '\\'); } + + String currentOSStylePath (const String& path) + { + #if JUCE_WINDOWS + return windowsStylePath (path); + #else + return unixStylePath (path); + #endif + } + + bool isAbsolutePath (const String& path) + { + return File::isAbsolutePath (path) + || path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows) + || path.startsWithChar ('$') + || path.startsWithChar ('~') + || (CharacterFunctions::isLetter (path[0]) && path[1] == ':') + || path.startsWithIgnoreCase ("smb:"); + } + + String getRelativePathFrom (const File& file, const File& sourceFolder) + { + #if ! JUCE_WINDOWS + // On a non-windows machine, we can't know if a drive-letter path may be relative or not. + if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':') + return file.getFullPathName(); + #endif + + return file.getRelativePathFrom (sourceFolder); + } + + void writeStreamToFile (const File& file, const std::function& writer) + { + MemoryOutputStream mo; + writer (mo); + overwriteFileIfDifferentOrThrow (file, mo); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.h b/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.h new file mode 100644 index 0000000000..795a9bab3a --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_BuildHelperFunctions.h @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData); + void overwriteFileIfDifferentOrThrow (const File& file, const String& newData); + + class SaveError + { + public: + SaveError (const String& error) : message (error) + {} + + SaveError (const File& fileThatFailedToWrite) + : message ("Can't write to the file: " + fileThatFailedToWrite.getFullPathName()) + {} + + String message; + }; + + String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString); + + String getXcodePackageType (ProjectType::Target::Type); + String getXcodeBundleSignature (ProjectType::Target::Type); + + inline String hexString8Digits (int value) + { + return String::toHexString (value).paddedLeft ('0', 8); + } + + String makeValidIdentifier (String s, + bool capitalise, + bool removeColons, + bool allowTemplates, + bool allowAsterisks = false); + + String makeBinaryDataIdentifierName (const File& file); + + void writeDataAsCppLiteral (const MemoryBlock& mb, + OutputStream& out, + bool breakAtNewLines, + bool allowStringBreaks); + + void createStringMatcher (OutputStream& out, + const String& utf8PointerVariable, + const StringArray& strings, + const StringArray& codeToExecute, + const int indentLevel); + + String unixStylePath (const String& path); + String windowsStylePath (const String& path); + String currentOSStylePath (const String& path); + + bool isAbsolutePath (const String& path); + + // A windows-aware version of File::getRelativePath() + String getRelativePathFrom (const File& file, const File& sourceFolder); + + void writeStreamToFile (const File& file, const std::function& writer); +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_CppTokeniserFunctions.cpp b/extras/Build/juce_build_tools/utils/juce_CppTokeniserFunctions.cpp new file mode 100644 index 0000000000..ef6e179e13 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_CppTokeniserFunctions.cpp @@ -0,0 +1,214 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + static bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept + { + static const char* const keywords2Char[] = + { "do", "if", "or", nullptr }; + + static const char* const keywords3Char[] = + { "and", "asm", "for", "int", "new", "not", "try", "xor", nullptr }; + + static const char* const keywords4Char[] = + { "auto", "bool", "case", "char", "else", "enum", "goto", + "long", "this", "true", "void", nullptr }; + + static const char* const keywords5Char[] = + { "bitor", "break", "catch", "class", "compl", "const", "false", "final", + "float", "or_eq", "short", "throw", "union", "using", "while", nullptr }; + + static const char* const keywords6Char[] = + { "and_eq", "bitand", "delete", "double", "export", "extern", "friend", + "import", "inline", "module", "not_eq", "public", "return", "signed", + "sizeof", "static", "struct", "switch", "typeid", "xor_eq", nullptr }; + + static const char* const keywords7Char[] = + { "__cdecl", "_Pragma", "alignas", "alignof", "concept", "default", + "mutable", "nullptr", "private", "typedef", "uint8_t", "virtual", + "wchar_t", nullptr }; + + static const char* const keywordsOther[] = + { "@class", "@dynamic", "@end", "@implementation", "@interface", "@public", + "@private", "@protected", "@property", "@synthesize", "__fastcall", "__stdcall", + "atomic_cancel", "atomic_commit", "atomic_noexcept", "char16_t", "char32_t", + "co_await", "co_return", "co_yield", "const_cast", "constexpr", "continue", + "decltype", "dynamic_cast", "explicit", "namespace", "noexcept", "operator", "override", + "protected", "register", "reinterpret_cast", "requires", "static_assert", + "static_cast", "synchronized", "template", "thread_local", "typename", "unsigned", + "volatile", nullptr }; + + const char* const* k; + + switch (tokenLength) + { + case 2: k = keywords2Char; break; + case 3: k = keywords3Char; break; + case 4: k = keywords4Char; break; + case 5: k = keywords5Char; break; + case 6: k = keywords6Char; break; + case 7: k = keywords7Char; break; + + default: + if (tokenLength < 2 || tokenLength > 16) + return false; + + k = keywordsOther; + break; + } + + for (int i = 0; k[i] != nullptr; ++i) + if (token.compare (CharPointer_ASCII (k[i])) == 0) + return true; + + return false; + } + + static bool isReservedKeyword (const String& token) noexcept + { + return isReservedKeyword (token.getCharPointer(), token.length()); + } + + //============================================================================== + /** Takes a UTF8 string and writes it to a stream using standard C++ escape sequences for any + non-ascii bytes. + + Although not strictly a tokenising function, this is still a function that often comes in + handy when working with C++ code! + + Note that addEscapeChars() is easier to use than this function if you're working with Strings. + + @see addEscapeChars + */ + static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytesToRead, + const int maxCharsOnLine, const bool breakAtNewLines, + const bool replaceSingleQuotes, const bool allowStringBreaks) + { + int charsOnLine = 0; + bool lastWasHexEscapeCode = false; + bool trigraphDetected = false; + + for (int i = 0; i < numBytesToRead || numBytesToRead < 0; ++i) + { + auto c = (unsigned char) utf8[i]; + bool startNewLine = false; + + switch (c) + { + + case '\t': out << "\\t"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break; + case '\r': out << "\\r"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break; + case '\n': out << "\\n"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break; + case '\\': out << "\\\\"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break; + case '\"': out << "\\\""; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break; + + case '?': + if (trigraphDetected) + { + out << "\\?"; + charsOnLine++; + trigraphDetected = false; + } + else + { + out << "?"; + trigraphDetected = true; + } + + lastWasHexEscapeCode = false; + charsOnLine++; + break; + + case 0: + if (numBytesToRead < 0) + return; + + out << "\\0"; + lastWasHexEscapeCode = true; + trigraphDetected = false; + charsOnLine += 2; + break; + + case '\'': + if (replaceSingleQuotes) + { + out << "\\\'"; + lastWasHexEscapeCode = false; + trigraphDetected = false; + charsOnLine += 2; + break; + } + + // deliberate fall-through... + + default: + if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit) + && CharacterFunctions::getHexDigitValue (c) >= 0)) + { + out << (char) c; + lastWasHexEscapeCode = false; + trigraphDetected = false; + ++charsOnLine; + } + else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127) + { + out << "\"\"" << (char) c; + lastWasHexEscapeCode = false; + trigraphDetected = false; + charsOnLine += 3; + } + else + { + out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c); + lastWasHexEscapeCode = true; + trigraphDetected = false; + charsOnLine += 4; + } + + break; + } + + if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine)) + && (numBytesToRead < 0 || i < numBytesToRead - 1)) + { + charsOnLine = 0; + out << "\"" << newLine << "\""; + lastWasHexEscapeCode = false; + } + } + } + + /** Takes a string and returns a version of it where standard C++ escape sequences have been + used to replace any non-ascii bytes. + + Although not strictly a tokenising function, this is still a function that often comes in + handy when working with C++ code! + + @see writeEscapeChars + */ + static String addEscapeChars (const String& s) + { + MemoryOutputStream mo; + writeEscapeChars (mo, s.toRawUTF8(), -1, -1, false, true, true); + return mo.toString(); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_Entitlements.cpp b/extras/Build/juce_build_tools/utils/juce_Entitlements.cpp new file mode 100644 index 0000000000..a239cc4b94 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_Entitlements.cpp @@ -0,0 +1,109 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + String EntitlementOptions::getEntitlementsFileContent() const + { + String content = + "\n" + "\n" + "\n" + "\n"; + + const auto entitlements = getEntitlements(); + + for (auto& key : entitlements.getAllKeys()) + content += "\t" + key + "\n\t" + entitlements[key] + "\n"; + + return content + "\n\n"; + } + + StringPairArray EntitlementOptions::getEntitlements() const + { + StringPairArray entitlements; + + if (isiOS) + { + if (isAudioPluginProject && shouldEnableIAA) + entitlements.set ("inter-app-audio", ""); + + if (isiCloudPermissionsEnabled) + { + entitlements.set ("com.apple.developer.icloud-container-identifiers", + "\n" + " iCloud.$(CFBundleIdentifier)\n" + " "); + + entitlements.set ("com.apple.developer.icloud-services", + "\n" + " CloudDocuments\n" + " "); + + entitlements.set ("com.apple.developer.ubiquity-container-identifiers", + "\n" + " iCloud.$(CFBundleIdentifier)\n" + " "); + } + } + + if (isPushNotificationsEnabled) + entitlements.set (isiOS ? "aps-environment" + : "com.apple.developer.aps-environment", + "development"); + + if (isAppGroupsEnabled) + { + auto appGroups = StringArray::fromTokens (appGroupIdString, ";", {}); + auto groups = String (""); + + for (auto group : appGroups) + groups += "\n\t\t" + group.trim() + ""; + + groups += "\n\t"; + + entitlements.set ("com.apple.security.application-groups", groups); + } + + if (isHardenedRuntimeEnabled) + for (auto& option : hardenedRuntimeOptions) + entitlements.set (option, ""); + + if (isAppSandboxEnabled || (! isiOS && isAudioPluginProject && type == ProjectType::Target::AudioUnitv3PlugIn)) + { + entitlements.set ("com.apple.security.app-sandbox", ""); + + if (isAppSandboxInhertianceEnabled) + { + // no other sandbox options can be specified if sandbox inheritance is enabled! + jassert (appSandboxOptions.isEmpty()); + + entitlements.set ("com.apple.security.inherit", ""); + } + + if (isAppSandboxEnabled) + for (auto& option : appSandboxOptions) + entitlements.set (option, ""); + } + + return entitlements; + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_Entitlements.h b/extras/Build/juce_build_tools/utils/juce_Entitlements.h new file mode 100644 index 0000000000..d910ec0fc8 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_Entitlements.h @@ -0,0 +1,48 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + struct EntitlementOptions final + { + String getEntitlementsFileContent() const; + + ProjectType::Target::Type type = ProjectType::Target::GUIApp; + + bool isiOS = false; + bool isAudioPluginProject = false; + bool shouldEnableIAA = false; + bool isiCloudPermissionsEnabled = false; + bool isPushNotificationsEnabled = false; + bool isAppGroupsEnabled = false; + bool isHardenedRuntimeEnabled = false; + bool isAppSandboxEnabled = false; + bool isAppSandboxInhertianceEnabled = false; + + String appGroupIdString; + + StringArray hardenedRuntimeOptions; + StringArray appSandboxOptions; + + private: + StringPairArray getEntitlements() const; + }; +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_Icons.cpp b/extras/Build/juce_build_tools/utils/juce_Icons.cpp new file mode 100644 index 0000000000..b8a678597b --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_Icons.cpp @@ -0,0 +1,497 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + Array asArray (const Icons& icons) + { + Array result; + + if (icons.small != nullptr) + result.add (icons.small.get()); + + if (icons.big != nullptr) + result.add (icons.big.get()); + + return result; + } + + namespace mac + { + static Image fixIconImageSize (Drawable& image) + { + const int validSizes[] = { 16, 32, 64, 128, 256, 512, 1024 }; + + auto w = image.getWidth(); + auto h = image.getHeight(); + + int bestSize = 16; + + for (int size : validSizes) + { + if (w == h && w == size) + { + bestSize = w; + break; + } + + if (jmax (w, h) > size) + bestSize = size; + } + + return rescaleImageForIcon (image, bestSize); + } + + static void writeIconData (MemoryOutputStream& out, const Image& image, const char* type) + { + MemoryOutputStream pngData; + PNGImageFormat pngFormat; + pngFormat.writeImageToStream (image, pngData); + + out.write (type, 4); + out.writeIntBigEndian (8 + (int) pngData.getDataSize()); + out << pngData; + } + } // namespace mac + + void writeMacIcon (const Icons& icons, OutputStream& out) + { + MemoryOutputStream data; + auto smallest = std::numeric_limits::max(); + Drawable* smallestImage = nullptr; + + const auto images = asArray (icons); + + for (int i = 0; i < images.size(); ++i) + { + auto image = mac::fixIconImageSize (*images[i]); + jassert (image.getWidth() == image.getHeight()); + + if (image.getWidth() < smallest) + { + smallest = image.getWidth(); + smallestImage = images[i]; + } + + switch (image.getWidth()) + { + case 16: mac::writeIconData (data, image, "icp4"); break; + case 32: mac::writeIconData (data, image, "icp5"); break; + case 64: mac::writeIconData (data, image, "icp6"); break; + case 128: mac::writeIconData (data, image, "ic07"); break; + case 256: mac::writeIconData (data, image, "ic08"); break; + case 512: mac::writeIconData (data, image, "ic09"); break; + case 1024: mac::writeIconData (data, image, "ic10"); break; + default: break; + } + } + + jassert (data.getDataSize() > 0); // no suitable sized images? + + // If you only supply a 1024 image, the file doesn't work on 10.8, so we need + // to force a smaller one in there too.. + if (smallest > 512 && smallestImage != nullptr) + mac::writeIconData (data, rescaleImageForIcon (*smallestImage, 512), "ic09"); + + out.write ("icns", 4); + out.writeIntBigEndian ((int) data.getDataSize() + 8); + out << data; + } + + Image getBestIconForSize (const Icons& icons, + int size, + bool returnNullIfNothingBigEnough) + { + auto* const im = [&]() -> Drawable* + { + if ((icons.small != nullptr) != (icons.big != nullptr)) + return icons.small != nullptr ? icons.small.get() : icons.big.get(); + + if (icons.small != nullptr && icons.big != nullptr) + { + if (icons.small->getWidth() >= size && icons.big->getWidth() >= size) + return icons.small->getWidth() < icons.big->getWidth() ? icons.small.get() : icons.big.get(); + + if (icons.small->getWidth() >= size) + return icons.small.get(); + + if (icons.big->getWidth() >= size) + return icons.big.get(); + } + + return nullptr; + }(); + + if (im == nullptr) + return {}; + + if (returnNullIfNothingBigEnough && im->getWidth() < size && im->getHeight() < size) + return {}; + + return rescaleImageForIcon (*im, size); + } + + namespace win + { + static void writeBMPImage (const Image& image, const int w, const int h, MemoryOutputStream& out) + { + int maskStride = (w / 8 + 3) & ~3; + + out.writeInt (40); // bitmapinfoheader size + out.writeInt (w); + out.writeInt (h * 2); + out.writeShort (1); // planes + out.writeShort (32); // bits + out.writeInt (0); // compression + out.writeInt ((h * w * 4) + (h * maskStride)); // size image + out.writeInt (0); // x pixels per meter + out.writeInt (0); // y pixels per meter + out.writeInt (0); // clr used + out.writeInt (0); // clr important + + Image::BitmapData bitmap (image, Image::BitmapData::readOnly); + int alphaThreshold = 5; + + int y; + for (y = h; --y >= 0;) + { + for (int x = 0; x < w; ++x) + { + auto pixel = bitmap.getPixelColour (x, y); + + if (pixel.getAlpha() <= alphaThreshold) + { + out.writeInt (0); + } + else + { + out.writeByte ((char) pixel.getBlue()); + out.writeByte ((char) pixel.getGreen()); + out.writeByte ((char) pixel.getRed()); + out.writeByte ((char) pixel.getAlpha()); + } + } + } + + for (y = h; --y >= 0;) + { + int mask = 0, count = 0; + + for (int x = 0; x < w; ++x) + { + auto pixel = bitmap.getPixelColour (x, y); + + mask <<= 1; + if (pixel.getAlpha() <= alphaThreshold) + mask |= 1; + + if (++count == 8) + { + out.writeByte ((char) mask); + count = 0; + mask = 0; + } + } + + if (mask != 0) + out.writeByte ((char) mask); + + for (int i = maskStride - w / 8; --i >= 0;) + out.writeByte (0); + } + } + + static void writeIcon (const Array& images, OutputStream& out) + { + out.writeShort (0); // reserved + out.writeShort (1); // .ico tag + out.writeShort ((short) images.size()); + + MemoryOutputStream dataBlock; + + int imageDirEntrySize = 16; + int dataBlockStart = 6 + images.size() * imageDirEntrySize; + + for (int i = 0; i < images.size(); ++i) + { + auto oldDataSize = dataBlock.getDataSize(); + + auto& image = images.getReference (i); + auto w = image.getWidth(); + auto h = image.getHeight(); + + if (w >= 256 || h >= 256) + { + PNGImageFormat pngFormat; + pngFormat.writeImageToStream (image, dataBlock); + } + else + { + writeBMPImage (image, w, h, dataBlock); + } + + out.writeByte ((char) w); + out.writeByte ((char) h); + out.writeByte (0); + out.writeByte (0); + out.writeShort (1); // colour planes + out.writeShort (32); // bits per pixel + out.writeInt ((int) (dataBlock.getDataSize() - oldDataSize)); + out.writeInt (dataBlockStart + (int) oldDataSize); + } + + jassert (out.getPosition() == dataBlockStart); + out << dataBlock; + } + } // namespace win + + void writeWinIcon (const Icons& icons, OutputStream& os) + { + Array images; + int sizes[] = { 16, 32, 48, 256 }; + + for (int size : sizes) + { + auto im = getBestIconForSize (icons, size, true); + + if (im.isValid()) + images.add (im); + } + + if (images.size() > 0) + win::writeIcon (images, os); + } + + void writeMacIcon (const Icons& icons, const File& file) + { + writeStreamToFile (file, [&] (juce::MemoryOutputStream& mo) { writeMacIcon (icons, mo); }); + } + + void writeWinIcon (const Icons& icons, const File& file) + { + writeStreamToFile (file, [&] (juce::MemoryOutputStream& mo) { writeWinIcon (icons, mo); }); + } + + Image rescaleImageForIcon (Drawable& d, const int size) + { + if (auto* drawableImage = dynamic_cast (&d)) + { + auto im = SoftwareImageType().convert (drawableImage->getImage()); + + if (im.getWidth() == size && im.getHeight() == size) + return im; + + // (scale it down in stages for better resampling) + while (im.getWidth() > 2 * size && im.getHeight() > 2 * size) + im = im.rescaled (im.getWidth() / 2, + im.getHeight() / 2); + + Image newIm (Image::ARGB, size, size, true, SoftwareImageType()); + Graphics g (newIm); + g.drawImageWithin (im, 0, 0, size, size, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); + return newIm; + } + + Image im (Image::ARGB, size, size, true, SoftwareImageType()); + Graphics g (im); + d.drawWithin (g, im.getBounds().toFloat(), RectanglePlacement::centred, 1.0f); + return im; + } + + struct AppIconType + { + const char* idiom; + const char* sizeString; + const char* filename; + const char* scale; + int size; + }; + + static const AppIconType iOSAppIconTypes[] + { + { "iphone", "20x20", "Icon-Notification-20@2x.png", "2x", 40 }, + { "iphone", "20x20", "Icon-Notification-20@3x.png", "3x", 60 }, + { "iphone", "29x29", "Icon-29.png", "1x", 29 }, + { "iphone", "29x29", "Icon-29@2x.png", "2x", 58 }, + { "iphone", "29x29", "Icon-29@3x.png", "3x", 87 }, + { "iphone", "40x40", "Icon-Spotlight-40@2x.png", "2x", 80 }, + { "iphone", "40x40", "Icon-Spotlight-40@3x.png", "3x", 120 }, + { "iphone", "57x57", "Icon.png", "1x", 57 }, + { "iphone", "57x57", "Icon@2x.png", "2x", 114 }, + { "iphone", "60x60", "Icon-60@2x.png", "2x", 120 }, + { "iphone", "60x60", "Icon-@3x.png", "3x", 180 }, + { "ipad", "20x20", "Icon-Notifications-20.png", "1x", 20 }, + { "ipad", "20x20", "Icon-Notifications-20@2x.png", "2x", 40 }, + { "ipad", "29x29", "Icon-Small-1.png", "1x", 29 }, + { "ipad", "29x29", "Icon-Small@2x-1.png", "2x", 58 }, + { "ipad", "40x40", "Icon-Spotlight-40.png", "1x", 40 }, + { "ipad", "40x40", "Icon-Spotlight-40@2x-1.png", "2x", 80 }, + { "ipad", "50x50", "Icon-Small-50.png", "1x", 50 }, + { "ipad", "50x50", "Icon-Small-50@2x.png", "2x", 100 }, + { "ipad", "72x72", "Icon-72.png", "1x", 72 }, + { "ipad", "72x72", "Icon-72@2x.png", "2x", 144 }, + { "ipad", "76x76", "Icon-76.png", "1x", 76 }, + { "ipad", "76x76", "Icon-76@2x.png", "2x", 152 }, + { "ipad", "83.5x83.5", "Icon-83.5@2x.png", "2x", 167 }, + { "ios-marketing", "1024x1024", "Icon-AppStore-1024.png", "1x", 1024 } + }; + + static void createiOSIconFiles (const Icons& icons, File appIconSet) + { + const auto images = asArray (icons); + + if (! images.isEmpty()) + { + for (auto& type : iOSAppIconTypes) + { + auto image = rescaleImageForIcon (*images.getFirst(), type.size); + + if (image.hasAlphaChannel()) + { + Image background (Image::RGB, image.getWidth(), image.getHeight(), false); + Graphics g (background); + g.fillAll (Colours::white); + + g.drawImageWithin (image, 0, 0, image.getWidth(), image.getHeight(), + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize); + + image = background; + } + + MemoryOutputStream pngData; + PNGImageFormat pngFormat; + pngFormat.writeImageToStream (image, pngData); + + overwriteFileIfDifferentOrThrow (appIconSet.getChildFile (type.filename), pngData); + } + } + } + + static String getiOSAssetContents (var images) + { + DynamicObject::Ptr v (new DynamicObject()); + + var info (new DynamicObject()); + info.getDynamicObject()->setProperty ("version", 1); + info.getDynamicObject()->setProperty ("author", "xcode"); + + v->setProperty ("images", images); + v->setProperty ("info", info); + + return JSON::toString (var (v.get())); + } + + //============================================================================== + static String getiOSAppIconContents() + { + var images; + + for (auto& type : iOSAppIconTypes) + { + DynamicObject::Ptr d (new DynamicObject()); + d->setProperty ("idiom", type.idiom); + d->setProperty ("size", type.sizeString); + d->setProperty ("filename", type.filename); + d->setProperty ("scale", type.scale); + images.append (var (d.get())); + } + + return getiOSAssetContents (images); + } + + struct ImageType + { + const char* orientation; + const char* idiom; + const char* subtype; + const char* extent; + const char* scale; + const char* filename; + int width; + int height; + }; + + static const ImageType iOSLaunchImageTypes[] + { + { "portrait", "iphone", nullptr, "full-screen", "2x", "LaunchImage-iphone-2x.png", 640, 960 }, + { "portrait", "iphone", "retina4", "full-screen", "2x", "LaunchImage-iphone-retina4.png", 640, 1136 }, + { "portrait", "ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-portrait-1x.png", 768, 1024 }, + { "landscape","ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-landscape-1x.png", 1024, 768 }, + { "portrait", "ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-portrait-2x.png", 1536, 2048 }, + { "landscape","ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-landscape-2x.png", 2048, 1536 } + }; + + static void createiOSLaunchImageFiles (const File& launchImageSet) + { + for (auto& type : iOSLaunchImageTypes) + { + Image image (Image::ARGB, type.width, type.height, true); // (empty black image) + image.clear (image.getBounds(), Colours::black); + + MemoryOutputStream pngData; + PNGImageFormat pngFormat; + pngFormat.writeImageToStream (image, pngData); + build_tools::overwriteFileIfDifferentOrThrow (launchImageSet.getChildFile (type.filename), pngData); + } + } + + static String getiOSLaunchImageContents() + { + var images; + + for (auto& type : iOSLaunchImageTypes) + { + DynamicObject::Ptr d (new DynamicObject()); + d->setProperty ("orientation", type.orientation); + d->setProperty ("idiom", type.idiom); + d->setProperty ("extent", type.extent); + d->setProperty ("minimum-system-version", "7.0"); + d->setProperty ("scale", type.scale); + d->setProperty ("filename", type.filename); + + if (type.subtype != nullptr) + d->setProperty ("subtype", type.subtype); + + images.append (var (d.get())); + } + + return getiOSAssetContents (images); + } + + RelativePath createXcassetsFolderFromIcons (const Icons& icons, + const File& targetFolder, + String projectFilenameRootString) + { + const auto assets = targetFolder.getChildFile (projectFilenameRootString) + .getChildFile ("Images.xcassets"); + const auto iconSet = assets.getChildFile ("AppIcon.appiconset"); + const auto launchImage = assets.getChildFile ("LaunchImage.launchimage"); + + overwriteFileIfDifferentOrThrow (iconSet.getChildFile ("Contents.json"), getiOSAppIconContents()); + createiOSIconFiles (icons, iconSet); + + overwriteFileIfDifferentOrThrow (launchImage.getChildFile ("Contents.json"), getiOSLaunchImageContents()); + createiOSLaunchImageFiles (launchImage); + + return { assets, targetFolder, RelativePath::buildTargetFolder }; + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_Icons.h b/extras/Build/juce_build_tools/utils/juce_Icons.h new file mode 100644 index 0000000000..ce174d79f0 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_Icons.h @@ -0,0 +1,42 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + struct Icons + { + std::unique_ptr small; + std::unique_ptr big; + }; + + Array asArray (const Icons&); + void writeMacIcon (const Icons&, const File&); + void writeWinIcon (const Icons&, const File&); + + Image getBestIconForSize (const Icons& icons, + int size, + bool returnNullIfNothingBigEnough); + Image rescaleImageForIcon (Drawable& d, const int size); + + RelativePath createXcassetsFolderFromIcons (const Icons& icons, + const File& targetFolder, + String projectFilenameRootString); +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_PlistOptions.cpp b/extras/Build/juce_build_tools/utils/juce_PlistOptions.cpp new file mode 100644 index 0000000000..a236111159 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_PlistOptions.cpp @@ -0,0 +1,354 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + //============================================================================== + static bool keyFoundAndNotSequentialDuplicate (XmlElement& xml, const String& key) + { + forEachXmlChildElementWithTagName (xml, element, "key") + { + if (element->getAllSubText().trim().equalsIgnoreCase (key)) + { + if (element->getNextElement() != nullptr && element->getNextElement()->hasTagName ("key")) + { + // found broken plist format (sequential duplicate), fix by removing + xml.removeChildElement (element, true); + return false; + } + + // key found (not sequential duplicate) + return true; + } + } + + // key not found + return false; + } + + static bool addKeyIfNotFound (XmlElement& xml, const String& key) + { + if (! keyFoundAndNotSequentialDuplicate (xml, key)) + { + xml.createNewChildElement ("key")->addTextElement (key); + return true; + } + + return false; + } + + static void addPlistDictionaryKey (XmlElement& xml, const String& key, const String& value) + { + if (addKeyIfNotFound (xml, key)) + xml.createNewChildElement ("string")->addTextElement (value); + } + + template + static void addPlistDictionaryKey (XmlElement& xml, const String& key, const char (&value) [N]) + { + addPlistDictionaryKey (xml, key, String { value }); + } + + static void addPlistDictionaryKey (XmlElement& xml, const String& key, const bool value) + { + if (addKeyIfNotFound (xml, key)) + xml.createNewChildElement (value ? "true" : "false"); + } + + static void addPlistDictionaryKey (XmlElement& xml, const String& key, int value) + { + if (addKeyIfNotFound (xml, key)) + xml.createNewChildElement ("integer")->addTextElement (String (value)); + } + + //============================================================================== + static void addArrayToPlist (XmlElement& dict, String arrayKey, const StringArray& arrayElements) + { + dict.createNewChildElement ("key")->addTextElement (arrayKey); + auto* plistStringArray = dict.createNewChildElement ("array"); + + for (auto& e : arrayElements) + plistStringArray->createNewChildElement ("string")->addTextElement (e); + } + + void PlistOptions::write (const File& infoPlistFile) const + { + writeStreamToFile (infoPlistFile, [&] (MemoryOutputStream& mo) { write (mo); }); + } + + void PlistOptions::write (MemoryOutputStream& mo) const + { + XmlElement::TextFormat format; + format.dtd = ""; + createXML()->writeTo (mo, format); + } + + std::unique_ptr PlistOptions::createXML() const + { + auto plist = parseXML (plistToMerge); + + if (plist == nullptr || ! plist->hasTagName ("plist")) + plist.reset (new XmlElement ("plist")); + + auto* dict = plist->getChildByName ("dict"); + + if (dict == nullptr) + dict = plist->createNewChildElement ("dict"); + + if (microphonePermissionEnabled) + addPlistDictionaryKey (*dict, "NSMicrophoneUsageDescription", microphonePermissionText); + + if (cameraPermissionEnabled) + addPlistDictionaryKey (*dict, "NSCameraUsageDescription", cameraPermissionText); + + if (iOS) + { + if (bluetoothPermissionEnabled) + { + addPlistDictionaryKey (*dict, "NSBluetoothAlwaysUsageDescription", bluetoothPermissionText); + addPlistDictionaryKey (*dict, "NSBluetoothPeripheralUsageDescription", bluetoothPermissionText); // needed for pre iOS 13.0 + } + + addPlistDictionaryKey (*dict, "LSRequiresIPhoneOS", true); + + if (type != ProjectType::Target::AudioUnitv3PlugIn) + addPlistDictionaryKey (*dict, "UIViewControllerBasedStatusBarAppearance", false); + + if (shouldAddStoryboardToProject) + addPlistDictionaryKey (*dict, "UILaunchStoryboardName", storyboardName); + } + else + { + if (sendAppleEventsPermissionEnabled) + addPlistDictionaryKey (*dict, "NSAppleEventsUsageDescription", sendAppleEventsPermissionText); + } + + addPlistDictionaryKey (*dict, "CFBundleExecutable", executableName); + + if (! iOS) // (NB: on iOS this causes error ITMS-90032 during publishing) + addPlistDictionaryKey (*dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String()); + + addPlistDictionaryKey (*dict, "CFBundleIdentifier", bundleIdentifier); + addPlistDictionaryKey (*dict, "CFBundleName", projectName); + + // needed by NSExtension on iOS + addPlistDictionaryKey (*dict, "CFBundleDisplayName", projectName); + addPlistDictionaryKey (*dict, "CFBundlePackageType", getXcodePackageType (type)); + addPlistDictionaryKey (*dict, "CFBundleSignature", getXcodeBundleSignature (type)); + addPlistDictionaryKey (*dict, "CFBundleShortVersionString", version); + addPlistDictionaryKey (*dict, "CFBundleVersion", version); + addPlistDictionaryKey (*dict, "NSHumanReadableCopyright", companyCopyright); + addPlistDictionaryKey (*dict, "NSHighResolutionCapable", true); + + auto replacedDocExtensions = StringArray::fromTokens (replacePreprocessorDefs (allPreprocessorDefs, + documentExtensions), ",", {}); + replacedDocExtensions.trim(); + replacedDocExtensions.removeEmptyStrings (true); + + if (! replacedDocExtensions.isEmpty() && type != ProjectType::Target::AudioUnitv3PlugIn) + { + dict->createNewChildElement ("key")->addTextElement ("CFBundleDocumentTypes"); + auto* dict2 = dict->createNewChildElement ("array")->createNewChildElement ("dict"); + XmlElement* arrayTag = nullptr; + + for (auto ex : replacedDocExtensions) + { + if (ex.startsWithChar ('.')) + ex = ex.substring (1); + + if (arrayTag == nullptr) + { + dict2->createNewChildElement ("key")->addTextElement ("CFBundleTypeExtensions"); + arrayTag = dict2->createNewChildElement ("array"); + + addPlistDictionaryKey (*dict2, "CFBundleTypeName", ex); + addPlistDictionaryKey (*dict2, "CFBundleTypeRole", "Editor"); + addPlistDictionaryKey (*dict2, "CFBundleTypeIconFile", "Icon"); + addPlistDictionaryKey (*dict2, "NSPersistentStoreTypeKey", "XML"); + } + + arrayTag->createNewChildElement ("string")->addTextElement (ex); + } + } + + if (fileSharingEnabled && type != ProjectType::Target::AudioUnitv3PlugIn) + addPlistDictionaryKey (*dict, "UIFileSharingEnabled", true); + + if (documentBrowserEnabled) + addPlistDictionaryKey (*dict, "UISupportsDocumentBrowser", true); + + if (statusBarHidden && type != ProjectType::Target::AudioUnitv3PlugIn) + addPlistDictionaryKey (*dict, "UIStatusBarHidden", true); + + if (iOS) + { + if (type != ProjectType::Target::AudioUnitv3PlugIn) + { + // Forcing full screen disables the split screen feature and prevents error ITMS-90475 + addPlistDictionaryKey (*dict, "UIRequiresFullScreen", true); + addPlistDictionaryKey (*dict, "UIStatusBarHidden", true); + + addIosScreenOrientations (*dict); + addIosBackgroundModes (*dict); + } + + if (type == ProjectType::Target::StandalonePlugIn && enableIAA) + { + XmlElement audioComponentsPlistKey ("key"); + audioComponentsPlistKey.addTextElement ("AudioComponents"); + + dict->addChildElement (new XmlElement (audioComponentsPlistKey)); + + XmlElement audioComponentsPlistEntry ("array"); + auto* audioComponentsDict = audioComponentsPlistEntry.createNewChildElement ("dict"); + + addPlistDictionaryKey (*audioComponentsDict, "name", IAAPluginName); + addPlistDictionaryKey (*audioComponentsDict, "manufacturer", pluginManufacturerCode.substring (0, 4)); + addPlistDictionaryKey (*audioComponentsDict, "type", IAATypeCode); + addPlistDictionaryKey (*audioComponentsDict, "subtype", pluginCode.substring (0, 4)); + addPlistDictionaryKey (*audioComponentsDict, "version", versionAsHex); + + dict->addChildElement (new XmlElement (audioComponentsPlistEntry)); + } + } + + const auto extraOptions = [&]() -> Array + { + if (type == ProjectType::Target::Type::AudioUnitPlugIn) + return createExtraAudioUnitTargetPlistOptions(); + + if (type == ProjectType::Target::Type::AudioUnitv3PlugIn) + return createExtraAudioUnitV3TargetPlistOptions(); + + return {}; + }(); + + for (auto& e : extraOptions) + dict->addChildElement (new XmlElement (e)); + + return plist; + } + + void PlistOptions::addIosScreenOrientations (XmlElement& dict) const + { + String screenOrientations[] = { iPhoneScreenOrientations, iPadScreenOrientations }; + String plistSuffix[] = { "", "~ipad" }; + auto orientationsAreTheSame = screenOrientations[0] == screenOrientations[1]; + + for (int i = 0; i < (orientationsAreTheSame ? 1 : 2); ++i) + { + StringArray iOSOrientations; + + if (screenOrientations[i].contains ("portrait")) { iOSOrientations.add ("UIInterfaceOrientationPortrait"); } + if (screenOrientations[i].contains ("landscape")) { iOSOrientations.add ("UIInterfaceOrientationLandscapeLeft"); iOSOrientations.add ("UIInterfaceOrientationLandscapeRight"); } + + addArrayToPlist (dict, String ("UISupportedInterfaceOrientations") + plistSuffix[i], iOSOrientations); + } + } + + void PlistOptions::addIosBackgroundModes (XmlElement& dict) const + { + StringArray iosBackgroundModes; + if (backgroundAudioEnabled) iosBackgroundModes.add ("audio"); + if (backgroundBleEnabled) iosBackgroundModes.add ("bluetooth-central"); + if (pushNotificationsEnabled) iosBackgroundModes.add ("remote-notification"); + + addArrayToPlist (dict, "UIBackgroundModes", iosBackgroundModes); + } + + Array PlistOptions::createExtraAudioUnitTargetPlistOptions() const + { + XmlElement plistKey ("key"); + plistKey.addTextElement ("AudioComponents"); + + XmlElement plistEntry ("array"); + auto* dict = plistEntry.createNewChildElement ("dict"); + + auto truncatedCode = pluginManufacturerCode.substring (0, 4); + auto pluginSubType = pluginCode.substring (0, 4); + + if (truncatedCode.toLowerCase() == truncatedCode) + { + throw SaveError ("AudioUnit plugin code identifiers invalid!\n\n" + "You have used only lower case letters in your AU plugin manufacturer identifier. " + "You must have at least one uppercase letter in your AU plugin manufacturer " + "identifier code."); + } + + addPlistDictionaryKey (*dict, "name", pluginManufacturer + ": " + pluginName); + addPlistDictionaryKey (*dict, "description", pluginDescription); + addPlistDictionaryKey (*dict, "factoryFunction", pluginAUExportPrefix + "Factory"); + addPlistDictionaryKey (*dict, "manufacturer", truncatedCode); + addPlistDictionaryKey (*dict, "type", auMainType.removeCharacters ("'")); + addPlistDictionaryKey (*dict, "subtype", pluginSubType); + addPlistDictionaryKey (*dict, "version", versionAsHex); + + if (isAuSandboxSafe) + { + addPlistDictionaryKey (*dict, "sandboxSafe", true); + } + else + { + dict->createNewChildElement ("key")->addTextElement ("resourceUsage"); + auto* resourceUsageDict = dict->createNewChildElement ("dict"); + + addPlistDictionaryKey (*resourceUsageDict, "network.client", true); + addPlistDictionaryKey (*resourceUsageDict, "temporary-exception.files.all.read-write", true); + } + + return { plistKey, plistEntry }; + } + + Array PlistOptions::createExtraAudioUnitV3TargetPlistOptions() const + { + XmlElement plistKey ("key"); + plistKey.addTextElement ("NSExtension"); + + XmlElement plistEntry ("dict"); + + addPlistDictionaryKey (plistEntry, "NSExtensionPrincipalClass", pluginAUExportPrefix + "FactoryAUv3"); + addPlistDictionaryKey (plistEntry, "NSExtensionPointIdentifier", "com.apple.AudioUnit-UI"); + plistEntry.createNewChildElement ("key")->addTextElement ("NSExtensionAttributes"); + + auto* dict = plistEntry.createNewChildElement ("dict"); + dict->createNewChildElement ("key")->addTextElement ("AudioComponents"); + auto* componentArray = dict->createNewChildElement ("array"); + + auto* componentDict = componentArray->createNewChildElement ("dict"); + + addPlistDictionaryKey (*componentDict, "name", pluginManufacturer + ": " + pluginName); + addPlistDictionaryKey (*componentDict, "description", pluginDescription); + addPlistDictionaryKey (*componentDict, "factoryFunction", pluginAUExportPrefix + "FactoryAUv3"); + addPlistDictionaryKey (*componentDict, "manufacturer", pluginManufacturerCode.substring (0, 4)); + addPlistDictionaryKey (*componentDict, "type", auMainType.removeCharacters ("'")); + addPlistDictionaryKey (*componentDict, "subtype", pluginCode.substring (0, 4)); + addPlistDictionaryKey (*componentDict, "version", versionAsHex); + addPlistDictionaryKey (*componentDict, "sandboxSafe", true); + + componentDict->createNewChildElement ("key")->addTextElement ("tags"); + auto* tagsArray = componentDict->createNewChildElement ("array"); + + tagsArray->createNewChildElement ("string") + ->addTextElement (isPluginSynth ? "Synth" : "Effects"); + + return { plistKey, plistEntry }; + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_PlistOptions.h b/extras/Build/juce_build_tools/utils/juce_PlistOptions.h new file mode 100644 index 0000000000..2a840270ce --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_PlistOptions.h @@ -0,0 +1,95 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + class PlistOptions final + { + public: + void write (const File& infoPlistFile) const; + + //============================================================================== + ProjectType::Target::Type type = ProjectType::Target::Type::GUIApp; + + String executableName; + String bundleIdentifier; + + String plistToMerge; + + bool iOS = false; + + bool microphonePermissionEnabled = false; + String microphonePermissionText; + + bool cameraPermissionEnabled = false; + String cameraPermissionText; + + bool bluetoothPermissionEnabled = false; + String bluetoothPermissionText; + + bool sendAppleEventsPermissionEnabled = false; + String sendAppleEventsPermissionText; + + bool shouldAddStoryboardToProject = false; + String storyboardName; + + File iconFile; + String projectName; + String version; + String companyCopyright; + + StringPairArray allPreprocessorDefs; + String documentExtensions; + + bool fileSharingEnabled = false; + bool documentBrowserEnabled = false; + bool statusBarHidden = false; + bool backgroundAudioEnabled = false; + bool backgroundBleEnabled = false; + bool pushNotificationsEnabled = false; + + bool enableIAA = false; + String IAAPluginName; + String pluginManufacturerCode; + String IAATypeCode; + String pluginCode; + int versionAsHex = 0; + + String iPhoneScreenOrientations; + String iPadScreenOrientations; + + String pluginName; + String pluginManufacturer; + String pluginDescription; + String pluginAUExportPrefix; + String auMainType; + bool isAuSandboxSafe = false; + bool isPluginSynth = false; + + private: + void write (MemoryOutputStream&) const; + std::unique_ptr createXML() const; + void addIosScreenOrientations (XmlElement&) const; + void addIosBackgroundModes (XmlElement&) const; + Array createExtraAudioUnitTargetPlistOptions() const; + Array createExtraAudioUnitV3TargetPlistOptions() const; + }; +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_ProjectType.h b/extras/Build/juce_build_tools/utils/juce_ProjectType.h new file mode 100644 index 0000000000..85288128ca --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_ProjectType.h @@ -0,0 +1,268 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + //============================================================================== + class ProjectType + { + public: + //============================================================================== + virtual ~ProjectType() { getAllTypes().removeFirstMatchingValue (this); } + + const String& getType() const noexcept { return type; } + const String& getDescription() const noexcept { return desc; } + + //============================================================================== + static Array getAllTypes(); + static const ProjectType* findType (const String& typeCode) + { + const auto& types = getAllTypes(); + + for (auto i = types.size(); --i >= 0;) + if (types.getUnchecked(i)->getType() == typeCode) + return types.getUnchecked(i); + + jassertfalse; + return nullptr; + } + + //============================================================================== + virtual bool isStaticLibrary() const { return false; } + virtual bool isDynamicLibrary() const { return false; } + virtual bool isGUIApplication() const { return false; } + virtual bool isCommandLineApp() const { return false; } + virtual bool isAudioPlugin() const { return false; } + + //============================================================================== + struct Target + { + enum Type + { + GUIApp = 0, + ConsoleApp = 1, + StaticLibrary = 2, + DynamicLibrary = 3, + + VSTPlugIn = 10, + VST3PlugIn = 11, + AAXPlugIn = 12, + RTASPlugIn = 13, + AudioUnitPlugIn = 14, + AudioUnitv3PlugIn = 15, + StandalonePlugIn = 16, + UnityPlugIn = 17, + + SharedCodeTarget = 20, // internal + AggregateTarget = 21, + + unspecified = 30 + }; + + enum TargetFileType + { + executable = 0, + staticLibrary = 1, + sharedLibraryOrDLL = 2, + pluginBundle = 3, + macOSAppex = 4, + unknown = 5 + }; + + //============================================================================== + explicit Target (Type targetType) : type (targetType) {} + + const char* getName() const noexcept + { + switch (type) + { + case GUIApp: return "App"; + case ConsoleApp: return "ConsoleApp"; + case StaticLibrary: return "Static Library"; + case DynamicLibrary: return "Dynamic Library"; + case VSTPlugIn: return "VST"; + case VST3PlugIn: return "VST3"; + case AudioUnitPlugIn: return "AU"; + case StandalonePlugIn: return "Standalone Plugin"; + case AudioUnitv3PlugIn: return "AUv3 AppExtension"; + case AAXPlugIn: return "AAX"; + case RTASPlugIn: return "RTAS"; + case UnityPlugIn: return "Unity Plugin"; + case SharedCodeTarget: return "Shared Code"; + case AggregateTarget: return "All"; + case unspecified: + default: break; + } + + return "undefined"; + } + + static Type typeFromName (const juce::String& name) + { + if (name == "App") return Type::GUIApp; + if (name == "ConsoleApp") return Type::ConsoleApp; + if (name == "Static Library") return Type::StaticLibrary; + if (name == "Dynamic Library") return Type::DynamicLibrary; + if (name == "VST") return Type::VSTPlugIn; + if (name == "VST3") return Type::VST3PlugIn; + if (name == "AU") return Type::AudioUnitPlugIn; + if (name == "Standalone Plugin") return Type::StandalonePlugIn; + if (name == "AUv3 AppExtension") return Type::AudioUnitv3PlugIn; + if (name == "AAX") return Type::AAXPlugIn; + if (name == "RTAS") return Type::RTASPlugIn; + if (name == "Unity Plugin") return Type::UnityPlugIn; + if (name == "Shared Code") return Type::SharedCodeTarget; + if (name == "All") return Type::AggregateTarget; + + jassertfalse; + return Type::ConsoleApp; + } + + TargetFileType getTargetFileType() const noexcept + { + switch (type) + { + case GUIApp: return executable; + case ConsoleApp: return executable; + case StaticLibrary: return staticLibrary; + case DynamicLibrary: return sharedLibraryOrDLL; + case VSTPlugIn: return pluginBundle; + case VST3PlugIn: return pluginBundle; + case AudioUnitPlugIn: return pluginBundle; + case StandalonePlugIn: return executable; + case AudioUnitv3PlugIn: return macOSAppex; + case AAXPlugIn: return pluginBundle; + case RTASPlugIn: return pluginBundle; + case UnityPlugIn: return pluginBundle; + case SharedCodeTarget: return staticLibrary; + case AggregateTarget: + case unspecified: + default: break; + } + + return unknown; + } + + const Type type; + + private: + //============================================================================== + Target& operator= (const Target&) = delete; + }; + + virtual bool supportsTargetType (Target::Type /*targetType*/) const { return false; } + + protected: + ProjectType (const String& t, const String& d) + : type (t), desc (d) + {} + + private: + const String type, desc; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectType) + }; + + //============================================================================== + struct ProjectType_GUIApp : public ProjectType + { + ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {} + + static const char* getTypeName() noexcept { return "guiapp"; } + bool isGUIApplication() const override { return true; } + bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::GUIApp); } + }; + + struct ProjectType_ConsoleApp : public ProjectType + { + ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {} + + static const char* getTypeName() noexcept { return "consoleapp"; } + bool isCommandLineApp() const override { return true; } + bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::ConsoleApp); } + }; + + struct ProjectType_StaticLibrary : public ProjectType + { + ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {} + + static const char* getTypeName() noexcept { return "library"; } + bool isStaticLibrary() const override { return true; } + bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::StaticLibrary); } + }; + + struct ProjectType_DLL : public ProjectType + { + ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {} + + static const char* getTypeName() noexcept { return "dll"; } + bool isDynamicLibrary() const override { return true; } + bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::DynamicLibrary); } + }; + + struct ProjectType_AudioPlugin : public ProjectType + { + ProjectType_AudioPlugin() : ProjectType (getTypeName(), "Audio Plug-in") {} + + static const char* getTypeName() noexcept { return "audioplug"; } + bool isAudioPlugin() const override { return true; } + + bool supportsTargetType (Target::Type targetType) const override + { + switch (targetType) + { + case Target::VSTPlugIn: + case Target::VST3PlugIn: + case Target::AAXPlugIn: + case Target::RTASPlugIn: + case Target::AudioUnitPlugIn: + case Target::AudioUnitv3PlugIn: + case Target::StandalonePlugIn: + case Target::UnityPlugIn: + case Target::SharedCodeTarget: + case Target::AggregateTarget: + return true; + + case Target::GUIApp: + case Target::ConsoleApp: + case Target::StaticLibrary: + case Target::DynamicLibrary: + case Target::unspecified: + default: + break; + } + + return false; + } + }; + + //============================================================================== + inline Array ProjectType::getAllTypes() + { + static ProjectType_GUIApp guiApp; + static ProjectType_ConsoleApp consoleApp; + static ProjectType_StaticLibrary staticLib; + static ProjectType_DLL dll; + static ProjectType_AudioPlugin plugin; + + return Array(&guiApp, &consoleApp, &staticLib, &dll, &plugin); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_RelativePath.h b/extras/Build/juce_build_tools/utils/juce_RelativePath.h new file mode 100644 index 0000000000..e5946f03d3 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_RelativePath.h @@ -0,0 +1,122 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + //============================================================================== + /** Manipulates a cross-platform partial file path. (Needed because File is designed + for absolute paths on the active OS) + */ + class RelativePath + { + public: + //============================================================================== + enum RootFolder + { + unknown, + projectFolder, + buildTargetFolder + }; + + //============================================================================== + RelativePath() + : root (unknown) + {} + + RelativePath (const String& relPath, const RootFolder rootType) + : path (unixStylePath (relPath)), root (rootType) + {} + + RelativePath (const File& file, const File& rootFolder, const RootFolder rootType) + : path (unixStylePath (getRelativePathFrom (file, rootFolder))), root (rootType) + {} + + RootFolder getRoot() const { return root; } + + String toUnixStyle() const { return unixStylePath (path); } + String toWindowsStyle() const { return windowsStylePath (path); } + + String getFileName() const { return getFakeFile().getFileName(); } + String getFileNameWithoutExtension() const { return getFakeFile().getFileNameWithoutExtension(); } + + String getFileExtension() const { return getFakeFile().getFileExtension(); } + bool hasFileExtension (juce::StringRef extension) const { return getFakeFile().hasFileExtension (extension); } + bool isAbsolute() const { return isAbsolutePath (path); } + + RelativePath withFileExtension (const String& extension) const + { + return RelativePath (path.upToLastOccurrenceOf (".", ! extension.startsWithChar ('.'), false) + extension, root); + } + + RelativePath getParentDirectory() const + { + String p (path); + if (path.endsWithChar ('/')) + p = p.dropLastCharacters (1); + + return RelativePath (p.upToLastOccurrenceOf ("/", false, false), root); + } + + RelativePath getChildFile (const String& subpath) const + { + if (isAbsolutePath (subpath)) + return RelativePath (subpath, root); + + String p (toUnixStyle()); + if (! p.endsWithChar ('/')) + p << '/'; + + return RelativePath (p + subpath, root); + } + + RelativePath rebased (const File& originalRoot, const File& newRoot, const RootFolder newRootType) const + { + if (isAbsolute()) + return RelativePath (path, newRootType); + + return RelativePath (getRelativePathFrom (originalRoot.getChildFile (toUnixStyle()), newRoot), newRootType); + } + + private: + //============================================================================== + String path; + RootFolder root; + + File getFakeFile() const + { + #if JUCE_WINDOWS + if (isAbsolutePath (path)) + { + // This is a hack to convert unix-style absolute paths into valid absolute Windows paths to avoid hitting + // an assertion in File::parseAbsolutePath(). + if (path.startsWithChar (L'/') || path.startsWithChar (L'$') || path.startsWithChar (L'~')) + return File (String ("C:\\") + windowsStylePath (path.substring (1))); + + return File (path); + } + #endif + + // This method gets called very often, so we'll cache this directory. + static const File currentWorkingDirectory (File::getCurrentWorkingDirectory()); + return currentWorkingDirectory.getChildFile (path); + } + }; +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.cpp b/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.cpp new file mode 100644 index 0000000000..3e30a218f5 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + uint64 calculateStreamHashCode (InputStream& in) + { + uint64 t = 0; + + const int bufferSize = 4096; + HeapBlock buffer; + buffer.malloc (bufferSize); + + for (;;) + { + auto num = in.read (buffer, bufferSize); + + if (num <= 0) + break; + + for (int i = 0; i < num; ++i) + t = t * 65599 + buffer[i]; + } + + return t; + } + + uint64 calculateFileHashCode (const File& file) + { + std::unique_ptr stream (file.createInputStream()); + return stream != nullptr ? calculateStreamHashCode (*stream) : 0; + } + + uint64 calculateMemoryHashCode (const void* data, size_t numBytes) + { + uint64 t = 0; + + for (size_t i = 0; i < numBytes; ++i) + t = t * 65599 + static_cast (data)[i]; + + return t; + } + + bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes) + { + if (file.getSize() == (int64) numBytes + && calculateMemoryHashCode (data, numBytes) == calculateFileHashCode (file)) + return true; + + if (file.exists()) + return file.replaceWithData (data, numBytes); + + return file.getParentDirectory().createDirectory() && file.appendData (data, numBytes); + } + + bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData) + { + return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize()); + } + + bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData) + { + const char* const utf8 = newData.toUTF8(); + return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8)); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.h b/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.h new file mode 100644 index 0000000000..2fd57a20d8 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_ResourceFileHelpers.h @@ -0,0 +1,31 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + uint64 calculateStreamHashCode (InputStream& in); + uint64 calculateFileHashCode (const File& file); + uint64 calculateMemoryHashCode (const void* data, size_t numBytes); + + bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes); + bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData); + bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData); +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_ResourceRc.cpp b/extras/Build/juce_build_tools/utils/juce_ResourceRc.cpp new file mode 100644 index 0000000000..80015d5dbe --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_ResourceRc.cpp @@ -0,0 +1,88 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + static void writeRCValue (MemoryOutputStream& mo, const String& n, const String& value) + { + if (value.isNotEmpty()) + mo << " VALUE \"" << n << "\", \"" + << addEscapeChars (value) << "\\0\"" << newLine; + } + + static String getCommaSeparatedVersionNumber (const String& version) + { + auto versionParts = StringArray::fromTokens (version, ",.", ""); + versionParts.trim(); + versionParts.removeEmptyStrings(); + while (versionParts.size() < 4) + versionParts.add ("0"); + + return versionParts.joinIntoString (","); + } + + void ResourceRcOptions::write (const File& resourceRcFile) const + { + MemoryOutputStream mo; + + mo << "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine + << " #include JUCE_USER_DEFINED_RC_FILE" << newLine + << "#else" << newLine + << newLine + << "#undef WIN32_LEAN_AND_MEAN" << newLine + << "#define WIN32_LEAN_AND_MEAN" << newLine + << "#include " << newLine + << newLine + << "VS_VERSION_INFO VERSIONINFO" << newLine + << "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine + << "BEGIN" << newLine + << " BLOCK \"StringFileInfo\"" << newLine + << " BEGIN" << newLine + << " BLOCK \"040904E4\"" << newLine + << " BEGIN" << newLine; + + writeRCValue (mo, "CompanyName", companyName); + writeRCValue (mo, "LegalCopyright", companyCopyright); + writeRCValue (mo, "FileDescription", projectName); + writeRCValue (mo, "FileVersion", version); + writeRCValue (mo, "ProductName", projectName); + writeRCValue (mo, "ProductVersion", version); + + mo << " END" << newLine + << " END" << newLine + << newLine + << " BLOCK \"VarFileInfo\"" << newLine + << " BEGIN" << newLine + << " VALUE \"Translation\", 0x409, 1252" << newLine + << " END" << newLine + << "END" << newLine + << newLine + << "#endif" << newLine; + + if (icon.existsAsFile()) + mo << newLine + << "IDI_ICON1 ICON DISCARDABLE " << icon.getFileName().quoted() + << newLine + << "IDI_ICON2 ICON DISCARDABLE " << icon.getFileName().quoted(); + + overwriteFileIfDifferentOrThrow (resourceRcFile, mo); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_ResourceRc.h b/extras/Build/juce_build_tools/utils/juce_ResourceRc.h new file mode 100644 index 0000000000..4a44131a90 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_ResourceRc.h @@ -0,0 +1,36 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + class ResourceRcOptions final + { + public: + void write (const File& resourceRcFile) const; + + //============================================================================== + String version; + String companyName; + String companyCopyright; + String projectName; + File icon; + }; +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_VersionNumbers.cpp b/extras/Build/juce_build_tools/utils/juce_VersionNumbers.cpp new file mode 100644 index 0000000000..05f1ab037b --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_VersionNumbers.cpp @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + StringArray getVersionSegments (juce::StringRef p) + { + auto segments = StringArray::fromTokens (p, ",.", ""); + segments.trim(); + segments.removeEmptyStrings(); + return segments; + } + + int getVersionAsHexInteger (juce::StringRef versionString) + { + auto segments = getVersionSegments (versionString); + + auto value = (segments[0].getIntValue() << 16) + + (segments[1].getIntValue() << 8) + + segments[2].getIntValue(); + + if (segments.size() > 3) + value = (value << 8) + segments[3].getIntValue(); + + return value; + } + + String getVersionAsHex (juce::StringRef versionString) + { + return "0x" + String::toHexString (getVersionAsHexInteger (versionString)); + } +} +} diff --git a/extras/Build/juce_build_tools/utils/juce_VersionNumbers.h b/extras/Build/juce_build_tools/utils/juce_VersionNumbers.h new file mode 100644 index 0000000000..5baf0bb212 --- /dev/null +++ b/extras/Build/juce_build_tools/utils/juce_VersionNumbers.h @@ -0,0 +1,29 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ +namespace build_tools +{ + StringArray getVersionSegments (juce::StringRef p); + + int getVersionAsHexInteger (juce::StringRef versionString); + + String getVersionAsHex (juce::StringRef versionString); +} +} diff --git a/extras/Build/juceaide/CMakeLists.txt b/extras/Build/juceaide/CMakeLists.txt new file mode 100644 index 0000000000..bcb648fa0a --- /dev/null +++ b/extras/Build/juceaide/CMakeLists.txt @@ -0,0 +1,90 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +# The juceaide program generates intermediate build files including BinaryData sources, icons, and +# plists. To ensure that we always build it for the host system, and not for, say, a device or +# simulator if we're targeting iOS or Android, we reinvoke cmake here and build juceaide during the +# configuration stage of the outer project. + +if(JUCE_BUILD_HELPER_TOOLS) + # Build the tool for the current system + juce_add_console_app(juceaide) + + target_sources(juceaide PRIVATE Main.cpp) + + target_compile_definitions(juceaide PRIVATE + JUCE_DISABLE_JUCE_VERSION_PRINTING=1 + JUCE_USE_CURL=0) + + target_link_libraries(juceaide PRIVATE juce::juce_build_tools) + + export(TARGETS juceaide + NAMESPACE juce_tools:: + FILE "${JUCE_BINARY_DIR}/JUCEToolsExport.cmake") +else() + # If we're building using the NDK, the gradle wrapper will try to inject its own compiler using + # environment variables, which is unfortunate because we really don't want to cross-compile + # juceaide. If you really want to set the compilers for juceaide, pass the appropriate + # CMAKE__COMPILER flags when configuring CMake. + unset(ENV{ASM}) + unset(ENV{CC}) + unset(ENV{CXX}) + + # Looks like we're boostrapping, reinvoke CMake + execute_process(COMMAND "${CMAKE_COMMAND}" + "-B${JUCE_BINARY_DIR}/tools" + "-G${CMAKE_GENERATOR}" + "-DCMAKE_BUILD_TYPE=Debug" + "-DJUCE_BUILD_HELPER_TOOLS=ON" + "-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}" + WORKING_DIRECTORY "${JUCE_SOURCE_DIR}" + OUTPUT_VARIABLE command_output + ERROR_VARIABLE command_output + RESULT_VARIABLE result_variable) + + if(result_variable) + message(FATAL_ERROR "Failed to configure tools\n${command_output}") + endif() + + execute_process(COMMAND "${CMAKE_COMMAND}" + --build "${JUCE_BINARY_DIR}/tools" + --config Debug + OUTPUT_VARIABLE command_output + ERROR_VARIABLE command_output + RESULT_VARIABLE result_variable) + + if(result_variable) + message(FATAL_ERROR "Failed to build tools\n${command_output}") + endif() + + # This will be generated by the recursive invocation of CMake (above) + include("${JUCE_BINARY_DIR}/tools/JUCEToolsExport.cmake") + + add_executable(juceaide IMPORTED GLOBAL) + get_target_property(imported_location juce_tools::juceaide IMPORTED_LOCATION_DEBUG) + set_target_properties(juceaide PROPERTIES IMPORTED_LOCATION "${imported_location}") + + add_executable(juce::juceaide ALIAS juceaide) + + set(JUCE_TOOL_INSTALL_DIR "bin" CACHE STRING + "The location, relative to the install prefix, where juceaide will be installed") + + install(PROGRAMS "${imported_location}" DESTINATION "${JUCE_TOOL_INSTALL_DIR}") + + get_filename_component(binary_name "${imported_location}" NAME) + set(JUCE_CMAKE_BINARY_BUILDER_NAME "${JUCE_TOOL_INSTALL_DIR}/${binary_name}" + CACHE INTERNAL "The name of the juceaide program") +endif() diff --git a/extras/Build/juceaide/Main.cpp b/extras/Build/juceaide/Main.cpp new file mode 100644 index 0000000000..5d6570443c --- /dev/null +++ b/extras/Build/juceaide/Main.cpp @@ -0,0 +1,507 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2020 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +#include + +#include +#include + +namespace +{ + +constexpr auto headerTemplate = R"(/* + IMPORTANT! This file is auto-generated. + If you alter its contents, your changes may be overwritten! + + This is the header file that your files should include in order to get all the + JUCE library headers. You should avoid including the JUCE headers directly in + your own source files, because that wouldn't pick up the correct configuration + options for your app. + +*/ + +#pragma once + +${JUCE_INCLUDES} + +#if JUCE_TARGET_HAS_BINARY_DATA +#include "BinaryData.h" +#endif + +#if ! DONT_SET_USING_JUCE_NAMESPACE + // If your code uses a lot of JUCE classes, then this will obviously save you + // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. + using namespace juce; +#endif + +#if ! JUCE_DONT_DECLARE_PROJECTINFO +namespace ProjectInfo +{ + const char* const projectName = "${JUCE_EXECUTABLE_NAME}"; + const char* const companyName = "${JUCE_COMPANY_NAME}"; + const char* const versionString = "${JUCE_PROJECT_VERSION}"; + const int versionNumber = ${JUCE_PROJECT_VERSION_HEX}; +} +#endif +)"; + +juce::String getValueOr (juce::ArgumentList& args, juce::String option, juce::String fallback) +{ + const auto opt = args.removeValueForOption (option); + return opt.isNotEmpty() ? opt : fallback; +} + +int writeBinaryData (juce::ArgumentList&& argumentList) +{ + juce::build_tools::ResourceFile resourceFile; + + resourceFile.setClassName (getValueOr (argumentList, "--namespace", "BinaryData")); + const auto lineEndings = argumentList.removeOptionIfFound ("--windows") ? "\r\n" : "\n"; + + if (argumentList.arguments.isEmpty()) + juce::ConsoleApplication::fail ("No destination folder specified for binary data files", 1); + + const auto outFolder = argumentList.arguments.removeAndReturn (0).resolveAsExistingFolder(); + + for (const auto& arg : argumentList.arguments) + resourceFile.addFile (arg.resolveAsExistingFile()); + + const auto result = resourceFile.write (0, + lineEndings, + outFolder.getChildFile ("./BinaryData.h"), + [&outFolder] (int index) + { + return outFolder.getChildFile ("./BinaryData" + juce::String { index + 1 } + ".cpp"); + }); + + if (result.result.failed()) + juce::ConsoleApplication::fail (result.result.getErrorMessage(), 1); + + return 0; +} + +struct IconParseResults final +{ + juce::build_tools::Icons icons; + juce::File output; +}; + +IconParseResults parseIconArguments (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (2); + const auto output = args.arguments.removeAndReturn (0); + + const auto popDrawable = [&args]() -> std::unique_ptr + { + if (args.size() == 0) + return {}; + + const auto firstArgText = args.arguments.removeAndReturn (0).text; + return juce::Drawable::createFromImageFile (firstArgText); + }; + + auto smallIcon = popDrawable(); + auto bigIcon = popDrawable(); + + return { { std::move (smallIcon), std::move (bigIcon) }, output.text }; +} + +int writeMacIcon (juce::ArgumentList&& argumentList) +{ + const auto parsed = parseIconArguments (std::move (argumentList)); + juce::build_tools::writeMacIcon (parsed.icons, parsed.output); + return 0; +} + +int writeiOSAssets (juce::ArgumentList&& argumentList) +{ + const auto parsed = parseIconArguments (std::move (argumentList)); + juce::build_tools::createXcassetsFolderFromIcons (parsed.icons, + parsed.output.getParentDirectory(), + parsed.output.getFileName()); + return 0; +} + +int writeWinIcon (juce::ArgumentList&& argumentList) +{ + const auto parsed = parseIconArguments (std::move (argumentList)); + juce::build_tools::writeWinIcon (parsed.icons, parsed.output); + return 0; +} + +std::unordered_map parseProjectData (const juce::File& file) +{ + constexpr auto recordSeparator = "\x1e"; + const auto contents = file.loadFileAsString(); + const auto lines = juce::StringArray::fromTokens (contents, recordSeparator, {}); + + std::unordered_map result; + + constexpr auto unitSeparator = "\x1f"; + + for (const auto& line : lines) + { + if (line.isEmpty()) + continue; + + result.emplace (line.upToFirstOccurrenceOf (unitSeparator, false, false), + line.fromFirstOccurrenceOf (unitSeparator, false, false)); + } + + return result; +} + +juce::String getStringValue (const std::unordered_map& dict, + juce::StringRef key) +{ + const auto it = dict.find (key); + return it != dict.cend() ? it->second : juce::String{}; +} + +bool getBoolValue (const std::unordered_map& dict, juce::StringRef key) +{ + const auto str = getStringValue (dict, key); + return str.equalsIgnoreCase ("yes") + || str.equalsIgnoreCase ("true") + || str.equalsIgnoreCase ("1") + || str.equalsIgnoreCase ("on"); +} + +struct UpdateField final +{ + const std::unordered_map& dict; + + void operator() (juce::StringRef key, juce::String& value) const + { + value = getStringValue (dict, key); + } + + void operator() (juce::StringRef key, juce::File& value) const + { + value = getStringValue (dict, key); + } + + void operator() (juce::StringRef key, bool& value) const + { + value = getBoolValue (dict, key); + } + + void operator() (juce::StringRef key, juce::StringArray& value) const + { + value = juce::StringArray::fromTokens (getStringValue (dict, key), ";", {}); + } +}; + +void setIfEmpty (juce::String& field, juce::StringRef fallback) +{ + if (field.isEmpty()) + field = fallback; +} + +juce::build_tools::PlistOptions parsePlistOptions (const juce::File& file, + juce::build_tools::ProjectType::Target::Type type) +{ + if (type == juce::build_tools::ProjectType::Target::ConsoleApp) + juce::ConsoleApplication::fail ("Deduced project type does not require a plist", 1); + + const auto dict = parseProjectData (file); + + UpdateField updateField { dict }; + + juce::build_tools::PlistOptions result; + + updateField ("EXECUTABLE_NAME", result.executableName); + updateField ("PLIST_TO_MERGE", result.plistToMerge); + updateField ("IS_IOS", result.iOS); + updateField ("MICROPHONE_PERMISSION_ENABLED", result.microphonePermissionEnabled); + updateField ("MICROPHONE_PERMISSION_TEXT", result.microphonePermissionText); + updateField ("CAMERA_PERMISSION_ENABLED", result.cameraPermissionEnabled); + updateField ("CAMERA_PERMISSION_TEXT", result.cameraPermissionText); + updateField ("BLUETOOTH_PERMISSION_ENABLED", result.bluetoothPermissionEnabled); + updateField ("BLUETOOTH_PERMISSION_TEXT", result.bluetoothPermissionText); + updateField ("SEND_APPLE_EVENTS_PERMISSION_ENABLED", result.sendAppleEventsPermissionEnabled); + updateField ("SEND_APPLE_EVENTS_PERMISSION_TEXT", result.sendAppleEventsPermissionText); + updateField ("SHOULD_ADD_STORYBOARD", result.shouldAddStoryboardToProject); + updateField ("LAUNCH_STORYBOARD_FILE", result.storyboardName); + updateField ("PROJECT_NAME", result.projectName); + updateField ("VERSION", result.version); + updateField ("COMPANY_COPYRIGHT", result.companyCopyright); + updateField ("DOCUMENT_EXTENSIONS", result.documentExtensions); + updateField ("FILE_SHARING_ENABLED", result.fileSharingEnabled); + updateField ("DOCUMENT_BROWSER_ENABLED", result.documentBrowserEnabled); + updateField ("STATUS_BAR_HIDDEN", result.statusBarHidden); + updateField ("BACKGROUND_AUDIO_ENABLED", result.backgroundAudioEnabled); + updateField ("BACKGROUND_BLE_ENABLED", result.backgroundBleEnabled); + updateField ("PUSH_NOTIFICATIONS_ENABLED", result.pushNotificationsEnabled); + updateField ("PLUGIN_MANUFACTURER_CODE", result.pluginManufacturerCode); + updateField ("PLUGIN_CODE", result.pluginCode); + updateField ("IPHONE_SCREEN_ORIENTATIONS", result.iPhoneScreenOrientations); + updateField ("IPAD_SCREEN_ORIENTATIONS", result.iPadScreenOrientations); + updateField ("PLUGIN_NAME", result.pluginName); + updateField ("PLUGIN_MANUFACTURER", result.pluginManufacturer); + updateField ("PLUGIN_DESCRIPTION", result.pluginDescription); + updateField ("PLUGIN_AU_EXPORT_PREFIX", result.pluginAUExportPrefix); + updateField ("PLUGIN_AU_MAIN_TYPE", result.auMainType); + updateField ("IS_AU_SANDBOX_SAFE", result.isAuSandboxSafe); + updateField ("IS_PLUGIN_SYNTH", result.isPluginSynth); + updateField ("BUNDLE_ID", result.bundleIdentifier); + updateField ("ICON_FILE", result.iconFile); + + result.type = type; + result.versionAsHex = juce::build_tools::getVersionAsHexInteger (result.version); + + if (result.storyboardName.isNotEmpty()) + result.storyboardName = result.storyboardName.fromLastOccurrenceOf ("/", false, false) + .upToLastOccurrenceOf (".storyboard", false, false); + + setIfEmpty (result.microphonePermissionText, + "This app requires audio input. If you do not have an audio interface connected it will use the built-in microphone."); + setIfEmpty (result.cameraPermissionText, + "This app requires access to the camera to function correctly."); + setIfEmpty (result.bluetoothPermissionText, + "This app requires access to Bluetooth to function correctly."); + setIfEmpty (result.sendAppleEventsPermissionText, + "This app requires the ability to send Apple events to function correctly."); + + result.documentExtensions = result.documentExtensions.replace (";", ","); + + // AUv3 needs a slightly different bundle ID + if (type == juce::build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn) + { + const auto bundleIdSegments = juce::StringArray::fromTokens (result.bundleIdentifier, ".", {}); + jassert (! bundleIdSegments.isEmpty()); + + const auto last = bundleIdSegments.isEmpty() ? "" + : bundleIdSegments[bundleIdSegments.size() - 1]; + + result.bundleIdentifier += "." + last + "AUv3"; + } + + return result; +} + +int writePlist (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (3); + const auto kind = args.arguments.removeAndReturn (0); + const auto input = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + parsePlistOptions (input.resolveAsExistingFile(), + juce::build_tools::ProjectType::Target::typeFromName (kind.text)) + .write (output.resolveAsFile()); + return 0; +} + +juce::build_tools::EntitlementOptions parseEntitlementsOptions (const juce::File& file, + juce::build_tools::ProjectType::Target::Type type) +{ + if (type == juce::build_tools::ProjectType::Target::ConsoleApp) + juce::ConsoleApplication::fail ("Deduced project type does not require entitlements", 1); + + const auto dict = parseProjectData (file); + + UpdateField updateField { dict }; + + juce::build_tools::EntitlementOptions result; + + updateField ("IS_IOS", result.isiOS); + updateField ("IS_PLUGIN", result.isAudioPluginProject); + updateField ("ICLOUD_PERMISSIONS_ENABLED", result.isiCloudPermissionsEnabled); + updateField ("PUSH_NOTIFICATIONS_ENABLED", result.isPushNotificationsEnabled); + updateField ("APP_GROUPS_ENABLED", result.isAppGroupsEnabled); + updateField ("APP_GROUP_IDS", result.appGroupIdString); + updateField ("HARDENED_RUNTIME_ENABLED", result.isHardenedRuntimeEnabled); + updateField ("HARDENED_RUNTIME_OPTIONS", result.hardenedRuntimeOptions); + updateField ("APP_SANDBOX_ENABLED", result.isAppSandboxEnabled); + updateField ("APP_SANDBOX_INHERIT", result.isAppSandboxInhertianceEnabled); + updateField ("APP_SANDBOX_OPTIONS", result.appSandboxOptions); + + result.type = type; + + return result; +} + +int writeEntitlements (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (3); + const auto kind = args.arguments.removeAndReturn (0); + const auto input = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + + const auto options = parseEntitlementsOptions (input.resolveAsExistingFile(), + juce::build_tools::ProjectType::Target::typeFromName (kind.text)); + juce::build_tools::overwriteFileIfDifferentOrThrow (output.resolveAsFile(), options.getEntitlementsFileContent()); + return 0; +} + +int createAndWrite (const juce::File& file, juce::StringRef text) +{ + if (file.create()) + return file.replaceWithText (text) ? 0 : 1; + + return 1; +} + +int writePkgInfo (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (2); + const auto kind = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + + const auto projectType = juce::build_tools::ProjectType::Target::typeFromName (kind.text); + return createAndWrite (output.resolveAsFile(), + juce::build_tools::getXcodePackageType (projectType) + + juce::build_tools::getXcodeBundleSignature (projectType)); +} + +juce::build_tools::ResourceRcOptions parseRcFileOptions (const juce::File& file) +{ + const auto dict = parseProjectData (file); + UpdateField updateField { dict }; + + juce::build_tools::ResourceRcOptions result; + + updateField ("VERSION", result.version); + updateField ("COMPANY_NAME", result.companyName); + updateField ("COMPANY_COPYRIGHT", result.companyCopyright); + updateField ("PROJECT_NAME", result.projectName); + updateField ("ICON_FILE", result.icon); + + return result; +} + +int writeRcFile (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (2); + const auto input = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + parseRcFileOptions (input.resolveAsExistingFile()).write (output.resolveAsFile()); + return 0; +} + +juce::String createDefineStatements (juce::StringRef definitions) +{ + const auto split = juce::StringArray::fromTokens (definitions, ";", "\""); + + juce::String defineStatements; + + for (const auto& def : split) + { + const auto defineName = def.upToFirstOccurrenceOf ("=", false, false); + const auto defineValue = def.fromFirstOccurrenceOf ("=", false, false); + defineStatements += "#define " + defineName + " " + defineValue + '\n'; + } + + return defineStatements; +} + +int writeAuAppConfig (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (2); + const auto input = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + + const auto dict = parseProjectData (input.resolveAsExistingFile()); + const auto getString = [&] (juce::StringRef key) { return getStringValue (dict, key); }; + + const auto defines = "#pragma once\n" + createDefineStatements (getString ("MODULE_DEFINITIONS")); + return createAndWrite (output.resolveAsFile(), defines); +} + +juce::String createIncludeStatements (juce::StringRef definitions) +{ + const auto split = juce::StringArray::fromTokens (definitions, ";", "\""); + + juce::String includeStatements; + + for (const auto& def : split) + { + constexpr auto moduleToken = "JUCE_MODULE_AVAILABLE_"; + + if (def.startsWith (moduleToken)) + { + const auto moduleName = def.fromFirstOccurrenceOf (moduleToken, false, false) + .upToFirstOccurrenceOf ("=", false, false); + includeStatements += "#include <" + moduleName + "/" + moduleName + ".h>\n"; + } + } + + return includeStatements; +} + +int writeHeader (juce::ArgumentList&& args) +{ + args.checkMinNumArguments (2); + const auto input = args.arguments.removeAndReturn (0); + const auto output = args.arguments.removeAndReturn (0); + + const auto dict = parseProjectData (input.resolveAsExistingFile()); + + const auto getString = [&] (juce::StringRef key) { return getStringValue (dict, key); }; + + const auto includes = createIncludeStatements (getString ("MODULE_DEFINITIONS")); + const auto projectName = getString ("PROJECT_NAME"); + const auto name = projectName.isEmpty() ? getString ("EXECUTABLE_NAME") : projectName; + const auto versionString = getString ("VERSION"); + + const auto headerText = juce::String (headerTemplate) + .replace ("${JUCE_INCLUDES}", includes) + .replace ("${JUCE_EXECUTABLE_NAME}", name) + .replace ("${JUCE_COMPANY_NAME}", getString ("COMPANY_NAME")) + .replace ("${JUCE_PROJECT_VERSION}", versionString) + .replace ("${JUCE_PROJECT_VERSION_HEX}", juce::build_tools::getVersionAsHex (versionString)); + + return createAndWrite (output.resolveAsFile(), headerText); +} + +} // namespace + +int main (int argc, char** argv) +{ + juce::ScopedJuceInitialiser_GUI libraryInitialiser; + + return juce::ConsoleApplication::invokeCatchingFailures ([argc, argv] + { + juce::ArgumentList argumentList { argc, argv }; + + using Fn = typename std::add_lvalue_reference::type; + + const std::unordered_map commands + { + { "auappconfig", writeAuAppConfig }, + { "binarydata", writeBinaryData }, + { "entitlements", writeEntitlements }, + { "header", writeHeader }, + { "iosassets", writeiOSAssets }, + { "macicon", writeMacIcon }, + { "pkginfo", writePkgInfo }, + { "plist", writePlist }, + { "rcfile", writeRcFile }, + { "winicon", writeWinIcon } + }; + + argumentList.checkMinNumArguments (1); + const auto mode = argumentList.arguments.removeAndReturn (0); + const auto it = commands.find (mode.text); + + if (it == commands.cend()) + juce::ConsoleApplication::fail ("No matching mode", 1); + + return it->second (std::move (argumentList)); + }); +} diff --git a/extras/CMakeLists.txt b/extras/CMakeLists.txt new file mode 100644 index 0000000000..896c1d828b --- /dev/null +++ b/extras/CMakeLists.txt @@ -0,0 +1,22 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +add_subdirectory(AudioPerformanceTest) +add_subdirectory(AudioPluginHost) +add_subdirectory(BinaryBuilder) +add_subdirectory(NetworkGraphicsDemo) +add_subdirectory(Projucer) +add_subdirectory(UnitTestRunner) diff --git a/extras/NetworkGraphicsDemo/CMakeLists.txt b/extras/NetworkGraphicsDemo/CMakeLists.txt new file mode 100644 index 0000000000..7e0243d650 --- /dev/null +++ b/extras/NetworkGraphicsDemo/CMakeLists.txt @@ -0,0 +1,30 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_gui_app(NetworkGraphicsDemo) + +juce_generate_juce_header(NetworkGraphicsDemo) + +target_sources(NetworkGraphicsDemo PRIVATE Source/Main.cpp) + +target_compile_definitions(NetworkGraphicsDemo PRIVATE + JUCE_USE_CURL=0 JUCE_WEB_BROWSER=0) + +target_link_libraries(NetworkGraphicsDemo PRIVATE + juce::juce_audio_utils + juce::juce_cryptography + juce::juce_opengl + juce::juce_osc) diff --git a/extras/Projucer/Builds/LinuxMakefile/Makefile b/extras/Projucer/Builds/LinuxMakefile/Makefile index f1f6fbcbae..b3bb9a3457 100644 --- a/extras/Projucer/Builds/LinuxMakefile/Makefile +++ b/extras/Projucer/Builds/LinuxMakefile/Makefile @@ -35,7 +35,7 @@ ifeq ($(CONFIG),Debug) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=6.0.0 -DJUCE_APP_VERSION_HEX=0x60000 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=6.0.0 -DJUCE_APP_VERSION_HEX=0x60000 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules -I../../../Build $(CPPFLAGS) JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0 JUCE_TARGET_APP := Projucer @@ -56,7 +56,7 @@ ifeq ($(CONFIG),Release) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=6.0.0 -DJUCE_APP_VERSION_HEX=0x60000 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=6.0.0 -DJUCE_APP_VERSION_HEX=0x60000 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules -I../../../Build $(CPPFLAGS) JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0 JUCE_TARGET_APP := Projucer @@ -123,6 +123,7 @@ OBJECTS_APP := \ $(JUCE_OBJDIR)/jucer_NewProjectWizardClasses_891f6fa2.o \ $(JUCE_OBJDIR)/BinaryData_ce4232d4.o \ $(JUCE_OBJDIR)/include_juce_analytics_f8e9fa94.o \ + $(JUCE_OBJDIR)/include_juce_build_tools_f5069398.o \ $(JUCE_OBJDIR)/include_juce_core_f26d17db.o \ $(JUCE_OBJDIR)/include_juce_cryptography_8cb807a8.o \ $(JUCE_OBJDIR)/include_juce_data_structures_7471b1e3.o \ @@ -419,6 +420,11 @@ $(JUCE_OBJDIR)/include_juce_analytics_f8e9fa94.o: ../../JuceLibraryCode/include_ @echo "Compiling include_juce_analytics.cpp" $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" +$(JUCE_OBJDIR)/include_juce_build_tools_f5069398.o: ../../JuceLibraryCode/include_juce_build_tools.cpp + -$(V_AT)mkdir -p $(JUCE_OBJDIR) + @echo "Compiling include_juce_build_tools.cpp" + $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" + $(JUCE_OBJDIR)/include_juce_core_f26d17db.o: ../../JuceLibraryCode/include_juce_core.cpp -$(V_AT)mkdir -p $(JUCE_OBJDIR) @echo "Compiling include_juce_core.cpp" diff --git a/extras/Projucer/Builds/MacOSX/Icon.icns b/extras/Projucer/Builds/MacOSX/Icon.icns index 64566582b2fa7109c5409816ee0cbb78564cd94a..6ab6915802b8cc41702a02e8527aec517d379e77 100644 GIT binary patch delta 23 ccmZ2}kLlPRR*uZ%ykZ8%IJb=)^6Nnu0BpAicK`qY delta 19 bcmX@MhjsZqCXUSHykZ81_39fr Disabled ProgramDatabase - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreadedDebugDLL true @@ -105,7 +105,7 @@ Full - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreaded true @@ -187,9 +187,6 @@ true - - true - @@ -253,6 +250,36 @@ true + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + true @@ -1452,6 +1479,7 @@ + @@ -1601,7 +1629,6 @@ - @@ -1654,6 +1681,17 @@ + + + + + + + + + + + @@ -2064,6 +2102,12 @@ + + + + + + @@ -2088,13 +2132,11 @@ - - diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters index 16e2c05db3..5e4ad5f4ed 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters @@ -95,6 +95,12 @@ {97F7F593-75F8-D6B2-DC96-C946C3976226} + + {D9FAFF6D-6737-F775-056A-D0B29BE13820} + + + {065C11E4-EB37-5B72-0A01-F549675EB866} + {42F7BE9D-3C8A-AE26-289B-8F355C068036} @@ -370,9 +376,6 @@ Projucer\BinaryData\Templates - - Projucer\BinaryData\Templates - Projucer\CodeEditor @@ -532,6 +535,36 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -1819,6 +1852,9 @@ JUCE Library Code + + JUCE Library Code + JUCE Library Code @@ -2262,9 +2298,6 @@ Projucer\Project - - Projucer\Project - Projucer\ProjectSaving @@ -2421,6 +2454,39 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -3647,6 +3713,24 @@ + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + Projucer\BinaryData\gradle @@ -3719,9 +3803,6 @@ Projucer\BinaryData\Icons - - Projucer\BinaryData\Templates - Projucer\BinaryData @@ -3737,9 +3818,6 @@ Projucer\BinaryData - - Projucer\BinaryData - JUCE Modules\juce_core\native\java diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj index 9d0a16efa4..af2f0fc8bf 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj @@ -63,7 +63,7 @@ Disabled ProgramDatabase - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreadedDebug true @@ -105,7 +105,7 @@ Full - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreaded true @@ -187,9 +187,6 @@ true - - true - @@ -253,6 +250,36 @@ true + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + true @@ -1452,6 +1479,7 @@ + @@ -1601,7 +1629,6 @@ - @@ -1654,6 +1681,17 @@ + + + + + + + + + + + @@ -2064,6 +2102,12 @@ + + + + + + @@ -2088,13 +2132,11 @@ - - diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters index 8148e932e2..41c98e79c0 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters @@ -95,6 +95,12 @@ {97F7F593-75F8-D6B2-DC96-C946C3976226} + + {D9FAFF6D-6737-F775-056A-D0B29BE13820} + + + {065C11E4-EB37-5B72-0A01-F549675EB866} + {42F7BE9D-3C8A-AE26-289B-8F355C068036} @@ -370,9 +376,6 @@ Projucer\BinaryData\Templates - - Projucer\BinaryData\Templates - Projucer\CodeEditor @@ -532,6 +535,36 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -1819,6 +1852,9 @@ JUCE Library Code + + JUCE Library Code + JUCE Library Code @@ -2262,9 +2298,6 @@ Projucer\Project - - Projucer\Project - Projucer\ProjectSaving @@ -2421,6 +2454,39 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -3647,6 +3713,24 @@ + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + Projucer\BinaryData\gradle @@ -3719,9 +3803,6 @@ Projucer\BinaryData\Icons - - Projucer\BinaryData\Templates - Projucer\BinaryData @@ -3737,9 +3818,6 @@ Projucer\BinaryData - - Projucer\BinaryData - JUCE Modules\juce_core\native\java diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj index 540cba1d5b..5be97d0395 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj @@ -63,7 +63,7 @@ Disabled ProgramDatabase - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreadedDebug true @@ -105,7 +105,7 @@ Full - ..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories) + ..\..\JuceLibraryCode;..\..\..\..\modules;..\..\..\Build;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=6.0.0;JUCE_APP_VERSION_HEX=0x60000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions) MultiThreaded true @@ -187,9 +187,6 @@ true - - true - @@ -253,6 +250,36 @@ true + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + true @@ -1452,6 +1479,7 @@ + @@ -1601,7 +1629,6 @@ - @@ -1654,6 +1681,17 @@ + + + + + + + + + + + @@ -2064,6 +2102,12 @@ + + + + + + @@ -2088,13 +2132,11 @@ - - diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters index 1acc5e8090..232cec7208 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters @@ -95,6 +95,12 @@ {97F7F593-75F8-D6B2-DC96-C946C3976226} + + {D9FAFF6D-6737-F775-056A-D0B29BE13820} + + + {065C11E4-EB37-5B72-0A01-F549675EB866} + {42F7BE9D-3C8A-AE26-289B-8F355C068036} @@ -370,9 +376,6 @@ Projucer\BinaryData\Templates - - Projucer\BinaryData\Templates - Projucer\CodeEditor @@ -532,6 +535,36 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -1819,6 +1852,9 @@ JUCE Library Code + + JUCE Library Code + JUCE Library Code @@ -2262,9 +2298,6 @@ Projucer\Project - - Projucer\Project - Projucer\ProjectSaving @@ -2421,6 +2454,39 @@ JUCE Modules\juce_analytics + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools\utils + + + JUCE Modules\juce_build_tools + JUCE Modules\juce_core\containers @@ -3647,6 +3713,24 @@ + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + + + Projucer\BinaryData + Projucer\BinaryData\gradle @@ -3719,9 +3803,6 @@ Projucer\BinaryData\Icons - - Projucer\BinaryData\Templates - Projucer\BinaryData @@ -3737,9 +3818,6 @@ Projucer\BinaryData - - Projucer\BinaryData - JUCE Modules\juce_core\native\java diff --git a/extras/Projucer/CMakeLists.txt b/extras/Projucer/CMakeLists.txt new file mode 100644 index 0000000000..4246730d33 --- /dev/null +++ b/extras/Projucer/CMakeLists.txt @@ -0,0 +1,166 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_gui_app(Projucer + BUNDLE_ID com.juce.theprojucer + ICON_BIG ${CMAKE_CURRENT_SOURCE_DIR}/Source/BinaryData/Icons/juce_icon.png + DOCUMENT_EXTENSIONS jucer + NEEDS_CURL TRUE + NEEDS_WEB_BROWSER TRUE) + +juce_generate_juce_header(Projucer) + +# This is to work around a bug with how cmake computes language standard flags with +# target_compile_features +set_target_properties(Projucer PROPERTIES CXX_STANDARD 11) + +target_sources(Projucer PRIVATE + Source/Application/jucer_AutoUpdater.cpp + Source/Application/jucer_CommandLine.cpp + Source/Application/jucer_Main.cpp + Source/Application/jucer_MainWindow.cpp + Source/Application/jucer_ProjucerAnalytics.cpp + Source/CodeEditor/jucer_DocumentEditorComponent.cpp + Source/CodeEditor/jucer_OpenDocumentManager.cpp + Source/CodeEditor/jucer_SourceCodeEditor.cpp + Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp + Source/ComponentEditor/Documents/jucer_ButtonDocument.cpp + Source/ComponentEditor/Documents/jucer_ComponentDocument.cpp + Source/ComponentEditor/PaintElements/jucer_ColouredElement.cpp + Source/ComponentEditor/PaintElements/jucer_PaintElement.cpp + Source/ComponentEditor/PaintElements/jucer_PaintElementGroup.cpp + Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp + Source/ComponentEditor/PaintElements/jucer_PaintElementPath.cpp + Source/ComponentEditor/UI/jucer_ComponentLayoutEditor.cpp + Source/ComponentEditor/UI/jucer_ComponentOverlayComponent.cpp + Source/ComponentEditor/UI/jucer_EditingPanelBase.cpp + Source/ComponentEditor/UI/jucer_JucerDocumentEditor.cpp + Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp + Source/ComponentEditor/UI/jucer_PaintRoutinePanel.cpp + Source/ComponentEditor/UI/jucer_ResourceEditorPanel.cpp + Source/ComponentEditor/UI/jucer_TestComponent.cpp + Source/ComponentEditor/jucer_BinaryResources.cpp + Source/ComponentEditor/jucer_ComponentLayout.cpp + Source/ComponentEditor/jucer_GeneratedCode.cpp + Source/ComponentEditor/jucer_JucerDocument.cpp + Source/ComponentEditor/jucer_ObjectTypes.cpp + Source/ComponentEditor/jucer_PaintRoutine.cpp + Source/Licenses/jucer_LicenseController.cpp + Source/LiveBuildEngine/jucer_CompileEngineClient.cpp + Source/LiveBuildEngine/jucer_CompileEngineServer.cpp + Source/LiveBuildEngine/jucer_DownloadCompileEngineThread.cpp + Source/Project/UI/jucer_HeaderComponent.cpp + Source/Project/jucer_Module.cpp + Source/Project/jucer_Project.cpp + Source/ProjectSaving/jucer_ProjectExporter.cpp + Source/ProjectSaving/jucer_ProjectSaver.cpp + Source/ProjectSaving/jucer_ResourceFile.cpp + Source/Settings/jucer_AppearanceSettings.cpp + Source/Settings/jucer_StoredSettings.cpp + Source/Utility/Helpers/jucer_CodeHelpers.cpp + Source/Utility/Helpers/jucer_FileHelpers.cpp + Source/Utility/Helpers/jucer_MiscUtilities.cpp + Source/Utility/Helpers/jucer_VersionInfo.cpp + Source/Utility/PIPs/jucer_PIPGenerator.cpp + Source/Utility/UI/jucer_Icons.cpp + Source/Utility/UI/jucer_JucerTreeViewBase.cpp + Source/Utility/UI/jucer_ProjucerLookAndFeel.cpp + Source/Utility/UI/jucer_SlidingPanelComponent.cpp + Source/Wizards/jucer_NewFileWizard.cpp + Source/Wizards/jucer_NewProjectWizardClasses.cpp) + +target_compile_definitions(Projucer PRIVATE + JUCE_ALLOW_STATIC_NULL_VARIABLES=0 + JUCE_LOAD_CURL_SYMBOLS_LAZILY=1 + JUCE_LOG_ASSERTIONS=1 + JUCE_STRICT_REFCOUNTEDPOINTER=1 + JUCE_USE_CURL=1 + JUCE_WEB_BROWSER=1) + +juce_add_binary_data(ProjucerData SOURCES + Source/BinaryData/Icons/background_logo.svg + Source/BinaryData/Icons/export_android.svg + Source/BinaryData/Icons/export_clion.svg + Source/BinaryData/Icons/export_codeBlocks.svg + Source/BinaryData/Icons/export_linux.svg + Source/BinaryData/Icons/export_visualStudio.svg + Source/BinaryData/Icons/export_xcode.svg + Source/BinaryData/Icons/huckleberry_icon.svg + Source/BinaryData/Icons/juce-logo-with-text.svg + Source/BinaryData/Icons/juce_icon.png + Source/BinaryData/Icons/wizard_AnimatedApp.svg + Source/BinaryData/Icons/wizard_AudioApp.svg + Source/BinaryData/Icons/wizard_AudioPlugin.svg + Source/BinaryData/Icons/wizard_ConsoleApp.svg + Source/BinaryData/Icons/wizard_DLL.svg + Source/BinaryData/Icons/wizard_GUI.svg + Source/BinaryData/Icons/wizard_Highlight.svg + Source/BinaryData/Icons/wizard_OpenGL.svg + Source/BinaryData/Icons/wizard_Openfile.svg + Source/BinaryData/Icons/wizard_StaticLibrary.svg + Source/BinaryData/Templates/jucer_AnimatedComponentSimpleTemplate.h + Source/BinaryData/Templates/jucer_AnimatedComponentTemplate.cpp + Source/BinaryData/Templates/jucer_AnimatedComponentTemplate.h + Source/BinaryData/Templates/jucer_AudioComponentSimpleTemplate.h + Source/BinaryData/Templates/jucer_AudioComponentTemplate.cpp + Source/BinaryData/Templates/jucer_AudioComponentTemplate.h + Source/BinaryData/Templates/jucer_AudioPluginEditorTemplate.cpp + Source/BinaryData/Templates/jucer_AudioPluginEditorTemplate.h + Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.cpp + Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h + Source/BinaryData/Templates/jucer_ComponentTemplate.cpp + Source/BinaryData/Templates/jucer_ComponentTemplate.h + Source/BinaryData/Templates/jucer_ContentCompSimpleTemplate.h + Source/BinaryData/Templates/jucer_ContentCompTemplate.cpp + Source/BinaryData/Templates/jucer_ContentCompTemplate.h + Source/BinaryData/Templates/jucer_InlineComponentTemplate.h + Source/BinaryData/Templates/jucer_MainConsoleAppTemplate.cpp + Source/BinaryData/Templates/jucer_MainTemplate_NoWindow.cpp + Source/BinaryData/Templates/jucer_MainTemplate_SimpleWindow.cpp + Source/BinaryData/Templates/jucer_MainTemplate_Window.cpp + Source/BinaryData/Templates/jucer_NewComponentTemplate.cpp + Source/BinaryData/Templates/jucer_NewComponentTemplate.h + Source/BinaryData/Templates/jucer_NewCppFileTemplate.cpp + Source/BinaryData/Templates/jucer_NewCppFileTemplate.h + Source/BinaryData/Templates/jucer_NewInlineComponentTemplate.h + Source/BinaryData/Templates/jucer_OpenGLComponentSimpleTemplate.h + Source/BinaryData/Templates/jucer_OpenGLComponentTemplate.cpp + Source/BinaryData/Templates/jucer_OpenGLComponentTemplate.h + Source/BinaryData/Templates/jucer_PIPAudioProcessorTemplate.h + Source/BinaryData/Templates/jucer_PIPTemplate.h + Source/BinaryData/colourscheme_dark.xml + Source/BinaryData/colourscheme_light.xml + Source/BinaryData/gradle/LICENSE + Source/BinaryData/gradle/gradle-wrapper.jar + Source/BinaryData/gradle/gradlew + Source/BinaryData/gradle/gradlew.bat + Source/BinaryData/nothingtoseehere.txt + Source/BinaryData/offlinepage.html + Source/BinaryData/projucer_EULA.txt + + ../Build/CMake/LaunchScreen.storyboard + ../Build/CMake/PIPAudioProcessor.cpp.in + ../Build/CMake/PIPComponent.cpp.in + ../Build/CMake/PIPConsole.cpp.in + ../Build/CMake/RecentFilesMenuTemplate.nib + ../Build/CMake/UnityPluginGUIScript.cs.in) + +target_link_libraries(Projucer PRIVATE + ProjucerData + juce::juce_analytics + juce::juce_build_tools + juce::juce_cryptography + juce::juce_gui_extra) diff --git a/extras/Projucer/JuceLibraryCode/AppConfig.h b/extras/Projucer/JuceLibraryCode/AppConfig.h index 58af4492b9..30a713c38a 100644 --- a/extras/Projucer/JuceLibraryCode/AppConfig.h +++ b/extras/Projucer/JuceLibraryCode/AppConfig.h @@ -70,6 +70,7 @@ //============================================================================== #define JUCE_MODULE_AVAILABLE_juce_analytics 1 +#define JUCE_MODULE_AVAILABLE_juce_build_tools 1 #define JUCE_MODULE_AVAILABLE_juce_core 1 #define JUCE_MODULE_AVAILABLE_juce_cryptography 1 #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index 8bf9c4cdda..5a5a3509e3 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -7,8 +7,365 @@ namespace BinaryData { -//================== gradle-wrapper.jar ================== +//================== LaunchScreen.storyboard ================== static const unsigned char temp_binary_data_0[] = +"\n" +"\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n"; + +const char* LaunchScreen_storyboard = (const char*) temp_binary_data_0; + +//================== PIPAudioProcessor.cpp.in ================== +static const unsigned char temp_binary_data_1[] = +"/*\n" +" ==============================================================================\n" +"\n" +" This file was auto-generated and contains the startup code for a PIP.\n" +"\n" +" ==============================================================================\n" +"*/\n" +"\n" +"#include \n" +"#include \"${JUCE_PIP_HEADER}\"\n" +"\n" +"//==============================================================================\n" +"AudioProcessor* JUCE_CALLTYPE createPluginFilter()\n" +"{\n" +" return new ${JUCE_PIP_MAIN_CLASS}();\n" +"}\n"; + +const char* PIPAudioProcessor_cpp_in = (const char*) temp_binary_data_1; + +//================== PIPComponent.cpp.in ================== +static const unsigned char temp_binary_data_2[] = +"/*\n" +" ==============================================================================\n" +"\n" +" This file was auto-generated and contains the startup code for a PIP.\n" +"\n" +" ==============================================================================\n" +"*/\n" +"\n" +"#include \n" +"#include \"${JUCE_PIP_HEADER}\"\n" +"\n" +"class Application : public JUCEApplication\n" +"{\n" +"public:\n" +" //==============================================================================\n" +" Application() {}\n" +"\n" +" const String getApplicationName() override { return \"${JUCE_PIP_NAME}\"; }\n" +" const String getApplicationVersion() override { return \"${PROJECT_VERSION}\"; }\n" +"\n" +" void initialise (const String&) override\n" +" {\n" +" mainWindow.reset (new MainWindow (\"${JUCE_PIP_NAME}\", new ${JUCE_PIP_MAIN_CLASS}, *this));\n" +" }\n" +"\n" +" void shutdown() override { mainWindow = nullptr; }\n" +"\n" +"private:\n" +" class MainWindow : public DocumentWindow\n" +" {\n" +" public:\n" +" MainWindow (const String& name, Component* c, JUCEApplication& a)\n" +" : DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel()\n" +" .findColour (ResizableWindow::backgroundColourId),\n" +" DocumentWindow::allButtons),\n" +" app (a)\n" +" {\n" +" setUsingNativeTitleBar (true);\n" +" setContentOwned (c, true);\n" +"\n" +" #if JUCE_ANDROID || JUCE_IOS\n" +" setFullScreen (true);\n" +" #else\n" +" setResizable (true, false);\n" +" setResizeLimits (300, 250, 10000, 10000);\n" +" centreWithSize (getWidth(), getHeight());\n" +" #endif\n" +"\n" +" setVisible (true);\n" +" }\n" +"\n" +" void closeButtonPressed() override\n" +" {\n" +" app.systemRequestedQuit();\n" +" }\n" +"\n" +" private:\n" +" JUCEApplication& app;\n" +"\n" +" //==============================================================================\n" +" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)\n" +" };\n" +"\n" +" std::unique_ptr mainWindow;\n" +"};\n" +"\n" +"//==============================================================================\n" +"START_JUCE_APPLICATION (Application)\n"; + +const char* PIPComponent_cpp_in = (const char*) temp_binary_data_2; + +//================== PIPConsole.cpp.in ================== +static const unsigned char temp_binary_data_3[] = +"/*\n" +" ==============================================================================\n" +"\n" +" This file was auto-generated and contains the startup code for a PIP.\n" +"\n" +" ==============================================================================\n" +"*/\n" +"\n" +"#include \n" +"#include \"${JUCE_PIP_HEADER}\"\n"; + +const char* PIPConsole_cpp_in = (const char*) temp_binary_data_3; + +//================== RecentFilesMenuTemplate.nib ================== +static const unsigned char temp_binary_data_4[] = +{ 98,112,108,105,115,116,48,48,212,0,1,0,2,0,3,0,4,0,5,0,6,1,53,1,54,88,36,118,101,114,115,105,111,110,88,36,111,98,106,101,99,116,115,89,36,97,114,99,104,105,118,101,114,84,36,116,111,112,18,0,1,134,160,175,16,74,0,7,0,8,0,31,0,35,0,36,0,42,0,46,0,50, +0,53,0,57,0,74,0,77,0,78,0,86,0,87,0,97,0,112,0,113,0,114,0,119,0,120,0,121,0,124,0,128,0,129,0,132,0,143,0,144,0,145,0,149,0,153,0,162,0,163,0,164,0,169,0,173,0,180,0,181,0,182,0,185,0,192,0,193,0,200,0,201,0,208,0,209,0,216,0,217,0,224,0,225,0,226, +0,229,0,230,0,232,0,249,1,11,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,47,1,50,85,36,110,117,108,108,219,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0, +29,95,16,16,78,83,86,105,115,105,98,108,101,87,105,110,100,111,119,115,93,78,83,79,98,106,101,99,116,115,75,101,121,115,86,78,83,82,111,111,116,92,78,83,79,105,100,115,86,97,108,117,101,115,86,36,99,108,97,115,115,90,78,83,79,105,100,115,75,101,121,115, +93,78,83,67,111,110,110,101,99,116,105,111,110,115,95,16,15,78,83,79,98,106,101,99,116,115,86,97,108,117,101,115,95,16,25,78,83,65,99,99,101,115,115,105,98,105,108,105,116,121,67,111,110,110,101,99,116,111,114,115,95,16,23,78,83,65,99,99,101,115,115, +105,98,105,108,105,116,121,79,105,100,115,75,101,121,115,95,16,25,78,83,65,99,99,101,115,115,105,98,105,108,105,116,121,79,105,100,115,86,97,108,117,101,115,128,5,128,9,128,2,128,55,128,73,128,54,128,7,128,53,128,71,128,72,128,72,210,0,13,0,32,0,33,0, +34,91,78,83,67,108,97,115,115,78,97,109,101,128,4,128,3,93,78,83,65,112,112,108,105,99,97,116,105,111,110,210,0,37,0,38,0,39,0,40,90,36,99,108,97,115,115,110,97,109,101,88,36,99,108,97,115,115,101,115,94,78,83,67,117,115,116,111,109,79,98,106,101,99, +116,162,0,39,0,41,88,78,83,79,98,106,101,99,116,210,0,13,0,43,0,44,0,45,90,78,83,46,111,98,106,101,99,116,115,128,6,160,210,0,37,0,38,0,47,0,48,92,78,83,77,117,116,97,98,108,101,83,101,116,163,0,47,0,49,0,41,85,78,83,83,101,116,210,0,13,0,43,0,51,0,52, +128,8,160,210,0,37,0,38,0,54,0,55,94,78,83,77,117,116,97,98,108,101,65,114,114,97,121,163,0,54,0,56,0,41,87,78,83,65,114,114,97,121,210,0,13,0,43,0,58,0,59,128,52,174,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,128,10,128,12, +128,45,128,15,128,39,128,25,128,28,128,30,128,33,128,35,128,43,128,41,128,47,128,50,210,0,13,0,32,0,33,0,76,128,4,128,11,93,78,83,65,112,112,108,105,99,97,116,105,111,110,212,0,79,0,13,0,80,0,81,0,82,0,83,0,84,0,85,91,78,83,77,101,110,117,73,116,101, +109,115,86,78,83,78,97,109,101,87,78,83,84,105,116,108,101,128,14,128,38,128,49,128,13,89,65,77,97,105,110,77,101,110,117,210,0,13,0,43,0,51,0,89,128,8,167,0,63,0,65,0,64,0,71,0,70,0,62,0,72,128,15,128,25,128,39,128,41,128,43,128,45,128,47,216,0,98,0, +99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,111,95,16,17,78,83,75,101,121,69,113,117,105,118,77,111,100,77,97,115,107,86,78,83,77,101,110,117,89,78,83,79,110,73,109,97,103,101,90,78,83,75,101,121,69,113,117,105,118, +93,78,83,77,110,101,109,111,110,105,99,76,111,99,92,78,83,77,105,120,101,100,73,109,97,103,101,18,0,16,0,0,128,12,128,18,128,24,128,17,18,127,255,255,255,128,22,128,16,91,100,101,108,109,101,65,112,112,75,105,116,80,211,0,13,0,115,0,32,0,116,0,117,0, +118,94,78,83,82,101,115,111,117,114,99,101,78,97,109,101,128,21,128,20,128,19,87,78,83,73,109,97,103,101,95,16,15,78,83,77,101,110,117,67,104,101,99,107,109,97,114,107,210,0,37,0,38,0,122,0,123,95,16,16,78,83,67,117,115,116,111,109,82,101,115,111,117, +114,99,101,162,0,122,0,41,211,0,13,0,115,0,32,0,116,0,126,0,118,128,21,128,23,128,19,95,16,16,78,83,77,101,110,117,77,105,120,101,100,83,116,97,116,101,210,0,37,0,38,0,130,0,131,90,78,83,77,101,110,117,73,116,101,109,162,0,130,0,41,218,0,133,0,98,0,134, +0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,135,0,104,0,66,0,61,0,106,0,107,0,108,0,109,0,110,0,142,88,78,83,65,99,116,105,111,110,89,78,83,83,117,98,109,101,110,117,128,27,128,28,128,12,128,18,128,24,128,17,128,22,128,26,84,70,105,108,101,94,115,117,98, +109,101,110,117,65,99,116,105,111,110,58,211,0,79,0,13,0,81,0,146,0,83,0,142,128,29,128,38,128,26,210,0,13,0,43,0,51,0,151,128,8,161,0,67,128,30,218,0,133,0,98,0,134,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,154,0,104,0,68,0,66,0,106,0,107,0,108,0,109, +0,110,0,161,128,32,128,33,128,28,128,18,128,24,128,17,128,22,128,31,91,79,112,101,110,32,82,101,99,101,110,116,94,115,117,98,109,101,110,117,65,99,116,105,111,110,58,212,0,79,0,13,0,80,0,81,0,165,0,83,0,167,0,161,128,34,128,38,128,37,128,31,210,0,13, +0,43,0,51,0,171,128,8,161,0,69,128,35,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,68,0,106,0,107,0,108,0,109,0,110,0,179,128,33,128,18,128,24,128,17,128,22,128,36,90,67,108,101,97,114,32,77,101,110,117,95,16,22,95,78,83,82,101,99,101,110, +116,68,111,99,117,109,101,110,116,115,77,101,110,117,210,0,37,0,38,0,183,0,184,86,78,83,77,101,110,117,162,0,183,0,41,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,191,128,12,128,18,128,24,128,17,128,22,128, +40,84,69,100,105,116,215,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,61,0,106,0,107,0,108,0,109,0,110,0,199,128,12,128,18,128,24,128,17,128,22,128,42,86,70,111,114,109,97,116,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0, +109,0,110,0,207,128,12,128,18,128,24,128,17,128,22,128,44,84,86,105,101,119,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,215,128,12,128,18,128,24,128,17,128,22,128,46,86,87,105,110,100,111,119,215,0,99,0, +100,0,13,0,101,0,102,0,103,0,81,0,61,0,106,0,107,0,108,0,109,0,110,0,223,128,12,128,18,128,24,128,17,128,22,128,48,84,72,101,108,112,91,95,78,83,77,97,105,110,77,101,110,117,210,0,13,0,32,0,33,0,228,128,4,128,51,93,78,83,70,111,110,116,77,97,110,97,103, +101,114,210,0,37,0,38,0,56,0,231,162,0,56,0,41,210,0,13,0,43,0,58,0,234,128,52,174,0,22,0,22,0,61,0,61,0,61,0,61,0,65,0,66,0,67,0,68,0,61,0,61,0,61,0,22,128,2,128,2,128,12,128,12,128,12,128,12,128,25,128,28,128,30,128,33,128,12,128,12,128,12,128,2,210, +0,13,0,43,0,58,0,251,128,52,175,16,15,0,22,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,128,2,128,10,128,12,128,45,128,15,128,39,128,25,128,28,128,30,128,33,128,35,128,43,128,41,128,47,128,50,210,0,13,0,43,0,58,1,13,128,52,175, +16,15,1,14,1,15,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,1,28,128,56,128,57,128,58,128,59,128,60,128,61,128,62,128,63,128,64,128,65,128,66,128,67,128,68,128,69,128,70,17,2,22,17,2,23,17,2,24,17,2,25,17,2,26,17,2,27,17,2,28,17,2,29, +17,2,30,17,2,31,17,2,32,17,2,33,17,2,34,17,2,35,17,2,36,210,0,13,0,43,0,51,1,46,128,8,160,210,0,13,0,43,0,58,1,49,128,52,160,210,0,37,0,38,1,51,1,52,94,78,83,73,66,79,98,106,101,99,116,68,97,116,97,162,1,51,0,41,95,16,15,78,83,75,101,121,101,100,65,114, +99,104,105,118,101,114,209,1,55,1,56,93,73,66,46,111,98,106,101,99,116,100,97,116,97,128,1,0,8,0,25,0,34,0,43,0,53,0,58,0,63,0,214,0,220,1,9,1,28,1,42,1,49,1,62,1,69,1,80,1,94,1,112,1,140,1,166,1,194,1,196,1,198,1,200,1,202,1,204,1,206,1,208,1,210,1, +212,1,214,1,216,1,225,1,237,1,239,1,241,1,255,2,8,2,19,2,28,2,43,2,48,2,57,2,66,2,77,2,79,2,80,2,89,2,102,2,109,2,115,2,124,2,126,2,127,2,136,2,151,2,158,2,166,2,175,2,177,2,206,2,208,2,210,2,212,2,214,2,216,2,218,2,220,2,222,2,224,2,226,2,228,2,230, +2,232,2,234,2,243,2,245,2,247,3,5,3,22,3,34,3,41,3,49,3,51,3,53,3,55,3,57,3,67,3,76,3,78,3,93,3,95,3,97,3,99,3,101,3,103,3,105,3,107,3,140,3,160,3,167,3,177,3,188,3,202,3,215,3,220,3,222,3,224,3,226,3,228,3,233,3,235,3,237,3,249,3,250,4,7,4,22,4,24,4, +26,4,28,4,36,4,54,4,63,4,82,4,87,4,100,4,102,4,104,4,106,4,125,4,134,4,145,4,150,4,191,4,200,4,210,4,212,4,214,4,216,4,218,4,220,4,222,4,224,4,226,4,231,4,246,5,3,5,5,5,7,5,9,5,18,5,20,5,23,5,25,5,66,5,68,5,70,5,72,5,74,5,76,5,78,5,80,5,82,5,94,5,109, +5,126,5,128,5,130,5,132,5,134,5,143,5,145,5,148,5,150,5,183,5,185,5,187,5,189,5,191,5,193,5,195,5,206,5,231,5,240,5,247,5,252,6,29,6,31,6,33,6,35,6,37,6,39,6,41,6,46,6,75,6,77,6,79,6,81,6,83,6,85,6,87,6,94,6,127,6,129,6,131,6,133,6,135,6,137,6,139,6, +144,6,177,6,179,6,181,6,183,6,185,6,187,6,189,6,196,6,225,6,227,6,229,6,231,6,233,6,235,6,237,6,242,6,254,7,7,7,9,7,11,7,25,7,34,7,39,7,48,7,50,7,79,7,81,7,83,7,85,7,87,7,89,7,91,7,93,7,95,7,97,7,99,7,101,7,103,7,105,7,107,7,116,7,118,7,151,7,153,7,155, +7,157,7,159,7,161,7,163,7,165,7,167,7,169,7,171,7,173,7,175,7,177,7,179,7,181,7,190,7,192,7,225,7,227,7,229,7,231,7,233,7,235,7,237,7,239,7,241,7,243,7,245,7,247,7,249,7,251,7,253,7,255,8,2,8,5,8,8,8,11,8,14,8,17,8,20,8,23,8,26,8,29,8,32,8,35,8,38,8, +41,8,44,8,53,8,55,8,56,8,65,8,67,8,68,8,77,8,92,8,97,8,115,8,120,8,134,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,136,0,0 }; + +const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_4; + +//================== UnityPluginGUIScript.cs.in ================== +static const unsigned char temp_binary_data_5[] = +"#if UNITY_EDITOR\n" +"\n" +"using UnityEditor;\n" +"using UnityEngine;\n" +"\n" +"using System.Collections.Generic;\n" +"using System.Runtime.InteropServices;\n" +"\n" +"public class ${plugin_class_name}GUI : IAudioEffectPluginGUI\n" +"{\n" +" public override string Name { get { return \"${plugin_name}\"; } }\n" +" public override string Description { get { return \"${plugin_description}\"; } }\n" +" public override string Vendor { get { return \"${plugin_vendor}\"; } }\n" +"\n" +" //==============================================================================\n" +" [DllImport(\"${plugin_name}\")] static extern System.IntPtr getRenderCallback();\n" +"\n" +" [DllImport(\"${plugin_name}\")] static extern void unityInitialiseTexture (int id, System.IntPtr texture, int width, int height);\n" +"\n" +" [DllImport(\"${plugin_name}\")] static extern void unityMouseDown (int id, float x, float y, EventModifiers mods, int button);\n" +" [DllImport(\"${plugin_name}\")] static extern void unityMouseDrag (int id, float x, float y, EventModifiers mods, int button);\n" +" [DllImport(\"${plugin_name}\")] static extern void unityMouseUp (int id, float x, float y, EventModifiers mods);\n" +"\n" +" [DllImport(\"${plugin_name}\")] static extern void unityKeyEvent (int id, KeyCode code, EventModifiers mods, string name);\n" +"\n" +" [DllImport(\"${plugin_name}\")] static extern void unitySetScreenBounds (int id, float x, float y, float w, float h);\n" +"\n" +" //==============================================================================\n" +" private class PluginGUIInstance\n" +" {\n" +" public PluginGUIInstance (ref IAudioEffectPlugin plugin, int id)\n" +" {\n" +" instanceID = id;\n" +"\n" +" float[] arr;\n" +" plugin.GetFloatBuffer (\"Editor\", out arr, 1);\n" +" hasEditor = (arr[0] > 0.0f);\n" +" }\n" +"\n" +" public void repaint (Rect r)\n" +" {\n" +" Vector2 newScreenPosition = GUIUtility.GUIToScreenPoint (r.position);\n" +"\n" +" if (bounds != r\n" +" || screenPosition != newScreenPosition)\n" +" {\n" +" screenPosition = newScreenPosition;\n" +" bounds = r;\n" +"\n" +" unitySetScreenBounds (instanceID, screenPosition.x, screenPosition.y, bounds.width, bounds.height);\n" +" setupTexture();\n" +" }\n" +"\n" +" GL.IssuePluginEvent (getRenderCallback(), instanceID);\n" +"\n" +" texture.SetPixels32 (pixels);\n" +" texture.Apply();\n" +"\n" +" EditorGUI.DrawPreviewTexture (bounds, texture);\n" +" }\n" +"\n" +" public bool handleMouseEvent (EventType eventType)\n" +" {\n" +" Vector2 mousePos = Event.current.mousePosition;\n" +" EventModifiers mods = Event.current.modifiers;\n" +"\n" +" if (! bounds.Contains (mousePos))\n" +" return false;\n" +"\n" +" Vector2 relativePos = new Vector2 (mousePos.x - bounds.x, mousePos.y - bounds.y);\n" +"\n" +" if (eventType == EventType.MouseDown)\n" +" {\n" +" unityMouseDown (instanceID, relativePos.x, relativePos.y, mods, Event.current.button);\n" +" GUIUtility.hotControl = GUIUtility.GetControlID (FocusType.Passive);\n" +" }\n" +" else if (eventType == EventType.MouseUp)\n" +" {\n" +" unityMouseUp (instanceID, relativePos.x, relativePos.y, mods);\n" +" GUIUtility.hotControl = 0;\n" +" }\n" +" else if (eventType == EventType.MouseDrag)\n" +" {\n" +" unityMouseDrag (instanceID, relativePos.x, relativePos.y, mods, Event.current.button);\n" +" }\n" +"\n" +" Event.current.Use();\n" +"\n" +" return true;\n" +" }\n" +"\n" +" public void handleKeyEvent (EventType eventType)\n" +" {\n" +" if (eventType == EventType.KeyDown)\n" +" {\n" +" KeyCode code = Event.current.keyCode;\n" +"\n" +" if (code == KeyCode.None)\n" +" return;\n" +"\n" +" EventModifiers mods = Event.current.modifiers;\n" +"\n" +" unityKeyEvent (instanceID, code, mods, code.ToString());\n" +" }\n" +" }\n" +"\n" +" private void setupTexture()\n" +" {\n" +" if (pixelHandle.IsAllocated)\n" +" pixelHandle.Free();\n" +"\n" +" texture = new Texture2D ((int) bounds.width, (int) bounds.height, TextureFormat.ARGB32, false);\n" +"\n" +" pixels = texture.GetPixels32();\n" +" pixelHandle = GCHandle.Alloc (pixels, GCHandleType.Pinned);\n" +"\n" +" unityInitialiseTexture (instanceID, pixelHandle.AddrOfPinnedObject(), texture.width, texture.height);\n" +" }\n" +"\n" +" public int instanceID = -1;\n" +" public bool hasEditor;\n" +"\n" +" private Vector2 screenPosition;\n" +" private Rect bounds;\n" +"\n" +" private Texture2D texture;\n" +" private Color32[] pixels;\n" +" private GCHandle pixelHandle;\n" +" }\n" +" List guis = new List();\n" +"\n" +" private PluginGUIInstance getGUIInstanceForPlugin (ref IAudioEffectPlugin plugin)\n" +" {\n" +" float[] idArray;\n" +" plugin.GetFloatBuffer (\"ID\", out idArray, 1);\n" +"\n" +" int id = (int) idArray[0];\n" +"\n" +" for (int i = 0; i < guis.Count; ++i)\n" +" {\n" +" if (guis[i].instanceID == id)\n" +" return guis[i];\n" +" }\n" +"\n" +" PluginGUIInstance newInstance = new PluginGUIInstance (ref plugin, id);\n" +" guis.Add (newInstance);\n" +"\n" +" return guis[guis.Count - 1];\n" +" }\n" +"\n" +" //==============================================================================\n" +" public override bool OnGUI (IAudioEffectPlugin plugin)\n" +" {\n" +" PluginGUIInstance guiInstance = getGUIInstanceForPlugin (ref plugin);\n" +"\n" +" if (! guiInstance.hasEditor)\n" +" return true;\n" +"\n" +" float[] arr;\n" +" plugin.GetFloatBuffer (\"Size\", out arr, 6);\n" +"\n" +" Rect r = GUILayoutUtility.GetRect (arr[0], arr[1],\n" +" new GUILayoutOption[] { GUILayout.MinWidth (arr[2]), GUILayout.MinHeight (arr[3]),\n" +" GUILayout.MaxWidth (arr[4]), GUILayout.MaxHeight (arr[5]) });\n" +"\n" +" int controlID = GUIUtility.GetControlID (FocusType.Passive);\n" +" Event currentEvent = Event.current;\n" +" EventType currentEventType = currentEvent.GetTypeForControl (controlID);\n" +"\n" +" if (currentEventType == EventType.Repaint)\n" +" guiInstance.repaint (r);\n" +" else if (currentEvent.isMouse)\n" +" guiInstance.handleMouseEvent (currentEventType);\n" +" else if (currentEvent.isKey)\n" +" guiInstance.handleKeyEvent (currentEventType);\n" +"\n" +" return false;\n" +" }\n" +"}\n" +"\n" +"#endif\n"; + +const char* UnityPluginGUIScript_cs_in = (const char*) temp_binary_data_5; + +//================== gradle-wrapper.jar ================== +static const unsigned char temp_binary_data_6[] = { 80,75,3,4,10,0,0,8,8,0,42,178,149,71,0,0,0,0,2,0,0,0,0,0,0,0,9,0,0,0,77,69,84,65,45,73,78,70,47,3,0,80,75,3,4,10,0,0,8,8,0,42,178,149,71,215,149,152,82,63,0,0,0,85,0,0,0,20,0,0,0,77,69,84,65,45,73,78,70,47,77,65,78,73,70,69,83,84,46,77,70,243,77,204, 203,76,75,45,46,209,13,75,45,42,206,204,207,179,82,48,212,51,224,229,242,204,45,200,73,205,77,205,43,73,44,1,10,234,134,100,150,228,164,90,41,184,23,37,166,228,164,98,200,194,181,26,233,25,2,245,242,114,1,0,80,75,3,4,10,0,0,8,8,0,22,178,149,71,0,0,0, 0,2,0,0,0,0,0,0,0,4,0,0,0,111,114,103,47,3,0,80,75,3,4,10,0,0,8,8,0,22,178,149,71,0,0,0,0,2,0,0,0,0,0,0,0,11,0,0,0,111,114,103,47,103,114,97,100,108,101,47,3,0,80,75,3,4,10,0,0,8,8,0,22,178,149,71,0,0,0,0,2,0,0,0,0,0,0,0,19,0,0,0,111,114,103,47,103,114, @@ -760,10 +1117,10 @@ static const unsigned char temp_binary_data_0[] = 76,105,110,101,80,97,114,115,101,114,36,65,102,116,101,114,70,105,114,115,116,83,117,98,67,111,109,109,97,110,100,46,99,108,97,115,115,80,75,1,2,20,3,10,0,0,8,8,0,10,178,149,71,105,222,125,0,70,0,0,0,68,0,0,0,31,0,0,0,0,0,0,0,0,0,0,0,180,129,219,191, 0,0,103,114,97,100,108,101,45,99,108,105,45,99,108,97,115,115,112,97,116,104,46,112,114,111,112,101,114,116,105,101,115,80,75,5,6,0,0,0,0,49,0,49,0,16,17,0,0,94,192,0,0,0,0,0,0 }; -const char* gradlewrapper_jar = (const char*) temp_binary_data_0; +const char* gradlewrapper_jar = (const char*) temp_binary_data_6; //================== gradlew ================== -static const unsigned char temp_binary_data_1[] = +static const unsigned char temp_binary_data_7[] = "#!/usr/bin/env bash\n" "\n" "##############################################################################\n" @@ -925,10 +1282,10 @@ static const unsigned char temp_binary_data_1[] = "\n" "exec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"; -const char* gradlew = (const char*) temp_binary_data_1; +const char* gradlew = (const char*) temp_binary_data_7; //================== gradlew.bat ================== -static const unsigned char temp_binary_data_2[] = +static const unsigned char temp_binary_data_8[] = "@if \"%DEBUG%\" == \"\" @echo off\r\n" "@rem ##########################################################################\r\n" "@rem\r\n" @@ -1020,10 +1377,10 @@ static const unsigned char temp_binary_data_2[] = "\r\n" ":omega\r\n"; -const char* gradlew_bat = (const char*) temp_binary_data_2; +const char* gradlew_bat = (const char*) temp_binary_data_8; //================== LICENSE ================== -static const unsigned char temp_binary_data_3[] = +static const unsigned char temp_binary_data_9[] = "Apache License\n" " Version 2.0, January 2004\n" " http://www.apache.org/licenses/\n" @@ -1227,10 +1584,10 @@ static const unsigned char temp_binary_data_3[] = " limitations under the License.\n" "\n"; -const char* LICENSE = (const char*) temp_binary_data_3; +const char* LICENSE = (const char*) temp_binary_data_9; //================== background_logo.svg ================== -static const unsigned char temp_binary_data_4[] = +static const unsigned char temp_binary_data_10[] = "\r\n" "\r\n" @@ -1269,10 +1626,10 @@ static const unsigned char temp_binary_data_4[] = "\r\n" "\r\n"; -const char* background_logo_svg = (const char*) temp_binary_data_4; +const char* background_logo_svg = (const char*) temp_binary_data_10; //================== export_android.svg ================== -static const unsigned char temp_binary_data_5[] = +static const unsigned char temp_binary_data_11[] = "\n" "\n" " \n" @@ -1303,10 +1660,10 @@ static const unsigned char temp_binary_data_5[] = " \n" ""; -const char* export_android_svg = (const char*) temp_binary_data_5; +const char* export_android_svg = (const char*) temp_binary_data_11; //================== export_clion.svg ================== -static const unsigned char temp_binary_data_6[] = +static const unsigned char temp_binary_data_12[] = "\n" " \n" " \n" @@ -1342,10 +1699,10 @@ static const unsigned char temp_binary_data_6[] = " \n" "\n"; -const char* export_clion_svg = (const char*) temp_binary_data_6; +const char* export_clion_svg = (const char*) temp_binary_data_12; //================== export_codeBlocks.svg ================== -static const unsigned char temp_binary_data_7[] = +static const unsigned char temp_binary_data_13[] = "\n" "\n" " \n" @@ -1367,10 +1724,10 @@ static const unsigned char temp_binary_data_7[] = " \n" ""; -const char* export_codeBlocks_svg = (const char*) temp_binary_data_7; +const char* export_codeBlocks_svg = (const char*) temp_binary_data_13; //================== export_linux.svg ================== -static const unsigned char temp_binary_data_8[] = +static const unsigned char temp_binary_data_14[] = "\n" "\n" " \n" @@ -1520,10 +1877,10 @@ static const unsigned char temp_binary_data_8[] = " \n" ""; -const char* export_linux_svg = (const char*) temp_binary_data_8; +const char* export_linux_svg = (const char*) temp_binary_data_14; //================== export_visualStudio.svg ================== -static const unsigned char temp_binary_data_9[] = +static const unsigned char temp_binary_data_15[] = "\n" "\n" " \n" @@ -1547,10 +1904,10 @@ static const unsigned char temp_binary_data_9[] = " \n" ""; -const char* export_visualStudio_svg = (const char*) temp_binary_data_9; +const char* export_visualStudio_svg = (const char*) temp_binary_data_15; //================== export_xcode.svg ================== -static const unsigned char temp_binary_data_10[] = +static const unsigned char temp_binary_data_16[] = "\n" "\n" " \n" @@ -1622,10 +1979,10 @@ static const unsigned char temp_binary_data_10[] = " \n" ""; -const char* export_xcode_svg = (const char*) temp_binary_data_10; +const char* export_xcode_svg = (const char*) temp_binary_data_16; //================== huckleberry_icon.svg ================== -static const unsigned char temp_binary_data_11[] = +static const unsigned char temp_binary_data_17[] = "\n" "\n" "\n"; -const char* huckleberry_icon_svg = (const char*) temp_binary_data_11; +const char* huckleberry_icon_svg = (const char*) temp_binary_data_17; //================== juce-logo-with-text.svg ================== -static const unsigned char temp_binary_data_12[] = +static const unsigned char temp_binary_data_18[] = "\n" "\n" "\n"; -const char* jucelogowithtext_svg = (const char*) temp_binary_data_12; +const char* jucelogowithtext_svg = (const char*) temp_binary_data_18; //================== juce_icon.png ================== -static const unsigned char temp_binary_data_13[] = +static const unsigned char temp_binary_data_19[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,0,0,0,2,0,8,6,0,0,0,244,120,212,250,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,3,40,105,84,88,116,88,77,76,58, 99,111,109,46,97,100,111,98,101,46,120,109,112,0,0,0,0,0,60,63,120,112,97,99,107,101,116,32,98,101,103,105,110,61,34,239,187,191,34,32,105,100,61,34,87,53,77,48,77,112,67,101,104,105,72,122,114,101,83,122,78,84,99,122,107,99,57,100,34,63,62,32,60,120, 58,120,109,112,109,101,116,97,32,120,109,108,110,115,58,120,61,34,97,100,111,98,101,58,110,115,58,109,101,116,97,47,34,32,120,58,120,109,112,116,107,61,34,65,100,111,98,101,32,88,77,80,32,67,111,114,101,32,53,46,54,45,99,48,54,55,32,55,57,46,49,53,55, @@ -2475,10 +2832,10 @@ static const unsigned char temp_binary_data_13[] = 0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,128,0,0,0,4,0,0,32,0,0,0,1,0,0,8,0,0,64,0,0,0,2,0,0,16,0,0,128,0,0,0,4,0,0,32,0,0,128,191,246,33,192,0,100,235,173,153,70,62,64, 37,0,0,0,0,73,69,78,68,174,66,96,130,0,0 }; -const char* juce_icon_png = (const char*) temp_binary_data_13; +const char* juce_icon_png = (const char*) temp_binary_data_19; //================== wizard_AnimatedApp.svg ================== -static const unsigned char temp_binary_data_14[] = +static const unsigned char temp_binary_data_20[] = "\n" "\n" "\n" @@ -2655,10 +3012,10 @@ static const unsigned char temp_binary_data_14[] = " id=\"line44\"\n" " style=\"stroke:#a45c94;stroke-opacity:0.94117647\" />"; -const char* wizard_AnimatedApp_svg = (const char*) temp_binary_data_14; +const char* wizard_AnimatedApp_svg = (const char*) temp_binary_data_20; //================== wizard_AudioApp.svg ================== -static const unsigned char temp_binary_data_15[] = +static const unsigned char temp_binary_data_21[] = "\n" "\n" "\n" @@ -3412,10 +3769,10 @@ static const unsigned char temp_binary_data_15[] = " id=\"line131\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_AudioApp_svg = (const char*) temp_binary_data_15; +const char* wizard_AudioApp_svg = (const char*) temp_binary_data_21; //================== wizard_AudioPlugin.svg ================== -static const unsigned char temp_binary_data_16[] = +static const unsigned char temp_binary_data_22[] = "\n" "\n" "\n" @@ -4271,10 +4628,10 @@ static const unsigned char temp_binary_data_16[] = " id=\"circle175\"\n" " style=\"stroke:#a45c94;stroke-opacity:1;fill:#a45c94;fill-opacity:1\" />"; -const char* wizard_AudioPlugin_svg = (const char*) temp_binary_data_16; +const char* wizard_AudioPlugin_svg = (const char*) temp_binary_data_22; //================== wizard_ConsoleApp.svg ================== -static const unsigned char temp_binary_data_17[] = +static const unsigned char temp_binary_data_23[] = "\n" "\n" "\n" @@ -4361,10 +4718,10 @@ static const unsigned char temp_binary_data_17[] = " id=\"path19\"\n" " style=\"stroke:#a45c94;stroke-opacity:1;fill:#a45c94;fill-opacity:1\" />"; -const char* wizard_ConsoleApp_svg = (const char*) temp_binary_data_17; +const char* wizard_ConsoleApp_svg = (const char*) temp_binary_data_23; //================== wizard_DLL.svg ================== -static const unsigned char temp_binary_data_18[] = +static const unsigned char temp_binary_data_24[] = "\n" "\n" "\n" @@ -4635,10 +4992,10 @@ static const unsigned char temp_binary_data_18[] = " id=\"path54\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_DLL_svg = (const char*) temp_binary_data_18; +const char* wizard_DLL_svg = (const char*) temp_binary_data_24; //================== wizard_GUI.svg ================== -static const unsigned char temp_binary_data_19[] = +static const unsigned char temp_binary_data_25[] = "\n" "\n" "\n" @@ -4808,10 +5165,10 @@ static const unsigned char temp_binary_data_19[] = " id=\"path47\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_GUI_svg = (const char*) temp_binary_data_19; +const char* wizard_GUI_svg = (const char*) temp_binary_data_25; //================== wizard_Highlight.svg ================== -static const unsigned char temp_binary_data_20[] = +static const unsigned char temp_binary_data_26[] = "\n" "\n" "\n" @@ -4861,10 +5218,10 @@ static const unsigned char temp_binary_data_20[] = " id=\"path3\"\n" " style=\"fill:#a45c94;fill-opacity:1\" />"; -const char* wizard_Highlight_svg = (const char*) temp_binary_data_20; +const char* wizard_Highlight_svg = (const char*) temp_binary_data_26; //================== wizard_Openfile.svg ================== -static const unsigned char temp_binary_data_21[] = +static const unsigned char temp_binary_data_27[] = "\n" "\n" "\n" @@ -4916,10 +5273,10 @@ static const unsigned char temp_binary_data_21[] = " id=\"path3\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_Openfile_svg = (const char*) temp_binary_data_21; +const char* wizard_Openfile_svg = (const char*) temp_binary_data_27; //================== wizard_OpenGL.svg ================== -static const unsigned char temp_binary_data_22[] = +static const unsigned char temp_binary_data_28[] = "\n" "\n" "\n" @@ -5047,10 +5404,10 @@ static const unsigned char temp_binary_data_22[] = " id=\"path23\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_OpenGL_svg = (const char*) temp_binary_data_22; +const char* wizard_OpenGL_svg = (const char*) temp_binary_data_28; //================== wizard_StaticLibrary.svg ================== -static const unsigned char temp_binary_data_23[] = +static const unsigned char temp_binary_data_29[] = "\n" "\n" "\n" @@ -5321,10 +5678,10 @@ static const unsigned char temp_binary_data_23[] = " id=\"path54\"\n" " style=\"stroke:#a45c94;stroke-opacity:1\" />"; -const char* wizard_StaticLibrary_svg = (const char*) temp_binary_data_23; +const char* wizard_StaticLibrary_svg = (const char*) temp_binary_data_29; //================== jucer_AnimatedComponentSimpleTemplate.h ================== -static const unsigned char temp_binary_data_24[] = +static const unsigned char temp_binary_data_30[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5390,10 +5747,10 @@ static const unsigned char temp_binary_data_24[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_AnimatedComponentSimpleTemplate_h = (const char*) temp_binary_data_24; +const char* jucer_AnimatedComponentSimpleTemplate_h = (const char*) temp_binary_data_30; //================== jucer_AnimatedComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_25[] = +static const unsigned char temp_binary_data_31[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5440,10 +5797,10 @@ static const unsigned char temp_binary_data_25[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_AnimatedComponentTemplate_cpp = (const char*) temp_binary_data_25; +const char* jucer_AnimatedComponentTemplate_cpp = (const char*) temp_binary_data_31; //================== jucer_AnimatedComponentTemplate.h ================== -static const unsigned char temp_binary_data_26[] = +static const unsigned char temp_binary_data_32[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5483,10 +5840,10 @@ static const unsigned char temp_binary_data_26[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_AnimatedComponentTemplate_h = (const char*) temp_binary_data_26; +const char* jucer_AnimatedComponentTemplate_h = (const char*) temp_binary_data_32; //================== jucer_AudioComponentSimpleTemplate.h ================== -static const unsigned char temp_binary_data_27[] = +static const unsigned char temp_binary_data_33[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5590,10 +5947,10 @@ static const unsigned char temp_binary_data_27[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_AudioComponentSimpleTemplate_h = (const char*) temp_binary_data_27; +const char* jucer_AudioComponentSimpleTemplate_h = (const char*) temp_binary_data_33; //================== jucer_AudioComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_28[] = +static const unsigned char temp_binary_data_34[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5678,10 +6035,10 @@ static const unsigned char temp_binary_data_28[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_AudioComponentTemplate_cpp = (const char*) temp_binary_data_28; +const char* jucer_AudioComponentTemplate_cpp = (const char*) temp_binary_data_34; //================== jucer_AudioComponentTemplate.h ================== -static const unsigned char temp_binary_data_29[] = +static const unsigned char temp_binary_data_35[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5723,10 +6080,10 @@ static const unsigned char temp_binary_data_29[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_AudioComponentTemplate_h = (const char*) temp_binary_data_29; +const char* jucer_AudioComponentTemplate_h = (const char*) temp_binary_data_35; //================== jucer_AudioPluginEditorTemplate.cpp ================== -static const unsigned char temp_binary_data_30[] = +static const unsigned char temp_binary_data_36[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5769,10 +6126,10 @@ static const unsigned char temp_binary_data_30[] = " // subcomponents in your editor..\r\n" "}\r\n"; -const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_30; +const char* jucer_AudioPluginEditorTemplate_cpp = (const char*) temp_binary_data_36; //================== jucer_AudioPluginEditorTemplate.h ================== -static const unsigned char temp_binary_data_31[] = +static const unsigned char temp_binary_data_37[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -5808,10 +6165,10 @@ static const unsigned char temp_binary_data_31[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%editor_class_name%%)\r\n" "};\r\n"; -const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_31; +const char* jucer_AudioPluginEditorTemplate_h = (const char*) temp_binary_data_37; //================== jucer_AudioPluginFilterTemplate.cpp ================== -static const unsigned char temp_binary_data_32[] = +static const unsigned char temp_binary_data_38[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6003,10 +6360,10 @@ static const unsigned char temp_binary_data_32[] = " return new %%filter_class_name%%();\r\n" "}\r\n"; -const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_32; +const char* jucer_AudioPluginFilterTemplate_cpp = (const char*) temp_binary_data_38; //================== jucer_AudioPluginFilterTemplate.h ================== -static const unsigned char temp_binary_data_33[] = +static const unsigned char temp_binary_data_39[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6069,10 +6426,10 @@ static const unsigned char temp_binary_data_33[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%filter_class_name%%)\r\n" "};\r\n"; -const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_33; +const char* jucer_AudioPluginFilterTemplate_h = (const char*) temp_binary_data_39; //================== jucer_ComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_34[] = +static const unsigned char temp_binary_data_40[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6148,10 +6505,10 @@ static const unsigned char temp_binary_data_34[] = "//[EndFile] You can add extra defines here...\r\n" "//[/EndFile]\r\n"; -const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_34; +const char* jucer_ComponentTemplate_cpp = (const char*) temp_binary_data_40; //================== jucer_ComponentTemplate.h ================== -static const unsigned char temp_binary_data_35[] = +static const unsigned char temp_binary_data_41[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6214,10 +6571,10 @@ static const unsigned char temp_binary_data_35[] = "//[EndFile] You can add extra defines here...\r\n" "//[/EndFile]\r\n"; -const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_35; +const char* jucer_ComponentTemplate_h = (const char*) temp_binary_data_41; //================== jucer_ContentCompSimpleTemplate.h ================== -static const unsigned char temp_binary_data_36[] = +static const unsigned char temp_binary_data_42[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6275,10 +6632,10 @@ static const unsigned char temp_binary_data_36[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_ContentCompSimpleTemplate_h = (const char*) temp_binary_data_36; +const char* jucer_ContentCompSimpleTemplate_h = (const char*) temp_binary_data_42; //================== jucer_ContentCompTemplate.cpp ================== -static const unsigned char temp_binary_data_37[] = +static const unsigned char temp_binary_data_43[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6317,10 +6674,10 @@ static const unsigned char temp_binary_data_37[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_37; +const char* jucer_ContentCompTemplate_cpp = (const char*) temp_binary_data_43; //================== jucer_ContentCompTemplate.h ================== -static const unsigned char temp_binary_data_38[] = +static const unsigned char temp_binary_data_44[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6357,10 +6714,10 @@ static const unsigned char temp_binary_data_38[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_38; +const char* jucer_ContentCompTemplate_h = (const char*) temp_binary_data_44; //================== jucer_InlineComponentTemplate.h ================== -static const unsigned char temp_binary_data_39[] = +static const unsigned char temp_binary_data_45[] = "//==============================================================================\r\n" "class %%component_class%% : public Component\r\n" "{\r\n" @@ -6402,10 +6759,10 @@ static const unsigned char temp_binary_data_39[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_39; +const char* jucer_InlineComponentTemplate_h = (const char*) temp_binary_data_45; //================== jucer_MainConsoleAppTemplate.cpp ================== -static const unsigned char temp_binary_data_40[] = +static const unsigned char temp_binary_data_46[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6428,10 +6785,10 @@ static const unsigned char temp_binary_data_40[] = " return 0;\r\n" "}\r\n"; -const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_40; +const char* jucer_MainConsoleAppTemplate_cpp = (const char*) temp_binary_data_46; //================== jucer_MainTemplate_NoWindow.cpp ================== -static const unsigned char temp_binary_data_41[] = +static const unsigned char temp_binary_data_47[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6486,10 +6843,10 @@ static const unsigned char temp_binary_data_41[] = "// This macro generates the main() routine that launches the app.\r\n" "START_JUCE_APPLICATION (%%app_class_name%%)\r\n"; -const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_41; +const char* jucer_MainTemplate_NoWindow_cpp = (const char*) temp_binary_data_47; //================== jucer_MainTemplate_SimpleWindow.cpp ================== -static const unsigned char temp_binary_data_42[] = +static const unsigned char temp_binary_data_48[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6596,10 +6953,10 @@ static const unsigned char temp_binary_data_42[] = "// This macro generates the main() routine that launches the app.\r\n" "START_JUCE_APPLICATION (%%app_class_name%%)\r\n"; -const char* jucer_MainTemplate_SimpleWindow_cpp = (const char*) temp_binary_data_42; +const char* jucer_MainTemplate_SimpleWindow_cpp = (const char*) temp_binary_data_48; //================== jucer_MainTemplate_Window.cpp ================== -static const unsigned char temp_binary_data_43[] = +static const unsigned char temp_binary_data_49[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6706,10 +7063,10 @@ static const unsigned char temp_binary_data_43[] = "// This macro generates the main() routine that launches the app.\r\n" "START_JUCE_APPLICATION (%%app_class_name%%)\r\n"; -const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_43; +const char* jucer_MainTemplate_Window_cpp = (const char*) temp_binary_data_49; //================== jucer_NewComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_44[] = +static const unsigned char temp_binary_data_50[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6762,10 +7119,10 @@ static const unsigned char temp_binary_data_44[] = "\r\n" "}\r\n"; -const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_44; +const char* jucer_NewComponentTemplate_cpp = (const char*) temp_binary_data_50; //================== jucer_NewComponentTemplate.h ================== -static const unsigned char temp_binary_data_45[] = +static const unsigned char temp_binary_data_51[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6796,10 +7153,10 @@ static const unsigned char temp_binary_data_45[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_45; +const char* jucer_NewComponentTemplate_h = (const char*) temp_binary_data_51; //================== jucer_NewCppFileTemplate.cpp ================== -static const unsigned char temp_binary_data_46[] = +static const unsigned char temp_binary_data_52[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6812,10 +7169,10 @@ static const unsigned char temp_binary_data_46[] = "\r\n" "%%include_corresponding_header%%\r\n"; -const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_46; +const char* jucer_NewCppFileTemplate_cpp = (const char*) temp_binary_data_52; //================== jucer_NewCppFileTemplate.h ================== -static const unsigned char temp_binary_data_47[] = +static const unsigned char temp_binary_data_53[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6828,10 +7185,10 @@ static const unsigned char temp_binary_data_47[] = "\r\n" "#pragma once\r\n"; -const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_47; +const char* jucer_NewCppFileTemplate_h = (const char*) temp_binary_data_53; //================== jucer_NewInlineComponentTemplate.h ================== -static const unsigned char temp_binary_data_48[] = +static const unsigned char temp_binary_data_54[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6894,10 +7251,10 @@ static const unsigned char temp_binary_data_48[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%component_class%%)\r\n" "};\r\n"; -const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_48; +const char* jucer_NewInlineComponentTemplate_h = (const char*) temp_binary_data_54; //================== jucer_OpenGLComponentSimpleTemplate.h ================== -static const unsigned char temp_binary_data_49[] = +static const unsigned char temp_binary_data_55[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -6974,10 +7331,10 @@ static const unsigned char temp_binary_data_49[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_OpenGLComponentSimpleTemplate_h = (const char*) temp_binary_data_49; +const char* jucer_OpenGLComponentSimpleTemplate_h = (const char*) temp_binary_data_55; //================== jucer_OpenGLComponentTemplate.cpp ================== -static const unsigned char temp_binary_data_50[] = +static const unsigned char temp_binary_data_56[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7035,10 +7392,10 @@ static const unsigned char temp_binary_data_50[] = " // update their positions.\r\n" "}\r\n"; -const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_50; +const char* jucer_OpenGLComponentTemplate_cpp = (const char*) temp_binary_data_56; //================== jucer_OpenGLComponentTemplate.h ================== -static const unsigned char temp_binary_data_51[] = +static const unsigned char temp_binary_data_57[] = "/*\r\n" " ==============================================================================\r\n" "\r\n" @@ -7080,10 +7437,10 @@ static const unsigned char temp_binary_data_51[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%content_component_class%%)\r\n" "};\r\n"; -const char* jucer_OpenGLComponentTemplate_h = (const char*) temp_binary_data_51; +const char* jucer_OpenGLComponentTemplate_h = (const char*) temp_binary_data_57; //================== jucer_PIPAudioProcessorTemplate.h ================== -static const unsigned char temp_binary_data_52[] = +static const unsigned char temp_binary_data_58[] = "class %%class_name%% : public AudioProcessor\r\n" "{\r\n" "public:\r\n" @@ -7192,92 +7549,10 @@ static const unsigned char temp_binary_data_52[] = " JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (%%class_name%%)\r\n" "};\r\n"; -const char* jucer_PIPAudioProcessorTemplate_h = (const char*) temp_binary_data_52; - -//================== jucer_PIPMain.cpp ================== -static const unsigned char temp_binary_data_53[] = -"/*\r\n" -" ==============================================================================\r\n" -"\r\n" -" This file was auto-generated and contains the startup code for a PIP.\r\n" -"\r\n" -" ==============================================================================\r\n" -"*/\r\n" -"\r\n" -"%%include_juce%%\r\n" -"#include \"%%filename%%\"\r\n" -"\r\n" -"%%component_begin%%\r\n" -"class Application : public JUCEApplication\r\n" -"{\r\n" -"public:\r\n" -" //==============================================================================\r\n" -" Application() {}\r\n" -"\r\n" -" const String getApplicationName() override { return \"%%project_name%%\"; }\r\n" -" const String getApplicationVersion() override { return \"%%project_version%%\"; }\r\n" -"\r\n" -" void initialise (const String&) override { %%startup%% }\r\n" -" void shutdown() override { %%shutdown%% }\r\n" -"\r\n" -"private:\r\n" -" class MainWindow : public DocumentWindow\r\n" -" {\r\n" -" public:\r\n" -" MainWindow (const String& name, Component* c, JUCEApplication& a)\r\n" -" : DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel()\r\n" -" .findColour (ResizableWindow::backgroundColourId),\r\n" -" DocumentWindow::allButtons),\r\n" -" app (a)\r\n" -" {\r\n" -" setUsingNativeTitleBar (true);\r\n" -" setContentOwned (c, true);\r\n" -"\r\n" -" #if JUCE_ANDROID || JUCE_IOS\r\n" -" setFullScreen (true);\r\n" -" #else\r\n" -" setResizable (true, false);\r\n" -" setResizeLimits (300, 250, 10000, 10000);\r\n" -" centreWithSize (getWidth(), getHeight());\r\n" -" #endif\r\n" -"\r\n" -" setVisible (true);\r\n" -" }\r\n" -"\r\n" -" void closeButtonPressed() override\r\n" -" {\r\n" -" app.systemRequestedQuit();\r\n" -" }\r\n" -"\r\n" -" private:\r\n" -" JUCEApplication& app;\r\n" -"\r\n" -" //==============================================================================\r\n" -" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)\r\n" -" };\r\n" -"\r\n" -" std::unique_ptr mainWindow;\r\n" -"};\r\n" -"\r\n" -"//==============================================================================\r\n" -"START_JUCE_APPLICATION (Application)\r\n" -"%%component_end%%\r\n" -"\r\n" -"%%audioprocessor_begin%%\r\n" -"//==============================================================================\r\n" -"AudioProcessor* JUCE_CALLTYPE createPluginFilter()\r\n" -"{\r\n" -" return new %%class_name%%();\r\n" -"}\r\n" -"%%audioprocessor_end%%\r\n" -"\r\n" -"%%console_begin%%\r\n" -"%%console_end%%\r\n"; - -const char* jucer_PIPMain_cpp = (const char*) temp_binary_data_53; +const char* jucer_PIPAudioProcessorTemplate_h = (const char*) temp_binary_data_58; //================== jucer_PIPTemplate.h ================== -static const unsigned char temp_binary_data_54[] = +static const unsigned char temp_binary_data_59[] = "/*******************************************************************************\r\n" " The block below describes the properties of this PIP. A PIP is a short snippet\r\n" " of code that can be read by the Projucer and used to generate a JUCE project.\r\n" @@ -7296,196 +7571,10 @@ static const unsigned char temp_binary_data_54[] = "//==============================================================================\r\n" "%%pip_code%%\r\n"; -const char* jucer_PIPTemplate_h = (const char*) temp_binary_data_54; - -//================== jucer_UnityPluginGUIScript.cs ================== -static const unsigned char temp_binary_data_55[] = -"#if UNITY_EDITOR\n" -"\n" -"using UnityEditor;\n" -"using UnityEngine;\n" -"\n" -"using System.Collections.Generic;\n" -"using System.Runtime.InteropServices;\n" -"\n" -"public class %%plugin_class_name%%GUI : IAudioEffectPluginGUI\n" -"{\n" -" public override string Name { get { return \"%%plugin_name%%\"; } }\n" -" public override string Description { get { return \"%%plugin_description%%\"; } }\n" -" public override string Vendor { get { return \"%%plugin_vendor%%\"; } }\n" -"\n" -" //==============================================================================\n" -"\t[DllImport(\"%%plugin_name%%\")] static extern System.IntPtr getRenderCallback();\n" -"\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unityInitialiseTexture (int id, System.IntPtr texture, int width, int height);\n" -"\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unityMouseDown (int id, float x, float y, EventModifiers mods, int button);\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unityMouseDrag (int id, float x, float y, EventModifiers mods, int button);\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unityMouseUp (int id, float x, float y, EventModifiers mods);\n" -"\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unityKeyEvent (int id, KeyCode code, EventModifiers mods, string name);\n" -"\n" -" [DllImport(\"%%plugin_name%%\")] static extern void unitySetScreenBounds (int id, float x, float y, float w, float h);\n" -"\n" -" //==============================================================================\n" -" private class PluginGUIInstance\n" -" {\n" -" public PluginGUIInstance (ref IAudioEffectPlugin plugin, int id)\n" -" {\n" -" instanceID = id;\n" -"\n" -" float[] arr;\n" -" plugin.GetFloatBuffer (\"Editor\", out arr, 1);\n" -" hasEditor = (arr[0] > 0.0f);\n" -" }\n" -"\n" -" public void repaint (Rect r)\n" -" { \n" -" Vector2 newScreenPosition = GUIUtility.GUIToScreenPoint (r.position);\n" -"\n" -" if (bounds != r \n" -" || screenPosition != newScreenPosition)\n" -" {\n" -" screenPosition = newScreenPosition;\n" -" bounds = r;\n" -"\n" -" unitySetScreenBounds (instanceID, screenPosition.x, screenPosition.y, bounds.width, bounds.height);\n" -" setupTexture();\n" -" }\n" -"\n" -"\t\t\tGL.IssuePluginEvent (getRenderCallback(), instanceID);\n" -"\n" -" texture.SetPixels32 (pixels);\n" -" texture.Apply();\n" -"\n" -" EditorGUI.DrawPreviewTexture (bounds, texture);\n" -" }\n" -"\n" -" public bool handleMouseEvent (EventType eventType)\n" -" {\n" -" Vector2 mousePos = Event.current.mousePosition;\n" -" EventModifiers mods = Event.current.modifiers;\n" -"\n" -" if (! bounds.Contains (mousePos))\n" -" return false;\n" -"\n" -" Vector2 relativePos = new Vector2 (mousePos.x - bounds.x, mousePos.y - bounds.y);\n" -"\n" -" if (eventType == EventType.MouseDown) \n" -" {\n" -" unityMouseDown (instanceID, relativePos.x, relativePos.y, mods, Event.current.button);\n" -" GUIUtility.hotControl = GUIUtility.GetControlID (FocusType.Passive);\n" -" }\n" -" else if (eventType == EventType.MouseUp)\n" -" {\n" -" unityMouseUp (instanceID, relativePos.x, relativePos.y, mods);\n" -" GUIUtility.hotControl = 0;\n" -" }\n" -" else if (eventType == EventType.MouseDrag) \n" -" {\n" -" unityMouseDrag (instanceID, relativePos.x, relativePos.y, mods, Event.current.button);\n" -" }\n" -"\n" -" Event.current.Use();\n" -"\n" -" return true;\n" -" }\n" -"\n" -" public void handleKeyEvent (EventType eventType)\n" -" {\n" -" if (eventType == EventType.KeyDown)\n" -" {\n" -" KeyCode code = Event.current.keyCode;\n" -"\n" -" if (code == KeyCode.None)\n" -" return;\n" -"\n" -" EventModifiers mods = Event.current.modifiers;\n" -"\n" -" unityKeyEvent (instanceID, code, mods, code.ToString());\n" -" }\n" -" }\n" -"\n" -" private void setupTexture()\n" -" {\n" -" if (pixelHandle.IsAllocated)\n" -" pixelHandle.Free();\n" -"\n" -" texture = new Texture2D ((int) bounds.width, (int) bounds.height, TextureFormat.ARGB32, false);\n" -"\n" -" pixels = texture.GetPixels32();\n" -" pixelHandle = GCHandle.Alloc (pixels, GCHandleType.Pinned);\n" -"\n" -" unityInitialiseTexture (instanceID, pixelHandle.AddrOfPinnedObject(), texture.width, texture.height);\n" -" }\n" -"\n" -" public int instanceID = -1;\n" -" public bool hasEditor;\n" -"\n" -" private Vector2 screenPosition;\n" -" private Rect bounds;\n" -"\n" -" private Texture2D texture;\n" -" private Color32[] pixels;\n" -" private GCHandle pixelHandle;\n" -" }\n" -" List guis = new List();\n" -"\n" -" private PluginGUIInstance getGUIInstanceForPlugin (ref IAudioEffectPlugin plugin)\n" -" {\n" -" float[] idArray;\n" -" plugin.GetFloatBuffer (\"ID\", out idArray, 1);\n" -"\n" -" int id = (int) idArray[0];\n" -"\n" -" for (int i = 0; i < guis.Count; ++i)\n" -" {\n" -" if (guis[i].instanceID == id)\n" -" return guis[i];\n" -" }\n" -"\n" -" PluginGUIInstance newInstance = new PluginGUIInstance (ref plugin, id);\n" -" guis.Add (newInstance);\n" -"\n" -" return guis[guis.Count - 1];\n" -" }\n" -"\n" -" //==============================================================================\n" -" public override bool OnGUI (IAudioEffectPlugin plugin)\n" -" {\n" -" PluginGUIInstance guiInstance = getGUIInstanceForPlugin (ref plugin);\n" -"\n" -" if (! guiInstance.hasEditor)\n" -" return true;\n" -"\n" -" float[] arr;\n" -" plugin.GetFloatBuffer (\"Size\", out arr, 6);\n" -"\n" -" Rect r = GUILayoutUtility.GetRect (arr[0], arr[1],\n" -" new GUILayoutOption[] { GUILayout.MinWidth (arr[2]), GUILayout.MinHeight (arr[3]),\n" -" GUILayout.MaxWidth (arr[4]), GUILayout.MaxHeight (arr[5]) });\n" -"\n" -" int controlID = GUIUtility.GetControlID (FocusType.Passive);\n" -" Event currentEvent = Event.current;\n" -" EventType currentEventType = currentEvent.GetTypeForControl (controlID);\n" -"\n" -" if (currentEventType == EventType.Repaint)\n" -" guiInstance.repaint (r);\n" -" else if (currentEvent.isMouse)\n" -" guiInstance.handleMouseEvent (currentEventType);\n" -" else if (currentEvent.isKey)\n" -" guiInstance.handleKeyEvent (currentEventType);\n" -"\n" -" return false;\n" -" }\n" -"}\n" -"\n" -"#endif\n"; - -const char* jucer_UnityPluginGUIScript_cs = (const char*) temp_binary_data_55; +const char* jucer_PIPTemplate_h = (const char*) temp_binary_data_59; //================== colourscheme_dark.xml ================== -static const unsigned char temp_binary_data_56[] = +static const unsigned char temp_binary_data_60[] = "\r\n" "\r\n" "\r\n" @@ -7510,10 +7599,10 @@ static const unsigned char temp_binary_data_56[] = " \r\n" "\r\n"; -const char* colourscheme_dark_xml = (const char*) temp_binary_data_56; +const char* colourscheme_dark_xml = (const char*) temp_binary_data_60; //================== colourscheme_light.xml ================== -static const unsigned char temp_binary_data_57[] = +static const unsigned char temp_binary_data_61[] = "\r\n" "\r\n" "\r\n" @@ -7538,16 +7627,16 @@ static const unsigned char temp_binary_data_57[] = " \r\n" "\r\n"; -const char* colourscheme_light_xml = (const char*) temp_binary_data_57; +const char* colourscheme_light_xml = (const char*) temp_binary_data_61; //================== nothingtoseehere.txt ================== -static const unsigned char temp_binary_data_58[] = +static const unsigned char temp_binary_data_62[] = "VUEtMTk3NTkzMTgtNA=="; -const char* nothingtoseehere_txt = (const char*) temp_binary_data_58; +const char* nothingtoseehere_txt = (const char*) temp_binary_data_62; //================== offlinepage.html ================== -static const unsigned char temp_binary_data_59[] = +static const unsigned char temp_binary_data_63[] = "\n" " \n" " \n" @@ -7591,10 +7680,10 @@ static const unsigned char temp_binary_data_59[] = " \n" ""; -const char* offlinepage_html = (const char*) temp_binary_data_59; +const char* offlinepage_html = (const char*) temp_binary_data_63; //================== projucer_EULA.txt ================== -static const unsigned char temp_binary_data_60[] = +static const unsigned char temp_binary_data_64[] = "\r\n" "IMPORTANT NOTICE: PLEASE READ CAREFULLY BEFORE INSTALLING THE SOFTWARE:\r\n" "\r\n" @@ -7758,47 +7847,7 @@ static const unsigned char temp_binary_data_60[] = "\r\n" "10.6. Please note that this License, its subject matter and its formation, are governed by English law. You and we both agree to that the courts of England and Wales will have exclusive jurisdiction.\r\n"; -const char* projucer_EULA_txt = (const char*) temp_binary_data_60; - -//================== RecentFilesMenuTemplate.nib ================== -static const unsigned char temp_binary_data_61[] = -{ 98,112,108,105,115,116,48,48,212,0,1,0,2,0,3,0,4,0,5,0,6,1,53,1,54,88,36,118,101,114,115,105,111,110,88,36,111,98,106,101,99,116,115,89,36,97,114,99,104,105,118,101,114,84,36,116,111,112,18,0,1,134,160,175,16,74,0,7,0,8,0,31,0,35,0,36,0,42,0,46,0,50, -0,53,0,57,0,74,0,77,0,78,0,86,0,87,0,97,0,112,0,113,0,114,0,119,0,120,0,121,0,124,0,128,0,129,0,132,0,143,0,144,0,145,0,149,0,153,0,162,0,163,0,164,0,169,0,173,0,180,0,181,0,182,0,185,0,192,0,193,0,200,0,201,0,208,0,209,0,216,0,217,0,224,0,225,0,226, -0,229,0,230,0,232,0,249,1,11,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,47,1,50,85,36,110,117,108,108,219,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0, -29,95,16,16,78,83,86,105,115,105,98,108,101,87,105,110,100,111,119,115,93,78,83,79,98,106,101,99,116,115,75,101,121,115,86,78,83,82,111,111,116,92,78,83,79,105,100,115,86,97,108,117,101,115,86,36,99,108,97,115,115,90,78,83,79,105,100,115,75,101,121,115, -93,78,83,67,111,110,110,101,99,116,105,111,110,115,95,16,15,78,83,79,98,106,101,99,116,115,86,97,108,117,101,115,95,16,25,78,83,65,99,99,101,115,115,105,98,105,108,105,116,121,67,111,110,110,101,99,116,111,114,115,95,16,23,78,83,65,99,99,101,115,115, -105,98,105,108,105,116,121,79,105,100,115,75,101,121,115,95,16,25,78,83,65,99,99,101,115,115,105,98,105,108,105,116,121,79,105,100,115,86,97,108,117,101,115,128,5,128,9,128,2,128,55,128,73,128,54,128,7,128,53,128,71,128,72,128,72,210,0,13,0,32,0,33,0, -34,91,78,83,67,108,97,115,115,78,97,109,101,128,4,128,3,93,78,83,65,112,112,108,105,99,97,116,105,111,110,210,0,37,0,38,0,39,0,40,90,36,99,108,97,115,115,110,97,109,101,88,36,99,108,97,115,115,101,115,94,78,83,67,117,115,116,111,109,79,98,106,101,99, -116,162,0,39,0,41,88,78,83,79,98,106,101,99,116,210,0,13,0,43,0,44,0,45,90,78,83,46,111,98,106,101,99,116,115,128,6,160,210,0,37,0,38,0,47,0,48,92,78,83,77,117,116,97,98,108,101,83,101,116,163,0,47,0,49,0,41,85,78,83,83,101,116,210,0,13,0,43,0,51,0,52, -128,8,160,210,0,37,0,38,0,54,0,55,94,78,83,77,117,116,97,98,108,101,65,114,114,97,121,163,0,54,0,56,0,41,87,78,83,65,114,114,97,121,210,0,13,0,43,0,58,0,59,128,52,174,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,128,10,128,12, -128,45,128,15,128,39,128,25,128,28,128,30,128,33,128,35,128,43,128,41,128,47,128,50,210,0,13,0,32,0,33,0,76,128,4,128,11,93,78,83,65,112,112,108,105,99,97,116,105,111,110,212,0,79,0,13,0,80,0,81,0,82,0,83,0,84,0,85,91,78,83,77,101,110,117,73,116,101, -109,115,86,78,83,78,97,109,101,87,78,83,84,105,116,108,101,128,14,128,38,128,49,128,13,89,65,77,97,105,110,77,101,110,117,210,0,13,0,43,0,51,0,89,128,8,167,0,63,0,65,0,64,0,71,0,70,0,62,0,72,128,15,128,25,128,39,128,41,128,43,128,45,128,47,216,0,98,0, -99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,111,95,16,17,78,83,75,101,121,69,113,117,105,118,77,111,100,77,97,115,107,86,78,83,77,101,110,117,89,78,83,79,110,73,109,97,103,101,90,78,83,75,101,121,69,113,117,105,118, -93,78,83,77,110,101,109,111,110,105,99,76,111,99,92,78,83,77,105,120,101,100,73,109,97,103,101,18,0,16,0,0,128,12,128,18,128,24,128,17,18,127,255,255,255,128,22,128,16,91,100,101,108,109,101,65,112,112,75,105,116,80,211,0,13,0,115,0,32,0,116,0,117,0, -118,94,78,83,82,101,115,111,117,114,99,101,78,97,109,101,128,21,128,20,128,19,87,78,83,73,109,97,103,101,95,16,15,78,83,77,101,110,117,67,104,101,99,107,109,97,114,107,210,0,37,0,38,0,122,0,123,95,16,16,78,83,67,117,115,116,111,109,82,101,115,111,117, -114,99,101,162,0,122,0,41,211,0,13,0,115,0,32,0,116,0,126,0,118,128,21,128,23,128,19,95,16,16,78,83,77,101,110,117,77,105,120,101,100,83,116,97,116,101,210,0,37,0,38,0,130,0,131,90,78,83,77,101,110,117,73,116,101,109,162,0,130,0,41,218,0,133,0,98,0,134, -0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,135,0,104,0,66,0,61,0,106,0,107,0,108,0,109,0,110,0,142,88,78,83,65,99,116,105,111,110,89,78,83,83,117,98,109,101,110,117,128,27,128,28,128,12,128,18,128,24,128,17,128,22,128,26,84,70,105,108,101,94,115,117,98, -109,101,110,117,65,99,116,105,111,110,58,211,0,79,0,13,0,81,0,146,0,83,0,142,128,29,128,38,128,26,210,0,13,0,43,0,51,0,151,128,8,161,0,67,128,30,218,0,133,0,98,0,134,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,154,0,104,0,68,0,66,0,106,0,107,0,108,0,109, -0,110,0,161,128,32,128,33,128,28,128,18,128,24,128,17,128,22,128,31,91,79,112,101,110,32,82,101,99,101,110,116,94,115,117,98,109,101,110,117,65,99,116,105,111,110,58,212,0,79,0,13,0,80,0,81,0,165,0,83,0,167,0,161,128,34,128,38,128,37,128,31,210,0,13, -0,43,0,51,0,171,128,8,161,0,69,128,35,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,68,0,106,0,107,0,108,0,109,0,110,0,179,128,33,128,18,128,24,128,17,128,22,128,36,90,67,108,101,97,114,32,77,101,110,117,95,16,22,95,78,83,82,101,99,101,110, -116,68,111,99,117,109,101,110,116,115,77,101,110,117,210,0,37,0,38,0,183,0,184,86,78,83,77,101,110,117,162,0,183,0,41,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,191,128,12,128,18,128,24,128,17,128,22,128, -40,84,69,100,105,116,215,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,61,0,106,0,107,0,108,0,109,0,110,0,199,128,12,128,18,128,24,128,17,128,22,128,42,86,70,111,114,109,97,116,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0, -109,0,110,0,207,128,12,128,18,128,24,128,17,128,22,128,44,84,86,105,101,119,216,0,98,0,99,0,100,0,13,0,101,0,102,0,103,0,81,0,104,0,61,0,106,0,107,0,108,0,109,0,110,0,215,128,12,128,18,128,24,128,17,128,22,128,46,86,87,105,110,100,111,119,215,0,99,0, -100,0,13,0,101,0,102,0,103,0,81,0,61,0,106,0,107,0,108,0,109,0,110,0,223,128,12,128,18,128,24,128,17,128,22,128,48,84,72,101,108,112,91,95,78,83,77,97,105,110,77,101,110,117,210,0,13,0,32,0,33,0,228,128,4,128,51,93,78,83,70,111,110,116,77,97,110,97,103, -101,114,210,0,37,0,38,0,56,0,231,162,0,56,0,41,210,0,13,0,43,0,58,0,234,128,52,174,0,22,0,22,0,61,0,61,0,61,0,61,0,65,0,66,0,67,0,68,0,61,0,61,0,61,0,22,128,2,128,2,128,12,128,12,128,12,128,12,128,25,128,28,128,30,128,33,128,12,128,12,128,12,128,2,210, -0,13,0,43,0,58,0,251,128,52,175,16,15,0,22,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,128,2,128,10,128,12,128,45,128,15,128,39,128,25,128,28,128,30,128,33,128,35,128,43,128,41,128,47,128,50,210,0,13,0,43,0,58,1,13,128,52,175, -16,15,1,14,1,15,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,1,28,128,56,128,57,128,58,128,59,128,60,128,61,128,62,128,63,128,64,128,65,128,66,128,67,128,68,128,69,128,70,17,2,22,17,2,23,17,2,24,17,2,25,17,2,26,17,2,27,17,2,28,17,2,29, -17,2,30,17,2,31,17,2,32,17,2,33,17,2,34,17,2,35,17,2,36,210,0,13,0,43,0,51,1,46,128,8,160,210,0,13,0,43,0,58,1,49,128,52,160,210,0,37,0,38,1,51,1,52,94,78,83,73,66,79,98,106,101,99,116,68,97,116,97,162,1,51,0,41,95,16,15,78,83,75,101,121,101,100,65,114, -99,104,105,118,101,114,209,1,55,1,56,93,73,66,46,111,98,106,101,99,116,100,97,116,97,128,1,0,8,0,25,0,34,0,43,0,53,0,58,0,63,0,214,0,220,1,9,1,28,1,42,1,49,1,62,1,69,1,80,1,94,1,112,1,140,1,166,1,194,1,196,1,198,1,200,1,202,1,204,1,206,1,208,1,210,1, -212,1,214,1,216,1,225,1,237,1,239,1,241,1,255,2,8,2,19,2,28,2,43,2,48,2,57,2,66,2,77,2,79,2,80,2,89,2,102,2,109,2,115,2,124,2,126,2,127,2,136,2,151,2,158,2,166,2,175,2,177,2,206,2,208,2,210,2,212,2,214,2,216,2,218,2,220,2,222,2,224,2,226,2,228,2,230, -2,232,2,234,2,243,2,245,2,247,3,5,3,22,3,34,3,41,3,49,3,51,3,53,3,55,3,57,3,67,3,76,3,78,3,93,3,95,3,97,3,99,3,101,3,103,3,105,3,107,3,140,3,160,3,167,3,177,3,188,3,202,3,215,3,220,3,222,3,224,3,226,3,228,3,233,3,235,3,237,3,249,3,250,4,7,4,22,4,24,4, -26,4,28,4,36,4,54,4,63,4,82,4,87,4,100,4,102,4,104,4,106,4,125,4,134,4,145,4,150,4,191,4,200,4,210,4,212,4,214,4,216,4,218,4,220,4,222,4,224,4,226,4,231,4,246,5,3,5,5,5,7,5,9,5,18,5,20,5,23,5,25,5,66,5,68,5,70,5,72,5,74,5,76,5,78,5,80,5,82,5,94,5,109, -5,126,5,128,5,130,5,132,5,134,5,143,5,145,5,148,5,150,5,183,5,185,5,187,5,189,5,191,5,193,5,195,5,206,5,231,5,240,5,247,5,252,6,29,6,31,6,33,6,35,6,37,6,39,6,41,6,46,6,75,6,77,6,79,6,81,6,83,6,85,6,87,6,94,6,127,6,129,6,131,6,133,6,135,6,137,6,139,6, -144,6,177,6,179,6,181,6,183,6,185,6,187,6,189,6,196,6,225,6,227,6,229,6,231,6,233,6,235,6,237,6,242,6,254,7,7,7,9,7,11,7,25,7,34,7,39,7,48,7,50,7,79,7,81,7,83,7,85,7,87,7,89,7,91,7,93,7,95,7,97,7,99,7,101,7,103,7,105,7,107,7,116,7,118,7,151,7,153,7,155, -7,157,7,159,7,161,7,163,7,165,7,167,7,169,7,171,7,173,7,175,7,177,7,179,7,181,7,190,7,192,7,225,7,227,7,229,7,231,7,233,7,235,7,237,7,239,7,241,7,243,7,245,7,247,7,249,7,251,7,253,7,255,8,2,8,5,8,8,8,11,8,14,8,17,8,20,8,23,8,26,8,29,8,32,8,35,8,38,8, -41,8,44,8,53,8,55,8,56,8,65,8,67,8,68,8,77,8,92,8,97,8,115,8,120,8,134,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,136,0,0 }; - -const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_61; +const char* projucer_EULA_txt = (const char*) temp_binary_data_64; const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) @@ -7811,6 +7860,12 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) switch (hash) { + case 0x31d21131: numBytes = 1042; return LaunchScreen_storyboard; + case 0x24e5a04d: numBytes = 477; return PIPAudioProcessor_cpp_in; + case 0xd572ce5a: numBytes = 2162; return PIPComponent_cpp_in; + case 0x1a77c680: numBytes = 299; return PIPConsole_cpp_in; + case 0xa41e649d: numBytes = 2842; return RecentFilesMenuTemplate_nib; + case 0x667fbbb3: numBytes = 6424; return UnityPluginGUIScript_cs_in; case 0x4d6bedc8: numBytes = 53636; return gradlewrapper_jar; case 0x10b04d10: numBytes = 4971; return gradlew; case 0x76cff066: numBytes = 2404; return gradlew_bat; @@ -7864,15 +7919,12 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) case 0x7fbac252: numBytes = 1665; return jucer_OpenGLComponentTemplate_cpp; case 0x491fa0d7: numBytes = 1263; return jucer_OpenGLComponentTemplate_h; case 0xbc050edc: numBytes = 4926; return jucer_PIPAudioProcessorTemplate_h; - case 0xf4ca9e9a: numBytes = 2421; return jucer_PIPMain_cpp; case 0x0b16e320: numBytes = 517; return jucer_PIPTemplate_h; - case 0xcd472557: numBytes = 6433; return jucer_UnityPluginGUIScript_cs; case 0x763d39dc: numBytes = 1050; return colourscheme_dark_xml; case 0xe8b08520: numBytes = 1050; return colourscheme_light_xml; case 0x938e96ec: numBytes = 20; return nothingtoseehere_txt; case 0xf11580d8: numBytes = 1155; return offlinepage_html; case 0xd6bb7d1d: numBytes = 14361; return projucer_EULA_txt; - case 0xa41e649d: numBytes = 2842; return RecentFilesMenuTemplate_nib; default: break; } @@ -7882,6 +7934,12 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) const char* namedResourceList[] = { + "LaunchScreen_storyboard", + "PIPAudioProcessor_cpp_in", + "PIPComponent_cpp_in", + "PIPConsole_cpp_in", + "RecentFilesMenuTemplate_nib", + "UnityPluginGUIScript_cs_in", "gradlewrapper_jar", "gradlew", "gradlew_bat", @@ -7935,19 +7993,22 @@ const char* namedResourceList[] = "jucer_OpenGLComponentTemplate_cpp", "jucer_OpenGLComponentTemplate_h", "jucer_PIPAudioProcessorTemplate_h", - "jucer_PIPMain_cpp", "jucer_PIPTemplate_h", - "jucer_UnityPluginGUIScript_cs", "colourscheme_dark_xml", "colourscheme_light_xml", "nothingtoseehere_txt", "offlinepage_html", - "projucer_EULA_txt", - "RecentFilesMenuTemplate_nib" + "projucer_EULA_txt" }; const char* originalFilenames[] = { + "LaunchScreen.storyboard", + "PIPAudioProcessor.cpp.in", + "PIPComponent.cpp.in", + "PIPConsole.cpp.in", + "RecentFilesMenuTemplate.nib", + "UnityPluginGUIScript.cs.in", "gradle-wrapper.jar", "gradlew", "gradlew.bat", @@ -8001,15 +8062,12 @@ const char* originalFilenames[] = "jucer_OpenGLComponentTemplate.cpp", "jucer_OpenGLComponentTemplate.h", "jucer_PIPAudioProcessorTemplate.h", - "jucer_PIPMain.cpp", "jucer_PIPTemplate.h", - "jucer_UnityPluginGUIScript.cs", "colourscheme_dark.xml", "colourscheme_light.xml", "nothingtoseehere.txt", "offlinepage.html", - "projucer_EULA.txt", - "RecentFilesMenuTemplate.nib" + "projucer_EULA.txt" }; const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8) diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index 85d9f8b033..9cbe060742 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -8,6 +8,24 @@ namespace BinaryData { + extern const char* LaunchScreen_storyboard; + const int LaunchScreen_storyboardSize = 1042; + + extern const char* PIPAudioProcessor_cpp_in; + const int PIPAudioProcessor_cpp_inSize = 477; + + extern const char* PIPComponent_cpp_in; + const int PIPComponent_cpp_inSize = 2162; + + extern const char* PIPConsole_cpp_in; + const int PIPConsole_cpp_inSize = 299; + + extern const char* RecentFilesMenuTemplate_nib; + const int RecentFilesMenuTemplate_nibSize = 2842; + + extern const char* UnityPluginGUIScript_cs_in; + const int UnityPluginGUIScript_cs_inSize = 6424; + extern const char* gradlewrapper_jar; const int gradlewrapper_jarSize = 53636; @@ -167,15 +185,9 @@ namespace BinaryData extern const char* jucer_PIPAudioProcessorTemplate_h; const int jucer_PIPAudioProcessorTemplate_hSize = 4926; - extern const char* jucer_PIPMain_cpp; - const int jucer_PIPMain_cppSize = 2421; - extern const char* jucer_PIPTemplate_h; const int jucer_PIPTemplate_hSize = 517; - extern const char* jucer_UnityPluginGUIScript_cs; - const int jucer_UnityPluginGUIScript_csSize = 6433; - extern const char* colourscheme_dark_xml; const int colourscheme_dark_xmlSize = 1050; @@ -191,11 +203,8 @@ namespace BinaryData extern const char* projucer_EULA_txt; const int projucer_EULA_txtSize = 14361; - extern const char* RecentFilesMenuTemplate_nib; - const int RecentFilesMenuTemplate_nibSize = 2842; - // Number of elements in the namedResourceList and originalFileNames arrays. - const int namedResourceListSize = 62; + const int namedResourceListSize = 65; // Points to the start of a list of resource names. extern const char* namedResourceList[]; diff --git a/extras/Projucer/JuceLibraryCode/JuceHeader.h b/extras/Projucer/JuceLibraryCode/JuceHeader.h index 66b3736678..6a729fdfb7 100644 --- a/extras/Projucer/JuceLibraryCode/JuceHeader.h +++ b/extras/Projucer/JuceLibraryCode/JuceHeader.h @@ -15,6 +15,7 @@ #include "AppConfig.h" #include +#include #include #include #include diff --git a/extras/Projucer/JuceLibraryCode/include_juce_build_tools.cpp b/extras/Projucer/JuceLibraryCode/include_juce_build_tools.cpp new file mode 100644 index 0000000000..37e445f792 --- /dev/null +++ b/extras/Projucer/JuceLibraryCode/include_juce_build_tools.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/extras/Projucer/Projucer.jucer b/extras/Projucer/Projucer.jucer index 624fccba80..5507008446 100644 --- a/extras/Projucer/Projucer.jucer +++ b/extras/Projucer/Projucer.jucer @@ -6,9 +6,9 @@ companyName="ROLI Ltd." companyCopyright="ROLI Ltd." cppLanguageStandard="11"> + microphonePermissionNeeded="1" cameraPermissionNeeded="1" smallIcon="Zrx1Gl"> @@ -24,9 +24,11 @@ + - + @@ -42,9 +44,11 @@ + - + + - + + - + @@ -92,6 +99,7 @@ + @@ -144,131 +152,137 @@ - - - + + + + + + + + - - - + + + - - + - - - - - - - - - - + - - - - - - + + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h b/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h index 32b5f17855..7e7e104f18 100644 --- a/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h +++ b/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h @@ -77,7 +77,7 @@ public: MemoryOutputStream out; out << "static const unsigned char pathData[] = "; - CodeHelpers::writeDataAsCppLiteral (data.getMemoryBlock(), out, false, true); + build_tools::writeDataAsCppLiteral (data.getMemoryBlock(), out, false, true); out << newLine << newLine << "Path path;" << newLine diff --git a/extras/Projucer/Source/Application/jucer_CommandLine.cpp b/extras/Projucer/Source/Application/jucer_CommandLine.cpp index 31d06d2337..69a56096af 100644 --- a/extras/Projucer/Source/Application/jucer_CommandLine.cpp +++ b/extras/Projucer/Source/Application/jucer_CommandLine.cpp @@ -629,11 +629,11 @@ namespace MemoryBlock data; FileInputStream input (source); input.readIntoMemoryBlock (data); - CodeHelpers::writeDataAsCppLiteral (data, literal, true, true); + build_tools::writeDataAsCppLiteral (data, literal, true, true); dataSize = data.getSize(); } - auto variableName = CodeHelpers::makeBinaryDataIdentifierName (source); + auto variableName = build_tools::makeBinaryDataIdentifierName (source); MemoryOutputStream header, cpp; diff --git a/extras/Projucer/Source/Application/jucer_CommonHeaders.h b/extras/Projucer/Source/Application/jucer_CommonHeaders.h index d2798fd84f..5e1333e76b 100644 --- a/extras/Projucer/Source/Application/jucer_CommonHeaders.h +++ b/extras/Projucer/Source/Application/jucer_CommonHeaders.h @@ -57,7 +57,6 @@ typedef TargetOS::OS DependencyPathOS; #include "../Utility/Helpers/jucer_MiscUtilities.h" #include "../Utility/Helpers/jucer_CodeHelpers.h" #include "../Utility/Helpers/jucer_FileHelpers.h" -#include "../Utility/Helpers/jucer_RelativePath.h" #include "../Utility/Helpers/jucer_ValueSourceHelpers.h" #include "../Utility/Helpers/jucer_PresetIDs.h" #include "jucer_CommandIDs.h" diff --git a/extras/Projucer/Source/CodeEditor/jucer_SourceCodeEditor.cpp b/extras/Projucer/Source/CodeEditor/jucer_SourceCodeEditor.cpp index 962285fcde..c99de4c3ae 100644 --- a/extras/Projucer/Source/CodeEditor/jucer_SourceCodeEditor.cpp +++ b/extras/Projucer/Source/CodeEditor/jucer_SourceCodeEditor.cpp @@ -646,7 +646,7 @@ void CppCodeEditorComponent::insertComponentClass() { auto className = aw.getTextEditorContents (classNameField).trim(); - if (className == CodeHelpers::makeValidIdentifier (className, false, true, false)) + if (className == build_tools::makeValidIdentifier (className, false, true, false)) { String code (BinaryData::jucer_InlineComponentTemplate_h); code = code.replace ("%%component_class%%", className); diff --git a/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp b/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp index fcf486a655..4165b29c17 100644 --- a/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp +++ b/extras/Projucer/Source/ComponentEditor/Components/jucer_ComponentTypeHandler.cpp @@ -546,7 +546,7 @@ void ComponentTypeHandler::fillInMemberVariableDeclarations (GeneratedCode& code String clsName (component->getProperties() ["virtualName"].toString()); if (clsName.isNotEmpty()) - clsName = CodeHelpers::makeValidIdentifier (clsName, false, false, true); + clsName = build_tools::makeValidIdentifier (clsName, false, false, true); else clsName = getClassName (component); @@ -584,7 +584,7 @@ void ComponentTypeHandler::fillInCreationCode (GeneratedCode& code, Component* c s << memberVariableName << ".reset (new "; if (virtualName.isNotEmpty()) - s << CodeHelpers::makeValidIdentifier (virtualName, false, false, true); + s << build_tools::makeValidIdentifier (virtualName, false, false, true); else s << getClassName (component); diff --git a/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h b/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h index 8571945314..6199e549b3 100644 --- a/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h +++ b/extras/Projucer/Source/ComponentEditor/Components/jucer_GenericComponentHandler.h @@ -142,7 +142,7 @@ private: void setText (const String& newText) override { document.perform (new GenericCompClassChangeAction (component, *document.getComponentLayout(), - CodeHelpers::makeValidIdentifier (newText, false, false, true)), + build_tools::makeValidIdentifier (newText, false, false, true)), "Change generic component class"); } diff --git a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h index d0587f9fda..4778dbf3fb 100644 --- a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h +++ b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h @@ -369,7 +369,7 @@ private: { if (Project* project = document->getCppDocument().getProject()) { - ResourceFile resourceFile (*project); + JucerResourceFile resourceFile (*project); for (int i = 0; i < resourceFile.getNumFiles(); ++i) { diff --git a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_ImageResourceProperty.h b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_ImageResourceProperty.h index 98ec15589c..0db8615264 100644 --- a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_ImageResourceProperty.h +++ b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_ImageResourceProperty.h @@ -114,7 +114,7 @@ public: if (Project* project = cpp.getProject()) { - ResourceFile resourceFile (*project); + JucerResourceFile resourceFile (*project); for (int i = 0; i < resourceFile.getNumFiles(); ++i) { diff --git a/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h b/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h index 23e941a2ed..e6a5ce33c3 100644 --- a/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h +++ b/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h @@ -732,7 +732,7 @@ struct RelativePositionedRectangle { double x, y, w, h; getRectangleDouble (x, y, w, h, parentArea, layout); - return Point ((float) x, (float) y); + return { (float) x, (float) y }; } void getXY (double& x, double& y, diff --git a/extras/Projucer/Source/ComponentEditor/jucer_BinaryResources.cpp b/extras/Projucer/Source/ComponentEditor/jucer_BinaryResources.cpp index ebfcd6e12c..0fd43116df 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_BinaryResources.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_BinaryResources.cpp @@ -154,7 +154,7 @@ String BinaryResources::browseForResource (const String& title, String BinaryResources::findUniqueName (const String& rootName) const { - auto nameRoot = CodeHelpers::makeValidIdentifier (rootName, true, true, false); + auto nameRoot = build_tools::makeValidIdentifier (rootName, true, true, false); auto name = nameRoot; auto names = getResourceNames(); diff --git a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp index a70b3b9ea3..d97c144e32 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp @@ -411,7 +411,7 @@ Component* ComponentLayout::addNewComponent (ComponentTypeHandler* const type, i std::unique_ptr xml (type->createXmlFor (c.get(), this)); c.reset (addComponentFromXml (*xml, true)); - String memberName (CodeHelpers::makeValidIdentifier (type->getClassName (c.get()), true, true, false)); + String memberName (build_tools::makeValidIdentifier (type->getClassName (c.get()), true, true, false)); setComponentMemberVariableName (c.get(), memberName); selected.selectOnly (c.get()); @@ -852,7 +852,7 @@ String ComponentLayout::getComponentMemberVariableName (Component* comp) const String name (comp->getProperties() ["memberName"].toString()); if (name.isEmpty()) - name = getUnusedMemberName (CodeHelpers::makeValidIdentifier (comp->getName(), true, true, false), comp); + name = getUnusedMemberName (build_tools::makeValidIdentifier (comp->getName(), true, true, false), comp); return name; } @@ -864,7 +864,7 @@ void ComponentLayout::setComponentMemberVariableName (Component* comp, const Str comp->getProperties().set ("memberName", String()); - const String n (getUnusedMemberName (CodeHelpers::makeValidIdentifier (newName, false, true, false), comp)); + const String n (getUnusedMemberName (build_tools::makeValidIdentifier (newName, false, true, false), comp)); comp->getProperties().set ("memberName", n); if (n != oldName) @@ -915,7 +915,7 @@ String ComponentLayout::getComponentVirtualClassName (Component* comp) const void ComponentLayout::setComponentVirtualClassName (Component* comp, const String& newName) { jassert (comp != nullptr); - const String name (CodeHelpers::makeValidIdentifier (newName, false, false, true)); + const String name (build_tools::makeValidIdentifier (newName, false, false, true)); if (name != getComponentVirtualClassName (comp)) { diff --git a/extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp b/extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp index b5297bb156..46a9238cb2 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp @@ -127,7 +127,7 @@ String GeneratedCode::getCallbackDefinitions() const CallbackMethod* const cm = callbacks.getUnchecked(i); const String userCodeBlockName ("User" - + CodeHelpers::makeValidIdentifier (cm->prototype.upToFirstOccurrenceOf ("(", false, false), + + build_tools::makeValidIdentifier (cm->prototype.upToFirstOccurrenceOf ("(", false, false), true, true, false).trim()); if (userCodeBlockName.isNotEmpty() && cm->hasPrePostUserSections) diff --git a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp index c8af270e04..e8ab6a17fb 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp @@ -118,9 +118,9 @@ void JucerDocument::refreshAllPropertyComps() void JucerDocument::setClassName (const String& newName) { if (newName != className - && CodeHelpers::makeValidIdentifier (newName, false, false, true).isNotEmpty()) + && build_tools::makeValidIdentifier (newName, false, false, true).isNotEmpty()) { - className = CodeHelpers::makeValidIdentifier (newName, false, false, true); + className = build_tools::makeValidIdentifier (newName, false, false, true); changed(); } } @@ -156,7 +156,7 @@ void JucerDocument::setParentClasses (const String& classes) type = s = String(); } - s = type + CodeHelpers::makeValidIdentifier (s.trim(), false, false, true, true); + s = type + build_tools::makeValidIdentifier (s.trim(), false, false, true, true); parentClassLines.set (i, s); } diff --git a/extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp b/extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp index f7acc852d4..1413f9cc22 100644 --- a/extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp +++ b/extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp @@ -386,11 +386,12 @@ private: : m->moduleInfo.getFolder(); m->findAndAddCompiledUnits (*exporter, nullptr, compileUnits, - isPluginProject || isVSTHost ? ProjectType::Target::SharedCodeTarget - : ProjectType::Target::unspecified); + isPluginProject || isVSTHost ? build_tools::ProjectType::Target::SharedCodeTarget + : build_tools::ProjectType::Target::unspecified); if (isPluginProject || isVSTHost) - m->findAndAddCompiledUnits (*exporter, nullptr, compileUnits, ProjectType::Target::StandalonePlugIn); + m->findAndAddCompiledUnits (*exporter, nullptr, compileUnits, + build_tools::ProjectType::Target::StandalonePlugIn); } break; diff --git a/extras/Projucer/Source/Project/jucer_Module.cpp b/extras/Projucer/Source/Project/jucer_Module.cpp index db7a9d5686..116926944f 100644 --- a/extras/Projucer/Source/Project/jucer_Module.cpp +++ b/extras/Projucer/Source/Project/jucer_Module.cpp @@ -383,7 +383,7 @@ void LibraryModule::getConfigFlags (Project& project, OwnedArray LibraryModule::getAllCompileUnits (ProjectType::Target::Type forTarget) const +Array LibraryModule::getAllCompileUnits (build_tools::ProjectType::Target::Type forTarget) const { auto files = getFolder().findChildFiles (File::findFiles, false); @@ -470,12 +470,12 @@ Array LibraryModule::getAllCompileUnits (ProjectType if (file.getFileName().startsWithIgnoreCase (getID()) && file.hasFileExtension (sourceFileExtensions)) { - if (forTarget == ProjectType::Target::unspecified + if (forTarget == build_tools::ProjectType::Target::unspecified || forTarget == Project::getTargetTypeFromFilePath (file, true)) { CompileUnit cu; cu.file = file; - units.add (cu); + units.add (std::move (cu)); } } } @@ -486,7 +486,7 @@ Array LibraryModule::getAllCompileUnits (ProjectType cu.isCompiledForNonObjC = ! cu.file.hasFileExtension ("mm;m"); if (cu.isCompiledForNonObjC) - if (files.contains (cu.file.withFileExtension ("mm"))) + if (cu.file.withFileExtension ("mm").existsAsFile()) cu.isCompiledForObjC = false; jassert (cu.isCompiledForObjC || cu.isCompiledForNonObjC); @@ -498,7 +498,7 @@ Array LibraryModule::getAllCompileUnits (ProjectType void LibraryModule::findAndAddCompiledUnits (ProjectExporter& exporter, ProjectSaver* projectSaver, Array& result, - ProjectType::Target::Type forTarget) const + build_tools::ProjectType::Target::Type forTarget) const { for (auto& cu : getAllCompileUnits (forTarget)) { @@ -532,7 +532,7 @@ void LibraryModule::addBrowseableCode (ProjectExporter& exporter, const ArraygetPathForModuleValue (moduleID) = path.toUnixStyle(); diff --git a/extras/Projucer/Source/Project/jucer_Module.h b/extras/Projucer/Source/Project/jucer_Module.h index 9962109629..9d829f58c2 100644 --- a/extras/Projucer/Source/Project/jucer_Module.h +++ b/extras/Projucer/Source/Project/jucer_Module.h @@ -74,16 +74,18 @@ public: struct CompileUnit { File file; - bool isCompiledForObjC, isCompiledForNonObjC; + bool isCompiledForObjC = false, isCompiledForNonObjC = false; bool isNeededForExporter (ProjectExporter&) const; String getFilenameForProxyFile() const; static bool hasSuffix (const File&, const char*); }; - Array getAllCompileUnits (ProjectType::Target::Type forTarget = ProjectType::Target::unspecified) const; + Array getAllCompileUnits (build_tools::ProjectType::Target::Type forTarget = + build_tools::ProjectType::Target::unspecified) const; void findAndAddCompiledUnits (ProjectExporter&, ProjectSaver*, Array& result, - ProjectType::Target::Type forTarget = ProjectType::Target::unspecified) const; + build_tools::ProjectType::Target::Type forTarget = + build_tools::ProjectType::Target::unspecified) const; ModuleDescription moduleInfo; diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 90dc2abc1f..f005462e7e 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -26,7 +26,7 @@ namespace { String makeValid4CC (const String& seed) { - auto s = CodeHelpers::makeValidIdentifier (seed, false, true, false) + "xxxx"; + auto s = build_tools::makeValidIdentifier (seed, false, true, false) + "xxxx"; return s.substring (0, 1).toUpperCase() + s.substring (1, 4).toLowerCase(); @@ -92,7 +92,7 @@ void Project::updateTitleDependencies() pluginNameValue. setDefault (projectName); pluginDescriptionValue. setDefault (projectName); bundleIdentifierValue. setDefault (getDefaultBundleIdentifierString()); - pluginAUExportPrefixValue.setDefault (CodeHelpers::makeValidIdentifier (projectName, false, true, false) + "AU"); + pluginAUExportPrefixValue.setDefault (build_tools::makeValidIdentifier (projectName, false, true, false) + "AU"); pluginAAXIdentifierValue. setDefault (getDefaultAAXIdentifierString()); } @@ -199,7 +199,7 @@ void Project::initialiseProjectValues() companyWebsiteValue.referTo (projectRoot, Ids::companyWebsite, getUndoManager()); companyEmailValue.referTo (projectRoot, Ids::companyEmail, getUndoManager()); - projectTypeValue.referTo (projectRoot, Ids::projectType, getUndoManager(), ProjectType_GUIApp::getTypeName()); + projectTypeValue.referTo (projectRoot, Ids::projectType, getUndoManager(), build_tools::ProjectType_GUIApp::getTypeName()); versionValue.referTo (projectRoot, Ids::version, getUndoManager(), "1.0.0"); bundleIdentifierValue.referTo (projectRoot, Ids::bundleIdentifier, getUndoManager(), getDefaultBundleIdentifierString()); @@ -253,7 +253,7 @@ void Project::initialiseAudioPluginValues() pluginChannelConfigsValue.referTo (projectRoot, Ids::pluginChannelConfigs, getUndoManager()); pluginAAXIdentifierValue.referTo (projectRoot, Ids::aaxIdentifier, getUndoManager(), getDefaultAAXIdentifierString()); pluginAUExportPrefixValue.referTo (projectRoot, Ids::pluginAUExportPrefix, getUndoManager(), - CodeHelpers::makeValidIdentifier (getProjectNameString(), false, true, false) + "AU"); + build_tools::makeValidIdentifier (getProjectNameString(), false, true, false) + "AU"); pluginAUMainTypeValue.referTo (projectRoot, Ids::pluginAUMainType, getUndoManager(), getDefaultAUMainTypes(), ","); pluginAUSandboxSafeValue.referTo (projectRoot, Ids::pluginAUIsSandboxSafe, getUndoManager(), false); @@ -689,7 +689,7 @@ bool Project::saveProjectRootToFile() { MemoryOutputStream mo; xml->writeTo (mo, {}); - return FileHelpers::overwriteFileWithNewDataIfDifferent (getFile(), mo); + return build_tools::overwriteFileWithNewDataIfDifferent (getFile(), mo); } jassertfalse; @@ -769,17 +769,17 @@ File Project::resolveFilename (String filename) const if (filename.isEmpty()) return {}; - filename = replacePreprocessorDefs (getPreprocessorDefs(), filename); + filename = build_tools::replacePreprocessorDefs (getPreprocessorDefs(), filename); #if ! JUCE_WINDOWS if (filename.startsWith ("~")) return File::getSpecialLocation (File::userHomeDirectory).getChildFile (filename.trimCharactersAtStart ("~/")); #endif - if (FileHelpers::isAbsolutePath (filename)) - return File::createFileWithoutCheckingPath (FileHelpers::currentOSStylePath (filename)); // (avoid assertions for windows-style paths) + if (build_tools::isAbsolutePath (filename)) + return File::createFileWithoutCheckingPath (build_tools::currentOSStylePath (filename)); // (avoid assertions for windows-style paths) - return getFile().getSiblingFile (FileHelpers::currentOSStylePath (filename)); + return getFile().getSiblingFile (build_tools::currentOSStylePath (filename)); } String Project::getRelativePathForFile (const File& file) const @@ -800,24 +800,24 @@ String Project::getRelativePathForFile (const File& file) const if (p1.upToFirstOccurrenceOf (File::getSeparatorString(), true, false) .equalsIgnoreCase (p2.upToFirstOccurrenceOf (File::getSeparatorString(), true, false))) { - filename = FileHelpers::getRelativePathFrom (file, relativePathBase); + filename = build_tools::getRelativePathFrom (file, relativePathBase); } return filename; } //============================================================================== -const ProjectType& Project::getProjectType() const +const build_tools::ProjectType& Project::getProjectType() const { - if (auto* type = ProjectType::findType (getProjectTypeString())) + if (auto* type = build_tools::ProjectType::findType (getProjectTypeString())) return *type; - auto* guiType = ProjectType::findType (ProjectType_GUIApp::getTypeName()); + auto* guiType = build_tools::ProjectType::findType (build_tools::ProjectType_GUIApp::getTypeName()); jassert (guiType != nullptr); return *guiType; } -bool Project::shouldBuildTargetType (ProjectType::Target::Type targetType) const noexcept +bool Project::shouldBuildTargetType (build_tools::ProjectType::Target::Type targetType) const noexcept { auto& projectType = getProjectType(); @@ -826,31 +826,31 @@ bool Project::shouldBuildTargetType (ProjectType::Target::Type targetType) const switch (targetType) { - case ProjectType::Target::VSTPlugIn: + case build_tools::ProjectType::Target::VSTPlugIn: return shouldBuildVST(); - case ProjectType::Target::VST3PlugIn: + case build_tools::ProjectType::Target::VST3PlugIn: return shouldBuildVST3(); - case ProjectType::Target::AAXPlugIn: + case build_tools::ProjectType::Target::AAXPlugIn: return shouldBuildAAX(); - case ProjectType::Target::RTASPlugIn: + case build_tools::ProjectType::Target::RTASPlugIn: return shouldBuildRTAS(); - case ProjectType::Target::AudioUnitPlugIn: + case build_tools::ProjectType::Target::AudioUnitPlugIn: return shouldBuildAU(); - case ProjectType::Target::AudioUnitv3PlugIn: + case build_tools::ProjectType::Target::AudioUnitv3PlugIn: return shouldBuildAUv3(); - case ProjectType::Target::StandalonePlugIn: + case build_tools::ProjectType::Target::StandalonePlugIn: return shouldBuildStandalonePlugin(); - case ProjectType::Target::UnityPlugIn: + case build_tools::ProjectType::Target::UnityPlugIn: return shouldBuildUnityPlugin(); - case ProjectType::Target::AggregateTarget: - case ProjectType::Target::SharedCodeTarget: + case build_tools::ProjectType::Target::AggregateTarget: + case build_tools::ProjectType::Target::SharedCodeTarget: return projectType.isAudioPlugin(); - case ProjectType::Target::unspecified: + case build_tools::ProjectType::Target::unspecified: return false; - case ProjectType::Target::GUIApp: - case ProjectType::Target::ConsoleApp: - case ProjectType::Target::StaticLibrary: - case ProjectType::Target::DynamicLibrary: + case build_tools::ProjectType::Target::GUIApp: + case build_tools::ProjectType::Target::ConsoleApp: + case build_tools::ProjectType::Target::StaticLibrary: + case build_tools::ProjectType::Target::DynamicLibrary: default: break; } @@ -858,67 +858,18 @@ bool Project::shouldBuildTargetType (ProjectType::Target::Type targetType) const return true; } -ProjectType::Target::Type Project::getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix) +build_tools::ProjectType::Target::Type Project::getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix) { - if (LibraryModule::CompileUnit::hasSuffix (file, "_AU")) return ProjectType::Target::AudioUnitPlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_AUv3")) return ProjectType::Target::AudioUnitv3PlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_AAX")) return ProjectType::Target::AAXPlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_RTAS")) return ProjectType::Target::RTASPlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST2")) return ProjectType::Target::VSTPlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST3")) return ProjectType::Target::VST3PlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_Standalone")) return ProjectType::Target::StandalonePlugIn; - else if (LibraryModule::CompileUnit::hasSuffix (file, "_Unity")) return ProjectType::Target::UnityPlugIn; + if (LibraryModule::CompileUnit::hasSuffix (file, "_AU")) return build_tools::ProjectType::Target::AudioUnitPlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_AUv3")) return build_tools::ProjectType::Target::AudioUnitv3PlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_AAX")) return build_tools::ProjectType::Target::AAXPlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_RTAS")) return build_tools::ProjectType::Target::RTASPlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST2")) return build_tools::ProjectType::Target::VSTPlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST3")) return build_tools::ProjectType::Target::VST3PlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_Standalone")) return build_tools::ProjectType::Target::StandalonePlugIn; + else if (LibraryModule::CompileUnit::hasSuffix (file, "_Unity")) return build_tools::ProjectType::Target::UnityPlugIn; - return (returnSharedTargetIfNoValidSuffix ? ProjectType::Target::SharedCodeTarget : ProjectType::Target::unspecified); -} - -const char* ProjectType::Target::getName() const noexcept -{ - switch (type) - { - case GUIApp: return "App"; - case ConsoleApp: return "ConsoleApp"; - case StaticLibrary: return "Static Library"; - case DynamicLibrary: return "Dynamic Library"; - case VSTPlugIn: return "VST"; - case VST3PlugIn: return "VST3"; - case AudioUnitPlugIn: return "AU"; - case StandalonePlugIn: return "Standalone Plugin"; - case AudioUnitv3PlugIn: return "AUv3 AppExtension"; - case AAXPlugIn: return "AAX"; - case RTASPlugIn: return "RTAS"; - case UnityPlugIn: return "Unity Plugin"; - case SharedCodeTarget: return "Shared Code"; - case AggregateTarget: return "All"; - case unspecified: - default: return "undefined"; - } -} - -ProjectType::Target::TargetFileType ProjectType::Target::getTargetFileType() const noexcept -{ - switch (type) - { - case GUIApp: return executable; - case ConsoleApp: return executable; - case StaticLibrary: return staticLibrary; - case DynamicLibrary: return sharedLibraryOrDLL; - case VSTPlugIn: return pluginBundle; - case VST3PlugIn: return pluginBundle; - case AudioUnitPlugIn: return pluginBundle; - case StandalonePlugIn: return executable; - case AudioUnitv3PlugIn: return macOSAppex; - case AAXPlugIn: return pluginBundle; - case RTASPlugIn: return pluginBundle; - case UnityPlugIn: return pluginBundle; - case SharedCodeTarget: return staticLibrary; - case AggregateTarget: - case unspecified: - default: - break; - } - - return unknown; + return (returnSharedTargetIfNoValidSuffix ? build_tools::ProjectType::Target::SharedCodeTarget : build_tools::ProjectType::Target::unspecified); } //============================================================================== @@ -990,7 +941,7 @@ void Project::createPropertyEditors (PropertyListBuilder& props) StringArray projectTypeNames; Array projectTypeCodes; - auto types = ProjectType::getAllTypes(); + auto types = build_tools::ProjectType::getAllTypes(); for (int i = 0; i < types.size(); ++i) { @@ -1144,33 +1095,6 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) } //============================================================================== -static StringArray getVersionSegments (const Project& p) -{ - auto segments = StringArray::fromTokens (p.getVersionString(), ",.", ""); - segments.trim(); - segments.removeEmptyStrings(); - return segments; -} - -int Project::getVersionAsHexInteger() const -{ - auto segments = getVersionSegments (*this); - - auto value = (segments[0].getIntValue() << 16) - + (segments[1].getIntValue() << 8) - + segments[2].getIntValue(); - - if (segments.size() > 3) - value = (value << 8) + segments[3].getIntValue(); - - return value; -} - -String Project::getVersionAsHex() const -{ - return "0x" + String::toHexString (getVersionAsHexInteger()); -} - File Project::getBinaryDataCppFile (int index) const { auto cpp = getGeneratedCodeFolder().getChildFile ("BinaryData.cpp"); @@ -1344,11 +1268,11 @@ File Project::Item::getFile() const void Project::Item::setFile (const File& file) { - setFile (RelativePath (project.getRelativePathForFile (file), RelativePath::projectFolder)); + setFile (build_tools::RelativePath (project.getRelativePathForFile (file), build_tools::RelativePath::projectFolder)); jassert (getFile() == file); } -void Project::Item::setFile (const RelativePath& file) +void Project::Item::setFile (const build_tools::RelativePath& file) { jassert (isFile()); state.setProperty (Ids::file, file.toUnixStyle(), getUndoManager()); @@ -1370,7 +1294,7 @@ bool Project::Item::renameFile (const File& newFile) return false; } -bool Project::Item::containsChildForFile (const RelativePath& file) const +bool Project::Item::containsChildForFile (const build_tools::RelativePath& file) const { return state.getChildWithProperty (Ids::file, file.toUnixStyle()).isValid(); } @@ -1610,7 +1534,7 @@ void Project::Item::addFileUnchecked (const File& file, int insertIndex, const b } } -bool Project::Item::addRelativeFile (const RelativePath& file, int insertIndex, bool shouldCompile) +bool Project::Item::addRelativeFile (const build_tools::RelativePath& file, int insertIndex, bool shouldCompile) { Item item (project, ValueTree (Ids::FILE), belongsToModule); item.initialiseMissingProperties(); @@ -1754,8 +1678,8 @@ static String getCompanyNameOrDefault (StringRef str) String Project::getDefaultBundleIdentifierString() const { - return "com." + CodeHelpers::makeValidIdentifier (getCompanyNameOrDefault (getCompanyNameString()), false, true, false) - + "." + CodeHelpers::makeValidIdentifier (getProjectNameString(), false, true, false); + return "com." + build_tools::makeValidIdentifier (getCompanyNameOrDefault (getCompanyNameString()), false, true, false) + + "." + build_tools::makeValidIdentifier (getProjectNameString(), false, true, false); } String Project::getDefaultPluginManufacturerString() const diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index d8d6daf9b8..a7d34ea0c5 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -18,8 +18,6 @@ #pragma once -#include "jucer_ProjectType.h" - class ProjectExporter; class LibraryModule; class EnabledModuleList; @@ -81,7 +79,7 @@ public: Value getProjectValue (const Identifier& name) { return projectRoot.getPropertyAsValue (name, getUndoManagerFor (projectRoot)); } var getProjectVar (const Identifier& name) const { return projectRoot.getProperty (name); } - const ProjectType& getProjectType() const; + const build_tools::ProjectType& getProjectType() const; String getProjectTypeString() const { return projectTypeValue.get(); } void setProjectType (const String& newProjectType) { projectTypeValue = newProjectType; } @@ -92,8 +90,8 @@ public: String getProjectLineFeed() const { return projectLineFeedValue.get(); } String getVersionString() const { return versionValue.get(); } - String getVersionAsHex() const; - int getVersionAsHexInteger() const; + String getVersionAsHex() const { return build_tools::getVersionAsHex (getVersionString()); } + int getVersionAsHexInteger() const { return build_tools::getVersionAsHexInteger (getVersionString()); } void setProjectVersion (const String& newVersion) { versionValue = newVersion; } String getBundleIdentifierString() const { return bundleIdentifierValue.get(); } @@ -217,8 +215,9 @@ public: bool isVST3PluginHost(); //============================================================================== - bool shouldBuildTargetType (ProjectType::Target::Type targetType) const noexcept; - static ProjectType::Target::Type getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix); + bool shouldBuildTargetType ( + build_tools::ProjectType::Target::Type targetType) const noexcept; + static build_tools::ProjectType::Target::Type getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix); //============================================================================== void updateDeprecatedProjectSettingsInteractively(); @@ -258,7 +257,7 @@ public: File getFile() const; String getFilePath() const; void setFile (const File& file); - void setFile (const RelativePath& file); + void setFile (const build_tools::RelativePath& file); File determineGroupFolder() const; bool renameFile (const File& newFile); @@ -295,11 +294,11 @@ public: bool addFileAtIndex (const File& file, int insertIndex, bool shouldCompile); bool addFileRetainingSortOrder (const File& file, bool shouldCompile); void addFileUnchecked (const File& file, int insertIndex, bool shouldCompile); - bool addRelativeFile (const RelativePath& file, int insertIndex, bool shouldCompile); + bool addRelativeFile (const build_tools::RelativePath& file, int insertIndex, bool shouldCompile); void removeItemFromProject(); void sortAlphabetically (bool keepGroupsAtStart, bool recursive); Item findItemForFile (const File& file) const; - bool containsChildForFile (const RelativePath& file) const; + bool containsChildForFile (const build_tools::RelativePath& file) const; Item getParent() const; Item createCopy(); diff --git a/extras/Projucer/Source/Project/jucer_ProjectType.h b/extras/Projucer/Source/Project/jucer_ProjectType.h deleted file mode 100644 index 0bcde8ab8e..0000000000 --- a/extras/Projucer/Source/Project/jucer_ProjectType.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE 6 technical preview. - Copyright (c) 2017 - ROLI Ltd. - - You may use this code under the terms of the GPL v3 - (see www.gnu.org/licenses). - - For this technical preview, this file is not subject to commercial licensing. - - JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER - EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE - DISCLAIMED. - - ============================================================================== -*/ - -#pragma once - -class Project; -class ProjectExporter; - -//============================================================================== -class ProjectType -{ -public: - //============================================================================== - virtual ~ProjectType(); - - const String& getType() const noexcept { return type; } - const String& getDescription() const noexcept { return desc; } - - //============================================================================== - static Array getAllTypes(); - static const ProjectType* findType (const String& typeCode); - - //============================================================================== - virtual bool isStaticLibrary() const { return false; } - virtual bool isDynamicLibrary() const { return false; } - virtual bool isGUIApplication() const { return false; } - virtual bool isCommandLineApp() const { return false; } - virtual bool isAudioPlugin() const { return false; } - - //============================================================================== - struct Target - { - enum Type - { - GUIApp = 0, - ConsoleApp = 1, - StaticLibrary = 2, - DynamicLibrary = 3, - - VSTPlugIn = 10, - VST3PlugIn = 11, - AAXPlugIn = 12, - RTASPlugIn = 13, - AudioUnitPlugIn = 14, - AudioUnitv3PlugIn = 15, - StandalonePlugIn = 16, - UnityPlugIn = 17, - - SharedCodeTarget = 20, // internal - AggregateTarget = 21, - - unspecified = 30 - }; - - enum TargetFileType - { - executable = 0, - staticLibrary = 1, - sharedLibraryOrDLL = 2, - pluginBundle = 3, - macOSAppex = 4, - unknown = 5 - }; - - //============================================================================== - Target (Type targetType) : type (targetType) {} - - const char* getName() const noexcept; - TargetFileType getTargetFileType() const noexcept; - - const Type type; - - private: - //============================================================================== - Target& operator= (const Target&) = delete; - }; - - virtual bool supportsTargetType (Target::Type /*targetType*/) const { return false; } - -protected: - ProjectType (const String& type, const String& desc); - -private: - const String type, desc; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectType) -}; - -//============================================================================== -inline ProjectType::ProjectType (const String& t, const String& d) - : type (t), desc (d) -{ -} - -inline ProjectType::~ProjectType() -{ - getAllTypes().removeFirstMatchingValue (this); -} - -inline const ProjectType* ProjectType::findType (const String& typeCode) -{ - const auto& types = getAllTypes(); - - for (auto i = types.size(); --i >= 0;) - if (types.getUnchecked(i)->getType() == typeCode) - return types.getUnchecked(i); - - jassertfalse; - return nullptr; -} - -//============================================================================== -struct ProjectType_GUIApp : public ProjectType -{ - ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {} - - static const char* getTypeName() noexcept { return "guiapp"; } - bool isGUIApplication() const override { return true; } - bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::GUIApp); } -}; - -struct ProjectType_ConsoleApp : public ProjectType -{ - ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {} - - static const char* getTypeName() noexcept { return "consoleapp"; } - bool isCommandLineApp() const override { return true; } - bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::ConsoleApp); } -}; - -struct ProjectType_StaticLibrary : public ProjectType -{ - ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {} - - static const char* getTypeName() noexcept { return "library"; } - bool isStaticLibrary() const override { return true; } - bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::StaticLibrary); } -}; - -struct ProjectType_DLL : public ProjectType -{ - ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {} - - static const char* getTypeName() noexcept { return "dll"; } - bool isDynamicLibrary() const override { return true; } - bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::DynamicLibrary); } -}; - -struct ProjectType_AudioPlugin : public ProjectType -{ - ProjectType_AudioPlugin() : ProjectType (getTypeName(), "Audio Plug-in") {} - - static const char* getTypeName() noexcept { return "audioplug"; } - bool isAudioPlugin() const override { return true; } - - bool supportsTargetType (Target::Type targetType) const override - { - switch (targetType) - { - case Target::VSTPlugIn: - case Target::VST3PlugIn: - case Target::AAXPlugIn: - case Target::RTASPlugIn: - case Target::AudioUnitPlugIn: - case Target::AudioUnitv3PlugIn: - case Target::StandalonePlugIn: - case Target::UnityPlugIn: - case Target::SharedCodeTarget: - case Target::AggregateTarget: - return true; - case Target::GUIApp: - case Target::ConsoleApp: - case Target::StaticLibrary: - case Target::DynamicLibrary: - case Target::unspecified: - default: - break; - } - - return false; - } -}; - -//============================================================================== -inline Array ProjectType::getAllTypes() -{ - static ProjectType_GUIApp guiApp; - static ProjectType_ConsoleApp consoleApp; - static ProjectType_StaticLibrary staticLib; - static ProjectType_DLL dll; - static ProjectType_AudioPlugin plugin; - - return Array(&guiApp, &consoleApp, &staticLib, &dll, &plugin); -} diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h index b7cf8250ed..f5c1dd0ac5 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h @@ -41,14 +41,14 @@ public: bool canCopeWithDuplicateFiles() override { return false; } bool supportsUserDefinedConfigurations() const override { return true; } - bool supportsTargetType (ProjectType::Target::Type type) const override + bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override { - return type == ProjectType::Target::GUIApp || type == ProjectType::Target::StaticLibrary - || type == ProjectType::Target::DynamicLibrary || type == ProjectType::Target::StandalonePlugIn; + return type == build_tools::ProjectType::Target::GUIApp || type == build_tools::ProjectType::Target::StaticLibrary + || type == build_tools::ProjectType::Target::DynamicLibrary || type == build_tools::ProjectType::Target::StandalonePlugIn; } //============================================================================== - void addPlatformSpecificSettingsForProjectType (const ProjectType&) override + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override { // no-op. } @@ -228,20 +228,20 @@ public: void writeFile (const File& gradleProjectFolder, const String& filePath, const String& fileContent) const { - MemoryOutputStream outStream; - outStream.setNewLineString ("\n"); - - outStream << fileContent; - overwriteFileIfDifferentOrThrow (gradleProjectFolder.getChildFile (filePath), outStream); + build_tools::writeStreamToFile (gradleProjectFolder.getChildFile (filePath), [&] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); + mo << fileContent; + }); } void writeBinaryFile (const File& gradleProjectFolder, const String& filePath, const char* binaryData, const int binarySize) const { - MemoryOutputStream outStream; - outStream.setNewLineString ("\n"); - - outStream.write (binaryData, static_cast (binarySize)); - overwriteFileIfDifferentOrThrow (gradleProjectFolder.getChildFile (filePath), outStream); + build_tools::writeStreamToFile (gradleProjectFolder.getChildFile (filePath), [&] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); + mo.write (binaryData, static_cast (binarySize)); + }); } protected: @@ -330,207 +330,207 @@ protected: private: void writeCmakeFile (const File& file) const { - MemoryOutputStream mo; - mo.setNewLineString ("\n"); - - mo << "# Automatically generated makefile, created by the Projucer" << newLine - << "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine - << newLine; - - mo << "cmake_minimum_required(VERSION 3.4.1)" << newLine << newLine; - - if (! isLibrary()) - mo << "SET(BINARY_NAME \"juce_jni\")" << newLine << newLine; - - auto useOboe = project.getEnabledModules().isModuleEnabled ("juce_audio_devices") && project.isConfigFlagEnabled ("JUCE_USE_ANDROID_OBOE", false); - - if (useOboe) + build_tools::writeStreamToFile (file, [&] (MemoryOutputStream& mo) { - String oboePath (androidOboeRepositoryPath.get().toString().trim().quoted()); + mo.setNewLineString ("\n"); - mo << "SET(OBOE_DIR " << oboePath << ")" << newLine << newLine; - mo << "add_subdirectory (${OBOE_DIR} ./oboe)" << newLine << newLine; - } + mo << "# Automatically generated makefile, created by the Projucer" << newLine + << "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine + << newLine; - String cpufeaturesPath ("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c"); - mo << "add_library(\"cpufeatures\" STATIC \"" << cpufeaturesPath << "\")" << newLine - << "set_source_files_properties(\"" << cpufeaturesPath << "\" PROPERTIES COMPILE_FLAGS \"-Wno-sign-conversion -Wno-gnu-statement-expression\")" << newLine << newLine; + mo << "cmake_minimum_required(VERSION 3.4.1)" << newLine << newLine; - { - auto projectDefines = getEscapedPreprocessorDefs (getProjectPreprocessorDefs()); - if (projectDefines.size() > 0) - mo << "add_definitions(" << projectDefines.joinIntoString (" ") << ")" << newLine << newLine; - } + if (! isLibrary()) + mo << "SET(BINARY_NAME \"juce_jni\")" << newLine << newLine; - { - mo << "include_directories( AFTER" << newLine; - - for (auto& path : extraSearchPaths) - mo << " \"" << escapeDirectoryForCmake (path) << "\"" << newLine; - - mo << " \"${ANDROID_NDK}/sources/android/cpufeatures\"" << newLine; + auto useOboe = project.getEnabledModules().isModuleEnabled ("juce_audio_devices") && project.isConfigFlagEnabled ("JUCE_USE_ANDROID_OBOE", false); if (useOboe) - mo << " \"${OBOE_DIR}/include\"" << newLine; + { + String oboePath (androidOboeRepositoryPath.get().toString().trim().quoted()); + mo << "SET(OBOE_DIR " << oboePath << ")" << newLine << newLine; + mo << "add_subdirectory (${OBOE_DIR} ./oboe)" << newLine << newLine; + } + + String cpufeaturesPath ("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c"); + mo << "add_library(\"cpufeatures\" STATIC \"" << cpufeaturesPath << "\")" << newLine + << "set_source_files_properties(\"" << cpufeaturesPath << "\" PROPERTIES COMPILE_FLAGS \"-Wno-sign-conversion -Wno-gnu-statement-expression\")" << newLine << newLine; + + { + auto projectDefines = getEscapedPreprocessorDefs (getProjectPreprocessorDefs()); + if (projectDefines.size() > 0) + mo << "add_definitions(" << projectDefines.joinIntoString (" ") << ")" << newLine << newLine; + } + + { + mo << "include_directories( AFTER" << newLine; + + for (auto& path : extraSearchPaths) + mo << " \"" << escapeDirectoryForCmake (path) << "\"" << newLine; + + mo << " \"${ANDROID_NDK}/sources/android/cpufeatures\"" << newLine; + + if (useOboe) + mo << " \"${OBOE_DIR}/include\"" << newLine; + + mo << ")" << newLine << newLine; + } + + auto cfgExtraLinkerFlags = getExtraLinkerFlagsString(); + if (cfgExtraLinkerFlags.isNotEmpty()) + { + mo << "SET( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\")" << newLine; + mo << "SET( CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} ${JUCE_LDFLAGS}\")" << newLine << newLine; + } + + mo << "enable_language(ASM)" << newLine << newLine; + + auto userLibraries = StringArray::fromTokens (getExternalLibrariesString(), ";", ""); + userLibraries.addArray (androidLibs); + + if (getNumConfigurations() > 0) + { + bool first = true; + + for (ConstConfigIterator config (*this); config.next();) + { + auto& cfg = dynamic_cast (*config); + auto libSearchPaths = cfg.getLibrarySearchPaths(); + auto cfgDefines = getConfigPreprocessorDefs (cfg); + auto cfgHeaderPaths = cfg.getHeaderSearchPaths(); + auto cfgLibraryPaths = cfg.getLibrarySearchPaths(); + + if (! isLibrary() && libSearchPaths.size() == 0 && cfgDefines.size() == 0 + && cfgHeaderPaths.size() == 0 && cfgLibraryPaths.size() == 0) + continue; + + mo << (first ? "IF" : "ELSEIF") << "(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() <<"\")" << newLine; + + if (isLibrary()) + { + mo << " SET(BINARY_NAME \"" << getNativeModuleBinaryName (cfg) << "\")" << newLine; + + auto binaryLocation = cfg.getTargetBinaryRelativePathString(); + + if (binaryLocation.isNotEmpty()) + { + auto locationRelativeToCmake = build_tools::RelativePath (binaryLocation, build_tools::RelativePath::projectFolder) + .rebased (getProject().getFile().getParentDirectory(), + file.getParentDirectory(), build_tools::RelativePath::buildTargetFolder); + + mo << " SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"" << "../../../../" << locationRelativeToCmake.toUnixStyle() << "\")" << newLine; + } + } + + writeCmakePathLines (mo, " ", "link_directories(", libSearchPaths); + + if (cfgDefines.size() > 0) + mo << " add_definitions(" << getEscapedPreprocessorDefs (cfgDefines).joinIntoString (" ") << ")" << newLine; + + writeCmakePathLines (mo, " ", "include_directories( AFTER", cfgHeaderPaths); + + if (userLibraries.size() > 0) + { + for (auto& lib : userLibraries) + { + String findLibraryCmd; + findLibraryCmd << "find_library(" << lib.toLowerCase().replaceCharacter (L' ', L'_') + << " \"" << lib << "\" PATHS"; + + writeCmakePathLines (mo, " ", findLibraryCmd, cfgLibraryPaths, " NO_CMAKE_FIND_ROOT_PATH)"); + } + + mo << newLine; + } + + if (cfg.isLinkTimeOptimisationEnabled()) + { + // There's no MIPS support for LTO + String mipsCondition ("NOT (ANDROID_ABI STREQUAL \"mips\" OR ANDROID_ABI STREQUAL \"mips64\")"); + mo << " if(" << mipsCondition << ")" << newLine; + StringArray cmakeVariables ("CMAKE_C_FLAGS", "CMAKE_CXX_FLAGS", "CMAKE_EXE_LINKER_FLAGS"); + + for (auto& variable : cmakeVariables) + { + auto configVariable = variable + "_" + cfg.getProductFlavourCMakeIdentifier(); + mo << " SET(" << configVariable << " \"${" << configVariable << "} -flto\")" << newLine; + } + + mo << " ENDIF(" << mipsCondition << ")" << newLine; + } + + first = false; + } + + if (! first) + { + ProjectExporter::BuildConfiguration::Ptr config (getConfiguration(0)); + + if (config) + { + if (auto* cfg = dynamic_cast (config.get())) + { + mo << "ELSE(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg->getProductFlavourCMakeIdentifier() <<"\")" << newLine; + mo << " MESSAGE( FATAL_ERROR \"No matching build-configuration found.\" )" << newLine; + mo << "ENDIF(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg->getProductFlavourCMakeIdentifier() <<"\")" << newLine << newLine; + } + } + } + } + + Array excludeFromBuild; + Array> extraCompilerFlags; + + mo << "add_library( ${BINARY_NAME}" << newLine; + mo << newLine; + mo << " " << (getProject().getProjectType().isStaticLibrary() ? "STATIC" : "SHARED") << newLine; + mo << newLine; + addCompileUnits (mo, excludeFromBuild, extraCompilerFlags); mo << ")" << newLine << newLine; - } - auto cfgExtraLinkerFlags = getExtraLinkerFlagsString(); - if (cfgExtraLinkerFlags.isNotEmpty()) - { - mo << "SET( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\")" << newLine; - mo << "SET( CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} ${JUCE_LDFLAGS}\")" << newLine << newLine; - } - - mo << "enable_language(ASM)" << newLine << newLine; - - auto userLibraries = StringArray::fromTokens (getExternalLibrariesString(), ";", ""); - userLibraries.addArray (androidLibs); - - if (getNumConfigurations() > 0) - { - bool first = true; - - for (ConstConfigIterator config (*this); config.next();) + if (excludeFromBuild.size() > 0) { - auto& cfg = dynamic_cast (*config); - auto libSearchPaths = cfg.getLibrarySearchPaths(); - auto cfgDefines = getConfigPreprocessorDefs (cfg); - auto cfgHeaderPaths = cfg.getHeaderSearchPaths(); - auto cfgLibraryPaths = cfg.getLibrarySearchPaths(); + for (auto& exclude : excludeFromBuild) + mo << "set_source_files_properties(\"" << exclude.toUnixStyle() << "\" PROPERTIES HEADER_FILE_ONLY TRUE)" << newLine; - if (! isLibrary() && libSearchPaths.size() == 0 && cfgDefines.size() == 0 - && cfgHeaderPaths.size() == 0 && cfgLibraryPaths.size() == 0) - continue; - - mo << (first ? "IF" : "ELSEIF") << "(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() <<"\")" << newLine; - - if (isLibrary()) - { - mo << " SET(BINARY_NAME \"" << getNativeModuleBinaryName (cfg) << "\")" << newLine; - - auto binaryLocation = cfg.getTargetBinaryRelativePathString(); - - if (binaryLocation.isNotEmpty()) - { - auto locationRelativeToCmake = RelativePath (binaryLocation, RelativePath::projectFolder) - .rebased (getProject().getFile().getParentDirectory(), - file.getParentDirectory(), RelativePath::buildTargetFolder); - - mo << " SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"" << "../../../../" << locationRelativeToCmake.toUnixStyle() << "\")" << newLine; - } - } - - writeCmakePathLines (mo, " ", "link_directories(", libSearchPaths); - - if (cfgDefines.size() > 0) - mo << " add_definitions(" << getEscapedPreprocessorDefs (cfgDefines).joinIntoString (" ") << ")" << newLine; - - writeCmakePathLines (mo, " ", "include_directories( AFTER", cfgHeaderPaths); - - if (userLibraries.size() > 0) - { - for (auto& lib : userLibraries) - { - String findLibraryCmd; - findLibraryCmd << "find_library(" << lib.toLowerCase().replaceCharacter (L' ', L'_') - << " \"" << lib << "\" PATHS"; - - writeCmakePathLines (mo, " ", findLibraryCmd, cfgLibraryPaths, " NO_CMAKE_FIND_ROOT_PATH)"); - } - - mo << newLine; - } - - if (cfg.isLinkTimeOptimisationEnabled()) - { - // There's no MIPS support for LTO - String mipsCondition ("NOT (ANDROID_ABI STREQUAL \"mips\" OR ANDROID_ABI STREQUAL \"mips64\")"); - mo << " if(" << mipsCondition << ")" << newLine; - StringArray cmakeVariables ("CMAKE_C_FLAGS", "CMAKE_CXX_FLAGS", "CMAKE_EXE_LINKER_FLAGS"); - - for (auto& variable : cmakeVariables) - { - auto configVariable = variable + "_" + cfg.getProductFlavourCMakeIdentifier(); - mo << " SET(" << configVariable << " \"${" << configVariable << "} -flto\")" << newLine; - } - - mo << " ENDIF(" << mipsCondition << ")" << newLine; - } - - first = false; + mo << newLine; } - if (! first) + if (! extraCompilerFlags.isEmpty()) { - ProjectExporter::BuildConfiguration::Ptr config (getConfiguration(0)); + for (auto& extra : extraCompilerFlags) + mo << "set_source_files_properties(\"" << extra.first.toUnixStyle() << "\" PROPERTIES COMPILE_FLAGS " << extra.second << " )" << newLine; - if (config) - { - if (auto* cfg = dynamic_cast (config.get())) - { - mo << "ELSE(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg->getProductFlavourCMakeIdentifier() <<"\")" << newLine; - mo << " MESSAGE( FATAL_ERROR \"No matching build-configuration found.\" )" << newLine; - mo << "ENDIF(JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg->getProductFlavourCMakeIdentifier() <<"\")" << newLine << newLine; - } - } + mo << newLine; } - } - Array excludeFromBuild; - Array> extraCompilerFlags; + auto libraries = getAndroidLibraries(); + if (libraries.size() > 0) + { + for (auto& lib : libraries) + mo << "find_library(" << lib.toLowerCase().replaceCharacter (L' ', L'_') << " \"" << lib << "\")" << newLine; - mo << "add_library( ${BINARY_NAME}" << newLine; - mo << newLine; - mo << " " << (getProject().getProjectType().isStaticLibrary() ? "STATIC" : "SHARED") << newLine; - mo << newLine; - addCompileUnits (mo, excludeFromBuild, extraCompilerFlags); - mo << ")" << newLine << newLine; + mo << newLine; + } - if (excludeFromBuild.size() > 0) - { - for (auto& exclude : excludeFromBuild) - mo << "set_source_files_properties(\"" << exclude.toUnixStyle() << "\" PROPERTIES HEADER_FILE_ONLY TRUE)" << newLine; + libraries.addArray (userLibraries); + mo << "target_link_libraries( ${BINARY_NAME}"; + if (libraries.size() > 0) + { + mo << newLine << newLine; - mo << newLine; - } + for (auto& lib : libraries) + mo << " ${" << lib.toLowerCase().replaceCharacter (L' ', L'_') << "}" << newLine; - if (! extraCompilerFlags.isEmpty()) - { - for (auto& extra : extraCompilerFlags) - mo << "set_source_files_properties(\"" << extra.first.toUnixStyle() << "\" PROPERTIES COMPILE_FLAGS " << extra.second << " )" << newLine; + mo << " \"cpufeatures\"" << newLine; + } - mo << newLine; - } + if (useOboe) + mo << " \"oboe\"" << newLine; - auto libraries = getAndroidLibraries(); - if (libraries.size() > 0) - { - for (auto& lib : libraries) - mo << "find_library(" << lib.toLowerCase().replaceCharacter (L' ', L'_') << " \"" << lib << "\")" << newLine; - - mo << newLine; - } - - libraries.addArray (userLibraries); - mo << "target_link_libraries( ${BINARY_NAME}"; - if (libraries.size() > 0) - { - mo << newLine << newLine; - - for (auto& lib : libraries) - mo << " ${" << lib.toLowerCase().replaceCharacter (L' ', L'_') << "}" << newLine; - - mo << " \"cpufeatures\"" << newLine; - } - - if (useOboe) - mo << " \"oboe\"" << newLine; - - mo << ")" << newLine; - - overwriteFileIfDifferentOrThrow (file, mo); + mo << ")" << newLine; + }); } //============================================================================== @@ -855,7 +855,7 @@ private: { auto appFolder = getTargetFolder().getChildFile ("app"); - RelativePath relativePath (source, appFolder, RelativePath::buildTargetFolder); + build_tools::RelativePath relativePath (source, appFolder, build_tools::RelativePath::buildTargetFolder); javaSourceSets.add (relativePath.toUnixStyle()); } } @@ -926,9 +926,9 @@ private: { auto appFolder = getTargetFolder().getChildFile ("app"); - auto relativePath = RelativePath (folder, RelativePath::projectFolder) + auto relativePath = build_tools::RelativePath (folder, build_tools::RelativePath::projectFolder) .rebased (getProject().getProjectFolder(), appFolder, - RelativePath::buildTargetFolder); + build_tools::RelativePath::buildTargetFolder); sourceSets.add (relativePath.toUnixStyle()); } @@ -1269,34 +1269,33 @@ private: { createDirectoryOrThrow (file.getParentDirectory()); - PNGImageFormat png; + build_tools::writeStreamToFile (file, [&] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); - MemoryOutputStream mo; - mo.setNewLineString ("\n"); + PNGImageFormat png; - if (! png.writeImageToStream (im, mo)) - throw SaveError ("Can't generate Android icon file"); - - overwriteFileIfDifferentOrThrow (file, mo); + if (! png.writeImageToStream (im, mo)) + throw build_tools::SaveError ("Can't generate Android icon file"); + }); } } void writeIcons (const File& folder) const { - std::unique_ptr bigIcon (getBigIcon()); - std::unique_ptr smallIcon (getSmallIcon()); + const auto icons = getIcons(); - if (bigIcon != nullptr && smallIcon != nullptr) + if (icons.big != nullptr && icons.small != nullptr) { - auto step = jmax (bigIcon->getWidth(), bigIcon->getHeight()) / 8; - writeIcon (folder.getChildFile ("drawable-xhdpi/icon.png"), getBestIconForSize (step * 8, false)); - writeIcon (folder.getChildFile ("drawable-hdpi/icon.png"), getBestIconForSize (step * 6, false)); - writeIcon (folder.getChildFile ("drawable-mdpi/icon.png"), getBestIconForSize (step * 4, false)); - writeIcon (folder.getChildFile ("drawable-ldpi/icon.png"), getBestIconForSize (step * 3, false)); + auto step = jmax (icons.big->getWidth(), icons.big->getHeight()) / 8; + writeIcon (folder.getChildFile ("drawable-xhdpi/icon.png"), build_tools::getBestIconForSize (icons, step * 8, false)); + writeIcon (folder.getChildFile ("drawable-hdpi/icon.png"), build_tools::getBestIconForSize (icons, step * 6, false)); + writeIcon (folder.getChildFile ("drawable-mdpi/icon.png"), build_tools::getBestIconForSize (icons, step * 4, false)); + writeIcon (folder.getChildFile ("drawable-ldpi/icon.png"), build_tools::getBestIconForSize (icons, step * 3, false)); } - else if (auto* icon = (bigIcon != nullptr ? bigIcon.get() : smallIcon.get())) + else if (auto* icon = (icons.big != nullptr ? icons.big.get() : icons.small.get())) { - writeIcon (folder.getChildFile ("drawable-mdpi/icon.png"), rescaleImageForIcon (*icon, icon->getWidth())); + writeIcon (folder.getChildFile ("drawable-mdpi/icon.png"), build_tools::rescaleImageForIcon (*icon, icon->getWidth())); } } @@ -1320,7 +1319,7 @@ private: //============================================================================== void addCompileUnits (const Project::Item& projectItem, MemoryOutputStream& mo, - Array& excludeFromBuild, Array>& extraCompilerFlags) const + Array& excludeFromBuild, Array>& extraCompilerFlags) const { if (projectItem.isGroup()) { @@ -1330,7 +1329,7 @@ private: else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this)) { auto f = projectItem.getFile(); - RelativePath file (f, getTargetFolder().getChildFile ("app"), RelativePath::buildTargetFolder); + build_tools::RelativePath file (f, getTargetFolder().getChildFile ("app"), build_tools::RelativePath::buildTargetFolder); auto targetType = getProject().getTargetTypeFromFilePath (f, true); @@ -1338,8 +1337,8 @@ private: if ((! projectItem.shouldBeCompiled()) || (! shouldFileBeCompiledByDefault (f)) || (getProject().isAudioPluginProject() - && targetType != ProjectType::Target::SharedCodeTarget - && targetType != ProjectType::Target::StandalonePlugIn)) + && targetType != build_tools::ProjectType::Target::SharedCodeTarget + && targetType != build_tools::ProjectType::Target::StandalonePlugIn)) { excludeFromBuild.add (file); } @@ -1353,8 +1352,8 @@ private: } } - void addCompileUnits (MemoryOutputStream& mo, Array& excludeFromBuild, - Array>& extraCompilerFlags) const + void addCompileUnits (MemoryOutputStream& mo, Array& excludeFromBuild, + Array>& extraCompilerFlags) const { for (int i = 0; i < getAllGroups().size(); ++i) addCompileUnits (getAllGroups().getReference(i), mo, excludeFromBuild, extraCompilerFlags); @@ -1499,8 +1498,8 @@ private: String escapeDirectoryForCmake (const String& path) const { auto relative = - RelativePath (path, RelativePath::buildTargetFolder) - .rebased (getTargetFolder(), getTargetFolder().getChildFile ("app"), RelativePath::buildTargetFolder); + build_tools::RelativePath (path, build_tools::RelativePath::buildTargetFolder) + .rebased (getTargetFolder(), getTargetFolder().getChildFile ("app"), build_tools::RelativePath::buildTargetFolder); return relative.toUnixStyle(); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h index 501a924d90..c19cc1d914 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h @@ -90,9 +90,9 @@ public: bool isOSX() const override { return false; } bool isiOS() const override { return false; } - bool supportsTargetType (ProjectType::Target::Type) const override { return true; } + bool supportsTargetType (build_tools::ProjectType::Target::Type) const override { return true; } - void addPlatformSpecificSettingsForProjectType (const ProjectType&) override {} + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override {} //============================================================================== bool canLaunchProject() override @@ -160,28 +160,27 @@ public: void create (const OwnedArray&) const override { - MemoryOutputStream out; - out.setNewLineString ("\n"); - - out << "# Automatically generated CMakeLists, created by the Projucer" << newLine - << "# Do not edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine - << newLine; - - out << "cmake_minimum_required (VERSION 3.4.1)" << newLine - << newLine; - - out << "if (NOT CMAKE_BUILD_TYPE)" << newLine - << " set (CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"Choose the type of build.\" FORCE)" << newLine - << "endif (NOT CMAKE_BUILD_TYPE)" << newLine - << newLine; - // We'll append to this later. - overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out); + build_tools::writeStreamToFile (getTargetFolder().getChildFile ("CMakeLists.txt"), [] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); + + mo << "# Automatically generated CMakeLists, created by the Projucer" << newLine + << "# Do not edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine + << newLine; + + mo << "cmake_minimum_required (VERSION 3.4.1)" << newLine + << newLine; + + mo << "if (NOT CMAKE_BUILD_TYPE)" << newLine + << " set (CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"Choose the type of build.\" FORCE)" << newLine + << "endif (NOT CMAKE_BUILD_TYPE)" << newLine + << newLine; + }); // CMake has stopped adding PkgInfo files to bundles, so we need to do it manually - MemoryOutputStream pkgInfoOut; - pkgInfoOut << "BNDL????"; - overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("PkgInfo"), out); + build_tools::writeStreamToFile (getTargetFolder().getChildFile ("PkgInfo"), + [] (MemoryOutputStream& mo) { mo << "BNDL????"; }); } void writeCMakeListsExporterSection (ProjectExporter* exporter) const @@ -218,7 +217,7 @@ public: out << "endif()" << newLine << newLine; - overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out); + build_tools::overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("CMakeLists.txt"), out); } private: @@ -288,7 +287,7 @@ private: return setCMakeVariable (variableName, "${" + variableName + "} " + value); } - static String getTargetVarName (ProjectType::Target& target) + static String getTargetVarName (build_tools::ProjectType::Target& target) { return String (target.getName()).toUpperCase().replaceCharacter (L' ', L'_'); } @@ -306,7 +305,7 @@ private: else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this) && getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType ) { - auto path = RelativePath (projectItem.getFile(), exporter.getTargetFolder(), RelativePath::buildTargetFolder).toUnixStyle(); + auto path = build_tools::RelativePath (projectItem.getFile(), exporter.getTargetFolder(), build_tools::RelativePath::buildTargetFolder).toUnixStyle(); fileInfoList.push_back (std::make_tuple (path, projectItem.shouldBeCompiled(), exporter.compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString())); @@ -318,8 +317,8 @@ private: { for (auto* target : exporter.targets) { - if (target->type == ProjectType::Target::Type::AggregateTarget - || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn) + if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget + || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn) continue; String functionName; @@ -327,29 +326,31 @@ private: switch (target->getTargetFileType()) { - case ProjectType::Target::TargetFileType::executable: + case build_tools::ProjectType::Target::TargetFileType::executable: functionName = "add_executable"; if (exporter.isCodeBlocks() && exporter.isWindows() - && target->type != ProjectType::Target::Type::ConsoleApp) + && target->type != + build_tools::ProjectType::Target::Type::ConsoleApp) properties.add ("WIN32"); break; - case ProjectType::Target::TargetFileType::staticLibrary: - case ProjectType::Target::TargetFileType::sharedLibraryOrDLL: - case ProjectType::Target::TargetFileType::pluginBundle: + case build_tools::ProjectType::Target::TargetFileType::staticLibrary: + case build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL: + case build_tools::ProjectType::Target::TargetFileType::pluginBundle: functionName = "add_library"; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::staticLibrary) + if (target->getTargetFileType() == + build_tools::ProjectType::Target::TargetFileType::staticLibrary) properties.add ("STATIC"); - else if (target->getTargetFileType() == ProjectType::Target::TargetFileType::sharedLibraryOrDLL) + else if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL) properties.add ("SHARED"); else properties.add ("MODULE"); break; - case ProjectType::Target::TargetFileType::macOSAppex: - case ProjectType::Target::TargetFileType::unknown: + case build_tools::ProjectType::Target::TargetFileType::macOSAppex: + case build_tools::ProjectType::Target::TargetFileType::unknown: default: continue; } @@ -368,7 +369,8 @@ private: for (auto& fileInfo : fileInfoList) out << " " << std::get<0> (fileInfo).quoted() << newLine; - auto isCMakeBundle = exporter.isXcode() && target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle; + auto isCMakeBundle = exporter.isXcode() + && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle; auto pkgInfoPath = String ("PkgInfo").quoted(); if (isCMakeBundle) @@ -376,7 +378,8 @@ private: auto xcodeIcnsFilePath = [&] () -> String { - if (exporter.isXcode() && target->getTargetFileType() == ProjectType::Target::TargetFileType::executable) + if (exporter.isXcode() + && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable) { StringArray pathComponents = { "..", "MacOSX", "Icon.icns" }; auto xcodeIcnsFile = getTargetFolder(); @@ -394,7 +397,8 @@ private: if (xcodeIcnsFilePath.isNotEmpty()) out << " " << xcodeIcnsFilePath << newLine; - if (exporter.isCodeBlocks() && target->getTargetFileType() == ProjectType::Target::TargetFileType::executable) + if (exporter.isCodeBlocks() + && target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable) { StringArray pathComponents = { "..", "CodeBlocksWindows", "resources.rc" }; auto windowsRcFile = getTargetFolder(); @@ -455,10 +459,10 @@ private: for (auto* target : exporter.targets) { - if (target->type == ProjectType::Target::Type::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget) continue; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle) out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine; out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->getTargetFileSuffix() << "\")" << newLine @@ -508,7 +512,7 @@ private: for (auto* target : exporter.targets) { - if (target->type == ProjectType::Target::Type::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget) continue; auto targetVarName = getTargetVarName (*target); @@ -552,8 +556,8 @@ private: out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle - || target->type == ProjectType::Target::Type::StandalonePlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle + || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn) out << " SHARED_CODE" << newLine; out << " " << exporter.getArchFlags (config) << newLine; @@ -572,8 +576,8 @@ private: out << ")" << newLine << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle - || target->type == ProjectType::Target::Type::StandalonePlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle + || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn) out << "add_dependencies (" << targetVarName << " " << "SHARED_CODE)" << newLine << newLine; } @@ -607,7 +611,7 @@ private: for (auto* target : exporter.targets) { - if (target->type == ProjectType::Target::Type::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget) continue; out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES PREFIX \"\")" << newLine @@ -637,7 +641,7 @@ private: for (auto* target : exporter.targets) { - if (target->type == ProjectType::Target::Type::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::Type::AggregateTarget) continue; auto targetVarName = getTargetVarName (*target); @@ -674,8 +678,8 @@ private: out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle - || target->type == ProjectType::Target::Type::StandalonePlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle + || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn) out << " SHARED_CODE" << newLine << " -L." << newLine; @@ -721,9 +725,9 @@ private: for (auto* target : exporter.targets) { - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex - || target->type == ProjectType::Target::Type::AggregateTarget - || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex + || target->type == build_tools::ProjectType::Target::Type::AggregateTarget + || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn) continue; auto targetAttributes = target->getTargetSettings (config); @@ -745,19 +749,19 @@ private: for (auto* target : exporter.targets) { - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex - || target->type == ProjectType::Target::Type::AggregateTarget - || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex + || target->type == build_tools::ProjectType::Target::Type::AggregateTarget + || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn) continue; - if (target->type == ProjectType::Target::Type::AudioUnitPlugIn) + if (target->type == build_tools::ProjectType::Target::Type::AudioUnitPlugIn) out << "find_program (RC_COMPILER Rez NO_DEFAULT_PATHS PATHS \"/Applications/Xcode.app/Contents/Developer/usr/bin\")" << newLine << "if (NOT RC_COMPILER)" << newLine << " message (WARNING \"failed to find Rez; older resource-based AU plug-ins may not work correctly\")" << newLine << "endif (NOT RC_COMPILER)" << newLine << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::staticLibrary - || target->getTargetFileType() == ProjectType::Target::TargetFileType::sharedLibraryOrDLL) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::staticLibrary + || target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::sharedLibraryOrDLL) out << "set_target_properties (" << getTargetVarName (*target) << " PROPERTIES SUFFIX \"" << target->xcodeBundleExtension << "\")" << newLine << newLine; } @@ -788,9 +792,9 @@ private: for (auto* target : exporter.targets) { - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::macOSAppex - || target->type == ProjectType::Target::Type::AggregateTarget - || target->type == ProjectType::Target::Type::AudioUnitv3PlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::macOSAppex + || target->type == build_tools::ProjectType::Target::Type::AggregateTarget + || target->type == build_tools::ProjectType::Target::Type::AudioUnitv3PlugIn) continue; auto targetVarName = getTargetVarName (*target); @@ -945,7 +949,7 @@ private: targetAttributeKeys.removeString ("OTHER_LDFLAGS"); } - if (target->type == ProjectType::Target::Type::AudioUnitPlugIn) + if (target->type == build_tools::ProjectType::Target::Type::AudioUnitPlugIn) { String rezFlags; @@ -965,7 +969,7 @@ private: auto sdkVersion = config.getOSXSDKVersionString().upToFirstOccurrenceOf (" ", false, false); auto sysroot = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" + sdkVersion + ".sdk"; - RelativePath rFile ("JuceLibraryCode/include_juce_audio_plugin_client_AU.r", RelativePath::projectFolder); + build_tools::RelativePath rFile ("JuceLibraryCode/include_juce_audio_plugin_client_AU.r", build_tools::RelativePath::projectFolder); rFile = rebaseFromProjectFolderToBuildTarget (rFile); out << "if (RC_COMPILER)" << newLine @@ -1063,13 +1067,13 @@ private: for (auto& key : targetAttributeKeys) out << " XCODE_ATTRIBUTE_" << key << " " << targetAttributes[key] << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::executable - || target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable + || target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle) { out << " MACOSX_BUNDLE_INFO_PLIST " << targetAttributes.getValue ("INFOPLIST_FILE", "\"\"") << newLine << " XCODE_ATTRIBUTE_PRODUCT_NAME " << binaryName.quoted() << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::executable) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::executable) { out << " MACOSX_BUNDLE TRUE" << newLine; } @@ -1085,8 +1089,8 @@ private: out << "target_link_libraries (" << targetVarName << " PRIVATE" << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle - || target->type == ProjectType::Target::Type::StandalonePlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle + || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn) out << " SHARED_CODE" << newLine; for (auto& path : libSearchPaths) @@ -1100,10 +1104,10 @@ private: out << ")" << newLine << newLine; - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle - || target->type == ProjectType::Target::Type::StandalonePlugIn) + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle + || target->type == build_tools::ProjectType::Target::Type::StandalonePlugIn) { - if (target->getTargetFileType() == ProjectType::Target::TargetFileType::pluginBundle + if (target->getTargetFileType() == build_tools::ProjectType::Target::TargetFileType::pluginBundle && targetAttributeKeys.contains("INSTALL_PATH")) { auto installPath = targetAttributes["INSTALL_PATH"].unquoted().replace ("$(HOME)", "$ENV{HOME}"); diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h index 08491d0e5c..07d0c05b5d 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h @@ -101,26 +101,26 @@ public: bool isOSX() const override { return false; } bool isiOS() const override { return false; } - bool supportsTargetType (ProjectType::Target::Type type) const override + bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override { switch (type) { - case ProjectType::Target::StandalonePlugIn: - case ProjectType::Target::GUIApp: - case ProjectType::Target::ConsoleApp: - case ProjectType::Target::StaticLibrary: - case ProjectType::Target::SharedCodeTarget: - case ProjectType::Target::AggregateTarget: - case ProjectType::Target::VSTPlugIn: - case ProjectType::Target::DynamicLibrary: + case build_tools::ProjectType::Target::StandalonePlugIn: + case build_tools::ProjectType::Target::GUIApp: + case build_tools::ProjectType::Target::ConsoleApp: + case build_tools::ProjectType::Target::StaticLibrary: + case build_tools::ProjectType::Target::SharedCodeTarget: + case build_tools::ProjectType::Target::AggregateTarget: + case build_tools::ProjectType::Target::VSTPlugIn: + case build_tools::ProjectType::Target::DynamicLibrary: return true; - case ProjectType::Target::AAXPlugIn: - case ProjectType::Target::RTASPlugIn: - case ProjectType::Target::UnityPlugIn: - case ProjectType::Target::VST3PlugIn: - case ProjectType::Target::AudioUnitPlugIn: - case ProjectType::Target::AudioUnitv3PlugIn: - case ProjectType::Target::unspecified: + case build_tools::ProjectType::Target::AAXPlugIn: + case build_tools::ProjectType::Target::RTASPlugIn: + case build_tools::ProjectType::Target::UnityPlugIn: + case build_tools::ProjectType::Target::VST3PlugIn: + case build_tools::ProjectType::Target::AudioUnitPlugIn: + case build_tools::ProjectType::Target::AudioUnitv3PlugIn: + case build_tools::ProjectType::Target::unspecified: default: break; } @@ -154,19 +154,19 @@ public: } //============================================================================== - void addPlatformSpecificSettingsForProjectType (const ProjectType&) override + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override { // add shared code target first as order matters for Codeblocks - if (shouldBuildTargetType (ProjectType::Target::SharedCodeTarget)) - targets.add (new CodeBlocksTarget (*this, ProjectType::Target::SharedCodeTarget)); + if (shouldBuildTargetType (build_tools::ProjectType::Target::SharedCodeTarget)) + targets.add (new CodeBlocksTarget (*this, build_tools::ProjectType::Target::SharedCodeTarget)); - //ProjectType::Target::SharedCodeTarget - callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) + //resource::ProjectType::Target::SharedCodeTarget + callForAllSupportedTargets ([this] (build_tools::ProjectType::Target::Type targetType) { - if (targetType == ProjectType::Target::SharedCodeTarget) + if (targetType == build_tools::ProjectType::Target::SharedCodeTarget) return; - targets.insert (targetType == ProjectType::Target::AggregateTarget ? 0 : -1, + targets.insert (targetType == build_tools::ProjectType::Target::AggregateTarget ? 0 : -1, new CodeBlocksTarget (*this, targetType)); }); @@ -240,17 +240,18 @@ private: } //============================================================================== - class CodeBlocksTarget : public ProjectType::Target + class CodeBlocksTarget : public build_tools::ProjectType::Target { public: - CodeBlocksTarget (const CodeBlocksProjectExporter& e, ProjectType::Target::Type typeToUse) - : ProjectType::Target (typeToUse), + CodeBlocksTarget (const CodeBlocksProjectExporter& e, + build_tools::ProjectType::Target::Type typeToUse) + : Target (typeToUse), exporter (e) {} String getTargetNameForConfiguration (const BuildConfiguration& config) const { - if (type == ProjectType::Target::AggregateTarget) + if (type == build_tools::ProjectType::Target::AggregateTarget) return config.getName(); return getName() + String (" | ") + config.getName(); @@ -484,8 +485,8 @@ private: { auto librarySearchPaths = config.getLibrarySearchPaths(); - if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget) - librarySearchPaths.add (RelativePath (getSharedCodePath (config), RelativePath::buildTargetFolder).getParentDirectory().toUnixStyle().quoted()); + if (getProject().isAudioPluginProject() && target.type != build_tools::ProjectType::Target::SharedCodeTarget) + librarySearchPaths.add (build_tools::RelativePath (getSharedCodePath (config), build_tools::RelativePath::buildTargetFolder).getParentDirectory().toUnixStyle().quoted()); return librarySearchPaths; } @@ -510,12 +511,12 @@ private: return getCleanedStringArray (paths); } - static int getTypeIndex (const ProjectType::Target::Type& type) + static int getTypeIndex (const build_tools::ProjectType::Target::Type& type) { - if (type == ProjectType::Target::GUIApp || type == ProjectType::Target::StandalonePlugIn) return 0; - if (type == ProjectType::Target::ConsoleApp) return 1; - if (type == ProjectType::Target::StaticLibrary || type == ProjectType::Target::SharedCodeTarget) return 2; - if (type == ProjectType::Target::DynamicLibrary || type == ProjectType::Target::VSTPlugIn) return 3; + if (type == build_tools::ProjectType::Target::GUIApp || type == build_tools::ProjectType::Target::StandalonePlugIn) return 0; + if (type == build_tools::ProjectType::Target::ConsoleApp) return 1; + if (type == build_tools::ProjectType::Target::StaticLibrary || type == build_tools::ProjectType::Target::SharedCodeTarget) return 2; + if (type == build_tools::ProjectType::Target::DynamicLibrary || type == build_tools::ProjectType::Target::VSTPlugIn) return 3; return 0; } @@ -525,8 +526,8 @@ private: String outputPath; if (config.getTargetBinaryRelativePathString().isNotEmpty()) { - RelativePath binaryPath (config.getTargetBinaryRelativePathString(), RelativePath::projectFolder); - binaryPath = binaryPath.rebased (projectFolder, getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath binaryPath (config.getTargetBinaryRelativePathString(), build_tools::RelativePath::projectFolder); + binaryPath = binaryPath.rebased (projectFolder, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); outputPath = config.getTargetBinaryRelativePathString(); } else @@ -539,8 +540,8 @@ private: String getSharedCodePath (const BuildConfiguration& config) const { - auto outputPath = getOutputPathForTarget (getTargetWithType (ProjectType::Target::SharedCodeTarget), config); - RelativePath path (outputPath, RelativePath::buildTargetFolder); + auto outputPath = getOutputPathForTarget (getTargetWithType (build_tools::ProjectType::Target::SharedCodeTarget), config); + build_tools::RelativePath path (outputPath, build_tools::RelativePath::buildTargetFolder); auto filename = path.getFileName(); if (isLinux()) @@ -560,7 +561,7 @@ private: if (isLinux()) { - bool keepPrefix = (target.type == ProjectType::Target::VSTPlugIn); + bool keepPrefix = (target.type == build_tools::ProjectType::Target::VSTPlugIn); output->setAttribute ("prefix_auto", keepPrefix ? 0 : 1); } @@ -578,7 +579,7 @@ private: xml.createNewChildElement ("Option")->setAttribute ("type", getTypeIndex (target.type)); xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc"); - if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget) + if (getProject().isAudioPluginProject() && target.type != build_tools::ProjectType::Target::SharedCodeTarget) xml.createNewChildElement ("Option")->setAttribute ("external_deps", getSharedCodePath (config)); { @@ -612,7 +613,7 @@ private: { auto* linker = xml.createNewChildElement ("Linker"); - if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget) + if (getProject().isAudioPluginProject() && target.type != build_tools::ProjectType::Target::SharedCodeTarget) setAddOption (*linker, "option", getSharedCodePath (config).quoted()); for (auto& flag : getLinkerFlags (config, target)) @@ -624,7 +625,8 @@ private: setAddOption (*linker, "library", lib); for (auto& path : getLinkerSearchPaths (config, target)) - setAddOption (*linker, "directory", replacePreprocessorDefs (getAllPreprocessorDefs(), path)); + setAddOption (*linker, "directory", + build_tools::replacePreprocessorDefs (getAllPreprocessorDefs(), path)); } } @@ -634,7 +636,7 @@ private: for (ConstConfigIterator config (*this); config.next();) for (auto target : targets) - if (target->type != ProjectType::Target::AggregateTarget) + if (target->type != build_tools::ProjectType::Target::AggregateTarget) createBuildTarget (*build->createNewChildElement ("Target"), *target, *config); } @@ -647,12 +649,12 @@ private: StringArray allTargets; for (auto target : targets) - if (target->type != ProjectType::Target::AggregateTarget) + if (target->type != build_tools::ProjectType::Target::AggregateTarget) allTargets.add (target->getTargetNameForConfiguration (*config)); for (auto target : targets) { - if (target->type == ProjectType::Target::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::AggregateTarget) { auto* configTarget = virtualTargets->createNewChildElement ("Add"); @@ -688,7 +690,7 @@ private: result = getCleanedStringArray (result); for (auto& option : result) - option = replacePreprocessorDefs (getAllPreprocessorDefs(), option); + option = build_tools::replacePreprocessorDefs (getAllPreprocessorDefs(), option); return result; } @@ -701,7 +703,7 @@ private: setAddOption (*linker, "library", lib); } - CodeBlocksTarget& getTargetWithType (ProjectType::Target::Type type) const + CodeBlocksTarget& getTargetWithType (build_tools::ProjectType::Target::Type type) const { CodeBlocksTarget* nonAggregrateTarget = nullptr; @@ -710,7 +712,7 @@ private: if (target->type == type) return *target; - if (target->type != ProjectType::Target::AggregateTarget) + if (target->type != build_tools::ProjectType::Target::AggregateTarget) nonAggregrateTarget = target; } @@ -725,10 +727,10 @@ private: CodeBlocksTarget& getMainTarget() const { if (getProject().isAudioPluginProject()) - return getTargetWithType (ProjectType::Target::SharedCodeTarget); + return getTargetWithType (build_tools::ProjectType::Target::SharedCodeTarget); for (auto* target : targets) - if (target->type != ProjectType::Target::AggregateTarget) + if (target->type != build_tools::ProjectType::Target::AggregateTarget) return *target; jassertfalse; @@ -741,7 +743,7 @@ private: if (getProject().isAudioPluginProject()) { if (! projectItem.shouldBeCompiled()) - return getTargetWithType (ProjectType::Target::SharedCodeTarget); + return getTargetWithType (build_tools::ProjectType::Target::SharedCodeTarget); return getTargetWithType (getProject().getTargetTypeFromFilePath (projectItem.getFile(), true)); } @@ -758,7 +760,7 @@ private: } else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this)) { - RelativePath file (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath file (projectItem.getFile(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder); auto* unit = xml.createNewChildElement ("Unit"); unit->setAttribute ("filename", file.toUnixStyle()); @@ -802,8 +804,8 @@ private: if (hasResourceFile()) { - auto iconFile = getTargetFolder().getChildFile ("icon.ico"); - MSVCProjectExporterBase::writeIconFile (*this, iconFile); + const auto iconFile = getTargetFolder().getChildFile ("icon.ico"); + build_tools::writeMacIcon (getIcons(), iconFile); auto rcFile = getTargetFolder().getChildFile ("resources.rc"); MSVCProjectExporterBase::createRCFile (project, iconFile, rcFile); diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h index 37db3b3bd3..abb6b5f492 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h @@ -81,12 +81,10 @@ public: if (auto* target = targets[i]) target->writeProjectFile(); + build_tools::writeStreamToFile (getSLNFile(), [&] (MemoryOutputStream& mo) { - MemoryOutputStream mo; writeSolutionFile (mo, "11.00", getSolutionComment()); - - overwriteFileIfDifferentOrThrow (getSLNFile(), mo); - } + }); } //============================================================================== @@ -348,11 +346,11 @@ public: }; //============================================================================== - class MSVCTargetBase : public ProjectType::Target + class MSVCTargetBase : public build_tools::ProjectType::Target { public: - MSVCTargetBase (ProjectType::Target::Type targetType, const MSVCProjectExporterBase& exporter) - : ProjectType::Target (targetType), owner (exporter) + MSVCTargetBase (build_tools::ProjectType::Target::Type targetType, const MSVCProjectExporterBase& exporter) + : build_tools::ProjectType::Target (targetType), owner (exporter) { projectGuid = createGUID (owner.getProject().getProjectUIDString() + getName()); } @@ -459,7 +457,7 @@ public: { auto* outdir = props->createNewChildElement ("OutDir"); setConditionAttribute (*outdir, config); - outdir->addTextElement (FileHelpers::windowsStylePath (getConfigTargetPath (config)) + "\\"); + outdir->addTextElement (build_tools::windowsStylePath (getConfigTargetPath (config)) + "\\"); } { @@ -470,7 +468,7 @@ public: if (! intermediatesPath.endsWithChar (L'\\')) intermediatesPath += L'\\'; - intdir->addTextElement (FileHelpers::windowsStylePath (intermediatesPath)); + intdir->addTextElement (build_tools::windowsStylePath (intermediatesPath)); } @@ -646,13 +644,13 @@ public: } auto manifestFile = getOwner().getManifestPath(); - if (manifestFile.getRoot() != RelativePath::unknown) + if (manifestFile.getRoot() != build_tools::RelativePath::unknown) { auto* bsc = group->createNewChildElement ("Manifest"); bsc->createNewChildElement ("AdditionalManifestFiles") ->addTextElement (manifestFile.rebased (getOwner().getProject().getFile().getParentDirectory(), getOwner().getTargetFolder(), - RelativePath::buildTargetFolder).toWindowsStyle()); + build_tools::RelativePath::buildTargetFolder).toWindowsStyle()); } if (getTargetFileType() == staticLibrary && ! config.is64Bit()) @@ -739,9 +737,9 @@ public: else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (getOwner()) && getOwner().getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType) { - RelativePath path (projectItem.getFile(), getOwner().getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath path (projectItem.getFile(), getOwner().getTargetFolder(), build_tools::RelativePath::buildTargetFolder); - jassert (path.getRoot() == RelativePath::buildTargetFolder); + jassert (path.getRoot() == build_tools::RelativePath::buildTargetFolder); if (path.hasFileExtension (cOrCppFileExtensions) || path.hasFileExtension (asmFileExtensions)) { @@ -791,7 +789,7 @@ public: e->createNewChildElement ("UniqueIdentifier")->addTextElement (createGUID (path + "_guidpathsaltxhsdf")); } - void addFileToFilter (const RelativePath& file, const String& groupPath, + void addFileToFilter (const build_tools::RelativePath& file, const String& groupPath, XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles) const { XmlElement* e = nullptr; @@ -803,7 +801,7 @@ public: else e = otherFiles.createNewChildElement ("None"); - jassert (file.getRoot() == RelativePath::buildTargetFolder); + jassert (file.getRoot() == build_tools::RelativePath::buildTargetFolder); e->setAttribute ("Include", file.toWindowsStyle()); e->createNewChildElement ("Filter")->addTextElement (groupPath); } @@ -830,9 +828,11 @@ public: } else if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (getOwner())) { - RelativePath relativePath (projectItem.getFile(), getOwner().getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath relativePath (projectItem.getFile(), + getOwner().getTargetFolder(), + build_tools::RelativePath::buildTargetFolder); - jassert (relativePath.getRoot() == RelativePath::buildTargetFolder); + jassert (relativePath.getRoot() == build_tools::RelativePath::buildTargetFolder); if (getOwner().getProject().getTargetTypeFromFilePath (projectItem.getFile(), true) == targetType && (targetType == SharedCodeTarget || projectItem.shouldBeCompiled())) @@ -845,7 +845,7 @@ public: return false; } - bool addFilesToFilter (const Array& files, const String& path, + bool addFilesToFilter (const Array& files, const String& path, XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles, XmlElement& groups) { if (files.size() > 0) @@ -923,12 +923,14 @@ public: if (binaryPath.isEmpty()) return "$(SolutionDir)$(Platform)\\$(Configuration)"; - RelativePath binaryRelPath (binaryPath, RelativePath::projectFolder); + build_tools::RelativePath binaryRelPath (binaryPath, build_tools::RelativePath::projectFolder); if (binaryRelPath.isAbsolute()) return binaryRelPath.toWindowsStyle(); - return prependDot (binaryRelPath.rebased (getOwner().projectFolder, getOwner().getTargetFolder(), RelativePath::buildTargetFolder) + return prependDot (binaryRelPath.rebased (getOwner().projectFolder, + getOwner().getTargetFolder(), + build_tools::RelativePath::buildTargetFolder) .toWindowsStyle()); } @@ -1025,15 +1027,15 @@ public: } //============================================================================== - RelativePath getAAXIconFile() const + build_tools::RelativePath getAAXIconFile() const { - RelativePath aaxSDK (owner.getAAXPathString(), RelativePath::projectFolder); - RelativePath projectIcon ("icon.ico", RelativePath::buildTargetFolder); + build_tools::RelativePath aaxSDK (owner.getAAXPathString(), build_tools::RelativePath::projectFolder); + build_tools::RelativePath projectIcon ("icon.ico", build_tools::RelativePath::buildTargetFolder); if (getOwner().getTargetFolder().getChildFile ("icon.ico").existsAsFile()) return projectIcon.rebased (getOwner().getTargetFolder(), getOwner().getProject().getProjectFolder(), - RelativePath::projectFolder); + build_tools::RelativePath::projectFolder); return aaxSDK.getChildFile ("Utilities").getChildFile ("PlugIn.ico"); } @@ -1042,10 +1044,10 @@ public: { if (type == AAXPlugIn) { - RelativePath aaxSDK (owner.getAAXPathString(), RelativePath::projectFolder); - RelativePath aaxLibsFolder = aaxSDK.getChildFile ("Libs"); - RelativePath bundleScript = aaxSDK.getChildFile ("Utilities").getChildFile ("CreatePackage.bat"); - RelativePath iconFilePath = getAAXIconFile(); + build_tools::RelativePath aaxSDK (owner.getAAXPathString(), build_tools::RelativePath::projectFolder); + build_tools::RelativePath aaxLibsFolder = aaxSDK.getChildFile ("Libs"); + build_tools::RelativePath bundleScript = aaxSDK.getChildFile ("Utilities").getChildFile ("CreatePackage.bat"); + build_tools::RelativePath iconFilePath = getAAXIconFile(); auto outputFilename = config.getOutputFilename (".aaxplugin", true, false); auto bundleDir = getOwner().getOutDirFile (config, outputFilename); @@ -1064,9 +1066,9 @@ public: } else if (type == UnityPlugIn) { - RelativePath scriptPath (config.project.getGeneratedCodeFolder().getChildFile (config.project.getUnityScriptName()), - getOwner().getTargetFolder(), - RelativePath::projectFolder); + build_tools::RelativePath scriptPath (config.project.getGeneratedCodeFolder().getChildFile (config.project.getUnityScriptName()), + getOwner().getTargetFolder(), + build_tools::RelativePath::projectFolder); auto pkgScript = String ("copy /Y ") + scriptPath.toWindowsStyle().quoted() + " \"$(OutDir)\""; @@ -1131,12 +1133,12 @@ public: { if (type == AAXPlugIn) { - auto aaxLibsFolder = RelativePath (owner.getAAXPathString(), RelativePath::projectFolder).getChildFile ("Libs"); + auto aaxLibsFolder = build_tools::RelativePath (owner.getAAXPathString(), build_tools::RelativePath::projectFolder).getChildFile ("Libs"); defines.set ("JucePlugin_AAXLibs_path", createRebasedPath (aaxLibsFolder)); } else if (type == RTASPlugIn) { - RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); + build_tools::RelativePath rtasFolder (owner.getRTASPathString(), build_tools::RelativePath::projectFolder); defines.set ("JucePlugin_WinBag_path", createRebasedPath (rtasFolder.getChildFile ("WinBag"))); } } @@ -1154,7 +1156,7 @@ public: StringArray searchPaths; if (type == RTASPlugIn) { - RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); + build_tools::RelativePath rtasFolder (owner.getRTASPathString(), build_tools::RelativePath::projectFolder); static const char* p[] = { "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses", "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses", @@ -1252,12 +1254,12 @@ public: auto& exp = getOwner(); auto moduleDefPath - = RelativePath (exp.getPathForModuleString ("juce_audio_plugin_client"), RelativePath::projectFolder) + = build_tools::RelativePath (exp.getPathForModuleString ("juce_audio_plugin_client"), build_tools::RelativePath::projectFolder) .getChildFile ("juce_audio_plugin_client").getChildFile ("RTAS").getChildFile ("juce_RTAS_WinExports.def"); return prependDot (moduleDefPath.rebased (exp.getProject().getProjectFolder(), - exp.getTargetFolder(), - RelativePath::buildTargetFolder).toWindowsStyle()); + exp.getTargetFolder(), + build_tools::RelativePath::buildTargetFolder).toWindowsStyle()); } return {}; @@ -1266,7 +1268,7 @@ public: File getVCProjFile() const { return getOwner().getProjectFile (getProjectFileSuffix(), getName()); } File getVCProjFiltersFile() const { return getOwner().getProjectFile (getFiltersFileSuffix(), getName()); } - String createRebasedPath (const RelativePath& path) const { return getOwner().createRebasedPath (path); } + String createRebasedPath (const build_tools::RelativePath& path) const { return getOwner().createRebasedPath (path); } void addWindowsTargetPlatformToConfig (XmlElement& e) const { @@ -1308,26 +1310,26 @@ public: bool isOSX() const override { return false; } bool isiOS() const override { return false; } - bool supportsTargetType (ProjectType::Target::Type type) const override + bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override { switch (type) { - case ProjectType::Target::StandalonePlugIn: - case ProjectType::Target::GUIApp: - case ProjectType::Target::ConsoleApp: - case ProjectType::Target::StaticLibrary: - case ProjectType::Target::SharedCodeTarget: - case ProjectType::Target::AggregateTarget: - case ProjectType::Target::VSTPlugIn: - case ProjectType::Target::VST3PlugIn: - case ProjectType::Target::AAXPlugIn: - case ProjectType::Target::RTASPlugIn: - case ProjectType::Target::UnityPlugIn: - case ProjectType::Target::DynamicLibrary: + case build_tools::ProjectType::Target::StandalonePlugIn: + case build_tools::ProjectType::Target::GUIApp: + case build_tools::ProjectType::Target::ConsoleApp: + case build_tools::ProjectType::Target::StaticLibrary: + case build_tools::ProjectType::Target::SharedCodeTarget: + case build_tools::ProjectType::Target::AggregateTarget: + case build_tools::ProjectType::Target::VSTPlugIn: + case build_tools::ProjectType::Target::VST3PlugIn: + case build_tools::ProjectType::Target::AAXPlugIn: + case build_tools::ProjectType::Target::RTASPlugIn: + case build_tools::ProjectType::Target::UnityPlugIn: + case build_tools::ProjectType::Target::DynamicLibrary: return true; - case ProjectType::Target::AudioUnitPlugIn: - case ProjectType::Target::AudioUnitv3PlugIn: - case ProjectType::Target::unspecified: + case build_tools::ProjectType::Target::AudioUnitPlugIn: + case build_tools::ProjectType::Target::AudioUnitv3PlugIn: + case build_tools::ProjectType::Target::unspecified: default: break; } @@ -1336,12 +1338,12 @@ public: } //============================================================================== - RelativePath getManifestPath() const + build_tools::RelativePath getManifestPath() const { auto path = manifestFileValue.get().toString(); - return path.isEmpty() ? RelativePath() - : RelativePath (path, RelativePath::projectFolder); + return path.isEmpty() ? build_tools::RelativePath() + : build_tools::RelativePath (path, build_tools::RelativePath::projectFolder); } //============================================================================== @@ -1378,16 +1380,16 @@ public: }; //============================================================================== - void addPlatformSpecificSettingsForProjectType (const ProjectType& type) override + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType& type) override { msvcExtraPreprocessorDefs.set ("_CRT_SECURE_NO_WARNINGS", ""); if (type.isCommandLineApp()) msvcExtraPreprocessorDefs.set("_CONSOLE", ""); - callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) + callForAllSupportedTargets ([this] (build_tools::ProjectType::Target::Type targetType) { - if (targetType != ProjectType::Target::AggregateTarget) + if (targetType != build_tools::ProjectType::Target::AggregateTarget) targets.add (new MSVCTargetBase (targetType, *this)); }); @@ -1399,13 +1401,13 @@ public: const MSVCTargetBase* getSharedCodeTarget() const { for (auto target : targets) - if (target->type == ProjectType::Target::SharedCodeTarget) + if (target->type == build_tools::ProjectType::Target::SharedCodeTarget) return target; return nullptr; } - bool hasTarget (ProjectType::Target::Type type) const + bool hasTarget (build_tools::ProjectType::Target::Type type) const { for (auto target : targets) if (target->type == type) @@ -1414,99 +1416,21 @@ public: return false; } - static void writeIconFile (const ProjectExporter& exporter, const File& iconFile) - { - Array images; - int sizes[] = { 16, 32, 48, 256 }; - - for (int i = 0; i < numElementsInArray (sizes); ++i) - { - auto im = exporter.getBestIconForSize (sizes[i], true); - - if (im.isValid()) - images.add (im); - } - - if (images.size() > 0) - { - MemoryOutputStream mo; - writeIconFile (images, mo); - overwriteFileIfDifferentOrThrow (iconFile, mo); - } - } - static void createRCFile (const Project& p, const File& iconFile, const File& rcFile) { - auto version = p.getVersionString(); + build_tools::ResourceRcOptions resourceRc; + resourceRc.version = p.getVersionString(); + resourceRc.companyName = p.getCompanyNameString(); + resourceRc.companyCopyright = p.getCompanyCopyrightString(); + resourceRc.projectName = p.getProjectNameString(); + resourceRc.icon = iconFile; - MemoryOutputStream mo; - - mo << "#pragma code_page(65001)" << newLine - << newLine - << "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine - << " #include JUCE_USER_DEFINED_RC_FILE" << newLine - << "#else" << newLine - << newLine - << "#undef WIN32_LEAN_AND_MEAN" << newLine - << "#define WIN32_LEAN_AND_MEAN" << newLine - << "#include " << newLine - << newLine - << "VS_VERSION_INFO VERSIONINFO" << newLine - << "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine - << "BEGIN" << newLine - << " BLOCK \"StringFileInfo\"" << newLine - << " BEGIN" << newLine - << " BLOCK \"040904E4\"" << newLine - << " BEGIN" << newLine; - - auto writeRCValue = [&mo] (const String& n, const String& value) - { - if (value.isNotEmpty()) - mo << " VALUE \"" << n << "\", \"" - << value.replace ("\"", "\"\"") << "\\0\"" << newLine; - }; - - writeRCValue ("CompanyName", p.getCompanyNameString()); - writeRCValue ("LegalCopyright", p.getCompanyCopyrightString()); - writeRCValue ("FileDescription", p.getProjectNameString()); - writeRCValue ("FileVersion", version); - writeRCValue ("ProductName", p.getProjectNameString()); - writeRCValue ("ProductVersion", version); - - mo << " END" << newLine - << " END" << newLine - << newLine - << " BLOCK \"VarFileInfo\"" << newLine - << " BEGIN" << newLine - << " VALUE \"Translation\", 0x409, 1252" << newLine - << " END" << newLine - << "END" << newLine - << newLine - << "#endif" << newLine; - - if (iconFile.existsAsFile()) - mo << newLine - << "IDI_ICON1 ICON DISCARDABLE " << iconFile.getFileName().quoted() - << newLine - << "IDI_ICON2 ICON DISCARDABLE " << iconFile.getFileName().quoted(); - - overwriteFileIfDifferentOrThrow (rcFile, mo); - } - - static String getCommaSeparatedVersionNumber (const String& version) - { - auto versionParts = StringArray::fromTokens (version, ",.", ""); - versionParts.trim(); - versionParts.removeEmptyStrings(); - while (versionParts.size() < 4) - versionParts.add ("0"); - - return versionParts.joinIntoString (","); + resourceRc.write (rcFile); } private: //============================================================================== - String createRebasedPath (const RelativePath& path) const + String createRebasedPath (const build_tools::RelativePath& path) const { auto rebasedPath = rebaseFromProjectFolderToBuildTarget (path).toWindowsStyle(); @@ -1539,7 +1463,7 @@ protected: if (File::isAbsolutePath (file) || file.startsWithChar ('$')) prefix = ""; - return prefix + FileHelpers::windowsStylePath (file); + return prefix + build_tools::windowsStylePath (file); } String getIntDirFile (const BuildConfiguration& config, const String& file) const { return prependIfNotAbsolute (replacePreprocessorTokens (config, file), "$(IntDir)\\"); } @@ -1595,7 +1519,7 @@ protected: for (int i = 0; i < targets.size(); ++i) if (auto* target = targets[i]) - if (target->type == ProjectType::Target::SharedCodeTarget) + if (target->type == build_tools::ProjectType::Target::SharedCodeTarget) return target->getProjectGuid(); return {}; @@ -1612,13 +1536,13 @@ protected: { if (auto* target = targets[i]) { - if (sharedCodeGuid.isEmpty() || (addingOtherTargets != 0) == (target->type != ProjectType::Target::StandalonePlugIn)) + if (sharedCodeGuid.isEmpty() || (addingOtherTargets != 0) == (target->type != build_tools::ProjectType::Target::StandalonePlugIn)) { out << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" << projectName << " - " << target->getName() << "\", \"" << target->getVCProjFile().getFileName() << "\", \"" << target->getProjectGuid() << '"' << newLine; - if (sharedCodeGuid.isNotEmpty() && target->type != ProjectType::Target::SharedCodeTarget) + if (sharedCodeGuid.isNotEmpty() && target->type != build_tools::ProjectType::Target::SharedCodeTarget) out << "\tProjectSection(ProjectDependencies) = postProject" << newLine << "\t\t" << sharedCodeGuid << " = " << sharedCodeGuid << newLine << "\tEndProjectSection" << newLine; @@ -1672,117 +1596,6 @@ protected: } //============================================================================== - static void writeBMPImage (const Image& image, const int w, const int h, MemoryOutputStream& out) - { - int maskStride = (w / 8 + 3) & ~3; - - out.writeInt (40); // bitmapinfoheader size - out.writeInt (w); - out.writeInt (h * 2); - out.writeShort (1); // planes - out.writeShort (32); // bits - out.writeInt (0); // compression - out.writeInt ((h * w * 4) + (h * maskStride)); // size image - out.writeInt (0); // x pixels per meter - out.writeInt (0); // y pixels per meter - out.writeInt (0); // clr used - out.writeInt (0); // clr important - - Image::BitmapData bitmap (image, Image::BitmapData::readOnly); - int alphaThreshold = 5; - - int y; - for (y = h; --y >= 0;) - { - for (int x = 0; x < w; ++x) - { - auto pixel = bitmap.getPixelColour (x, y); - - if (pixel.getAlpha() <= alphaThreshold) - { - out.writeInt (0); - } - else - { - out.writeByte ((char) pixel.getBlue()); - out.writeByte ((char) pixel.getGreen()); - out.writeByte ((char) pixel.getRed()); - out.writeByte ((char) pixel.getAlpha()); - } - } - } - - for (y = h; --y >= 0;) - { - int mask = 0, count = 0; - - for (int x = 0; x < w; ++x) - { - auto pixel = bitmap.getPixelColour (x, y); - - mask <<= 1; - if (pixel.getAlpha() <= alphaThreshold) - mask |= 1; - - if (++count == 8) - { - out.writeByte ((char) mask); - count = 0; - mask = 0; - } - } - - if (mask != 0) - out.writeByte ((char) mask); - - for (int i = maskStride - w / 8; --i >= 0;) - out.writeByte (0); - } - } - - static void writeIconFile (const Array& images, MemoryOutputStream& out) - { - out.writeShort (0); // reserved - out.writeShort (1); // .ico tag - out.writeShort ((short) images.size()); - - MemoryOutputStream dataBlock; - - int imageDirEntrySize = 16; - int dataBlockStart = 6 + images.size() * imageDirEntrySize; - - for (int i = 0; i < images.size(); ++i) - { - auto oldDataSize = dataBlock.getDataSize(); - - auto& image = images.getReference (i); - auto w = image.getWidth(); - auto h = image.getHeight(); - - if (w >= 256 || h >= 256) - { - PNGImageFormat pngFormat; - pngFormat.writeImageToStream (image, dataBlock); - } - else - { - writeBMPImage (image, w, h, dataBlock); - } - - out.writeByte ((char) w); - out.writeByte ((char) h); - out.writeByte (0); - out.writeByte (0); - out.writeShort (1); // colour planes - out.writeShort (32); // bits per pixel - out.writeInt ((int) (dataBlock.getDataSize() - oldDataSize)); - out.writeInt (dataBlockStart + (int) oldDataSize); - } - - jassert (out.getPosition() == dataBlockStart); - out << dataBlock; - } - bool hasResourceFile() const { return ! projectType.isStaticLibrary(); @@ -1793,7 +1606,7 @@ protected: if (hasResourceFile()) { iconFile = getTargetFolder().getChildFile ("icon.ico"); - writeIconFile (*this, iconFile); + build_tools::writeWinIcon (getIcons(), iconFile); rcFile = getTargetFolder().getChildFile ("resources.rc"); createRCFile (project, iconFile, rcFile); } @@ -1801,11 +1614,11 @@ protected: static String prependDot (const String& filename) { - return FileHelpers::isAbsolutePath (filename) ? filename + return build_tools::isAbsolutePath (filename) ? filename : (".\\" + filename); } - static bool shouldUseStdCall (const RelativePath& path) + static bool shouldUseStdCall (const build_tools::RelativePath& path) { return path.getFileNameWithoutExtension().startsWithIgnoreCase ("include_juce_audio_plugin_client_RTAS_"); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h index d27020b20a..ad1d1084af 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h @@ -76,11 +76,11 @@ protected: public: //============================================================================== - class MakefileTarget : public ProjectType::Target + class MakefileTarget : public build_tools::ProjectType::Target { public: - MakefileTarget (ProjectType::Target::Type targetType, const MakefileProjectExporter& exporter) - : ProjectType::Target (targetType), owner (exporter) + MakefileTarget (build_tools::ProjectType::Target::Type targetType, const MakefileProjectExporter& exporter) + : build_tools::ProjectType::Target (targetType), owner (exporter) {} StringArray getCompilerFlags() const @@ -114,7 +114,7 @@ public: StringPairArray getDefines (const BuildConfiguration& config) const { StringPairArray result; - auto commonOptionKeys = owner.getAllPreprocessorDefs (config, ProjectType::Target::unspecified).getAllKeys(); + auto commonOptionKeys = owner.getAllPreprocessorDefs (config, build_tools::ProjectType::Target::unspecified).getAllKeys(); auto targetSpecific = owner.getAllPreprocessorDefs (config, type); for (auto& key : targetSpecific.getAllKeys()) @@ -186,7 +186,7 @@ public: out << "OBJECTS_" + getTargetVarName() + String (" := \\") << newLine; for (auto& f : filesToCompile) - out << " $(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), RelativePath::buildTargetFolder })) << " \\" << newLine; + out << " $(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder })) << " \\" << newLine; out << newLine; } @@ -198,7 +198,7 @@ public: for (auto& f : filesToCompile) { - RelativePath relativePath (f.first, owner.getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath relativePath (f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder); out << "$(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor (relativePath)) << ": " << escapeSpaces (relativePath.toUnixStyle()) << newLine << "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)" << newLine @@ -252,9 +252,9 @@ public: { auto scriptName = owner.getProject().getUnityScriptName(); - RelativePath scriptPath (owner.getProject().getGeneratedCodeFolder().getChildFile (scriptName), - owner.getTargetFolder(), - RelativePath::projectFolder); + build_tools::RelativePath scriptPath (owner.getProject().getGeneratedCodeFolder().getChildFile (scriptName), + owner.getTargetFolder(), + build_tools::RelativePath::projectFolder); out << "\t-$(V_AT)cp " + scriptPath.toUnixStyle() + " $(JUCE_OUTDIR)/" + scriptName << newLine; } @@ -331,26 +331,26 @@ public: bool isOSX() const override { return false; } bool isiOS() const override { return false; } - bool supportsTargetType (ProjectType::Target::Type type) const override + bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override { switch (type) { - case ProjectType::Target::GUIApp: - case ProjectType::Target::ConsoleApp: - case ProjectType::Target::StaticLibrary: - case ProjectType::Target::SharedCodeTarget: - case ProjectType::Target::AggregateTarget: - case ProjectType::Target::VSTPlugIn: - case ProjectType::Target::StandalonePlugIn: - case ProjectType::Target::DynamicLibrary: - case ProjectType::Target::UnityPlugIn: + case build_tools::ProjectType::Target::GUIApp: + case build_tools::ProjectType::Target::ConsoleApp: + case build_tools::ProjectType::Target::StaticLibrary: + case build_tools::ProjectType::Target::SharedCodeTarget: + case build_tools::ProjectType::Target::AggregateTarget: + case build_tools::ProjectType::Target::VSTPlugIn: + case build_tools::ProjectType::Target::StandalonePlugIn: + case build_tools::ProjectType::Target::DynamicLibrary: + case build_tools::ProjectType::Target::UnityPlugIn: return true; - case ProjectType::Target::VST3PlugIn: - case ProjectType::Target::AAXPlugIn: - case ProjectType::Target::RTASPlugIn: - case ProjectType::Target::AudioUnitPlugIn: - case ProjectType::Target::AudioUnitv3PlugIn: - case ProjectType::Target::unspecified: + case build_tools::ProjectType::Target::VST3PlugIn: + case build_tools::ProjectType::Target::AAXPlugIn: + case build_tools::ProjectType::Target::RTASPlugIn: + case build_tools::ProjectType::Target::AudioUnitPlugIn: + case build_tools::ProjectType::Target::AudioUnitv3PlugIn: + case build_tools::ProjectType::Target::unspecified: default: break; } @@ -377,8 +377,8 @@ public: { auto fileType = target->getTargetFileType(); - if (fileType == ProjectType::Target::sharedLibraryOrDLL - || fileType == ProjectType::Target::pluginBundle) + if (fileType == build_tools::ProjectType::Target::sharedLibraryOrDLL + || fileType == build_tools::ProjectType::Target::pluginBundle) return true; } @@ -388,20 +388,19 @@ public: //============================================================================== void create (const OwnedArray&) const override { - MemoryOutputStream mo; - mo.setNewLineString ("\n"); - - writeMakefile (mo); - - overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("Makefile"), mo); + build_tools::writeStreamToFile (getTargetFolder().getChildFile ("Makefile"), [&] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); + writeMakefile (mo); + }); } //============================================================================== - void addPlatformSpecificSettingsForProjectType (const ProjectType&) override + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override { - callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) + callForAllSupportedTargets ([this] (build_tools::ProjectType::Target::Type targetType) { - targets.insert (targetType == ProjectType::Target::AggregateTarget ? 0 : -1, + targets.insert (targetType == build_tools::ProjectType::Target::AggregateTarget ? 0 : -1, new MakefileTarget (targetType, *this)); }); @@ -430,7 +429,7 @@ private: result.set ("NDEBUG", "1"); } - result = mergePreprocessorDefs (result, getAllPreprocessorDefs (config, ProjectType::Target::unspecified)); + result = mergePreprocessorDefs (result, getAllPreprocessorDefs (config, build_tools::ProjectType::Target::unspecified)); return result; } @@ -542,7 +541,7 @@ private: StringArray result; for (auto& path : searchPaths) - result.add (FileHelpers::unixStylePath (replacePreprocessorTokens (config, path))); + result.add (build_tools::unixStylePath (replacePreprocessorTokens (config, path))); return result; } @@ -614,7 +613,7 @@ private: //============================================================================== void writeDefineFlags (OutputStream& out, const MakeBuildConfiguration& config) const { - out << createGCCPreprocessorFlags (mergePreprocessorDefs (getDefines (config), getAllPreprocessorDefs (config, ProjectType::Target::unspecified))); + out << createGCCPreprocessorFlags (mergePreprocessorDefs (getDefines (config), getAllPreprocessorDefs (config, build_tools::ProjectType::Target::unspecified))); } void writePkgConfigFlags (OutputStream& out) const @@ -680,7 +679,7 @@ private: { if (auto* target = targets.getUnchecked (i)) { - if (target->type == ProjectType::Target::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::AggregateTarget) { StringArray dependencies; MemoryOutputStream subTargetLines; @@ -691,7 +690,7 @@ private: if (auto* dependency = targets.getUnchecked (j)) { - if (dependency->type != ProjectType::Target::SharedCodeTarget) + if (dependency->type != build_tools::ProjectType::Target::SharedCodeTarget) { auto phonyName = dependency->getPhonyName(); @@ -723,8 +722,8 @@ private: if (config.getTargetBinaryRelativePathString().isNotEmpty()) { - RelativePath binaryPath (config.getTargetBinaryRelativePathString(), RelativePath::projectFolder); - outputDir = binaryPath.rebased (projectFolder, getTargetFolder(), RelativePath::buildTargetFolder).toUnixStyle(); + build_tools::RelativePath binaryPath (config.getTargetBinaryRelativePathString(), build_tools::RelativePath::projectFolder); + outputDir = binaryPath.rebased (projectFolder, getTargetFolder(), build_tools::RelativePath::buildTargetFolder).toUnixStyle(); } out << "ifeq ($(CONFIG)," << escapeSpaces (config.getName()) << ")" << newLine @@ -785,7 +784,7 @@ private: { if (auto* target = targets.getUnchecked (i)) { - if (target->type == ProjectType::Target::AggregateTarget) + if (target->type == build_tools::ProjectType::Target::AggregateTarget) continue; out << "-include $(OBJECTS_" << target->getTargetVarName() @@ -931,7 +930,7 @@ private: return "-march=native"; } - String getObjectFileFor (const RelativePath& file) const + String getObjectFileFor (const build_tools::RelativePath& file) const { return file.getFileNameWithoutExtension() + "_" + String::toHexString (file.toUnixStyle().hashCode()) + ".o"; @@ -947,8 +946,8 @@ private: return phonyTargetLine.toString(); for (auto target : targets) - if (target->type != ProjectType::Target::SharedCodeTarget - && target->type != ProjectType::Target::AggregateTarget) + if (target->type != build_tools::ProjectType::Target::SharedCodeTarget + && target->type != build_tools::ProjectType::Target::AggregateTarget) phonyTargetLine << " " << target->getPhonyName(); return phonyTargetLine.toString(); diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h index b99970fbb3..a87b1522ad 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h @@ -207,7 +207,7 @@ public: String getDevelopmentTeamIDString() const { return iosDevelopmentTeamIDValue.get(); } String getAppGroupIdString() const { return iosAppGroupsIDValue.get(); } - String getDefaultLaunchStoryboardName() const { jassert (iOS); return "LaunchScreen"; } + String getDefaultLaunchStoryboardName() const { return "LaunchScreen"; } //============================================================================== bool usesMMFiles() const override { return true; } @@ -227,27 +227,27 @@ public: bool isOSX() const override { return ! iOS; } bool isiOS() const override { return iOS; } - bool supportsTargetType (ProjectType::Target::Type type) const override + bool supportsTargetType (build_tools::ProjectType::Target::Type type) const override { switch (type) { - case ProjectType::Target::AudioUnitv3PlugIn: - case ProjectType::Target::StandalonePlugIn: - case ProjectType::Target::GUIApp: - case ProjectType::Target::StaticLibrary: - case ProjectType::Target::DynamicLibrary: - case ProjectType::Target::SharedCodeTarget: - case ProjectType::Target::AggregateTarget: + case build_tools::ProjectType::Target::AudioUnitv3PlugIn: + case build_tools::ProjectType::Target::StandalonePlugIn: + case build_tools::ProjectType::Target::GUIApp: + case build_tools::ProjectType::Target::StaticLibrary: + case build_tools::ProjectType::Target::DynamicLibrary: + case build_tools::ProjectType::Target::SharedCodeTarget: + case build_tools::ProjectType::Target::AggregateTarget: return true; - case ProjectType::Target::ConsoleApp: - case ProjectType::Target::VSTPlugIn: - case ProjectType::Target::VST3PlugIn: - case ProjectType::Target::AAXPlugIn: - case ProjectType::Target::RTASPlugIn: - case ProjectType::Target::AudioUnitPlugIn: - case ProjectType::Target::UnityPlugIn: + case build_tools::ProjectType::Target::ConsoleApp: + case build_tools::ProjectType::Target::VSTPlugIn: + case build_tools::ProjectType::Target::VST3PlugIn: + case build_tools::ProjectType::Target::AAXPlugIn: + case build_tools::ProjectType::Target::RTASPlugIn: + case build_tools::ProjectType::Target::AudioUnitPlugIn: + case build_tools::ProjectType::Target::UnityPlugIn: return ! iOS; - case ProjectType::Target::unspecified: + case build_tools::ProjectType::Target::unspecified: default: break; } @@ -580,13 +580,8 @@ public: createObjects(); - auto projectFile = projectBundle.getChildFile ("project.pbxproj"); - - { - MemoryOutputStream mo; - writeProjectFile (mo); - overwriteFileIfDifferentOrThrow (projectFile, mo); - } + build_tools::writeStreamToFile (projectBundle.getChildFile ("project.pbxproj"), + [this] (MemoryOutputStream& mo) { writeProjectFile (mo); }); writeInfoPlistFiles(); @@ -599,11 +594,11 @@ public: } //============================================================================== - void addPlatformSpecificSettingsForProjectType (const ProjectType&) override + void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) override { - callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) + callForAllSupportedTargets ([this] (build_tools::ProjectType::Target::Type targetType) { - targets.insert (targetType == ProjectType::Target::AggregateTarget ? 0 : -1, + targets.insert (targetType == build_tools::ProjectType::Target::AggregateTarget ? 0 : -1, new XcodeTarget (targetType, *this)); }); @@ -860,18 +855,16 @@ public: }; //============================================================================== - struct XcodeTarget : ProjectType::Target + struct XcodeTarget : build_tools::ProjectType::Target { //============================================================================== - XcodeTarget (ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter) - : ProjectType::Target (targetType), + XcodeTarget (build_tools::ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter) + : Target (targetType), owner (exporter) { switch (type) { case GUIApp: - xcodePackageType = "APPL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.application"; xcodeBundleExtension = ".app"; xcodeProductType = "com.apple.product-type.application"; @@ -900,8 +893,6 @@ public: break; case VSTPlugIn: - xcodePackageType = "BNDL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".vst"; xcodeProductType = "com.apple.product-type.bundle"; @@ -909,8 +900,6 @@ public: break; case VST3PlugIn: - xcodePackageType = "BNDL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".vst3"; xcodeProductType = "com.apple.product-type.bundle"; @@ -918,8 +907,6 @@ public: break; case AudioUnitPlugIn: - xcodePackageType = "BNDL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".component"; xcodeProductType = "com.apple.product-type.bundle"; @@ -929,8 +916,6 @@ public: break; case StandalonePlugIn: - xcodePackageType = "APPL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.application"; xcodeBundleExtension = ".app"; xcodeProductType = "com.apple.product-type.application"; @@ -938,8 +923,6 @@ public: break; case AudioUnitv3PlugIn: - xcodePackageType = "XPC!"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.app-extension"; xcodeBundleExtension = ".appex"; xcodeBundleIDSubPath = "AUv3"; @@ -950,8 +933,6 @@ public: break; case AAXPlugIn: - xcodePackageType = "TDMw"; - xcodeBundleSignature = "PTul"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".aaxplugin"; xcodeProductType = "com.apple.product-type.bundle"; @@ -959,8 +940,6 @@ public: break; case RTASPlugIn: - xcodePackageType = "TDMw"; - xcodeBundleSignature = "PTul"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".dpm"; xcodeProductType = "com.apple.product-type.bundle"; @@ -968,8 +947,6 @@ public: break; case UnityPlugIn: - xcodePackageType = "BNDL"; - xcodeBundleSignature = "????"; xcodeFileType = "wrapper.cfbundle"; xcodeBundleExtension = ".bundle"; xcodeProductType = "com.apple.product-type.bundle"; @@ -987,7 +964,7 @@ public: xcodeCopyToProductInstallPathAfterBuild = false; break; - case ProjectType::Target::unspecified: + case unspecified: default: // unknown target type! jassertfalse; @@ -1015,7 +992,7 @@ public: return String (getName()).replace (" ", "_") + String (".entitlements"); } - String xcodePackageType, xcodeBundleSignature, xcodeBundleExtension; + String xcodeBundleExtension; String xcodeProductType, xcodeFileType; String xcodeOtherRezFlags, xcodeBundleIDSubPath; bool xcodeCopyToProductInstallPathAfterBuild; @@ -1029,7 +1006,7 @@ public: struct SourceFileInfo { - RelativePath path; + build_tools::RelativePath path; bool shouldBeCompiled = false; }; @@ -1049,9 +1026,11 @@ public: { SourceFileInfo info; - info.path = RelativePath (projectItem.getFile(), owner.getTargetFolder(), RelativePath::buildTargetFolder); + info.path = build_tools::RelativePath (projectItem.getFile(), + owner.getTargetFolder(), + build_tools::RelativePath::buildTargetFolder); - jassert (info.path.getRoot() == RelativePath::buildTargetFolder); + jassert (info.path.getRoot() == build_tools::RelativePath::buildTargetFolder); if (targetType == SharedCodeTarget || projectItem.shouldBeCompiled()) info.shouldBeCompiled = projectItem.shouldBeCompiled(); @@ -1352,8 +1331,11 @@ public: // (= for audio plug-ins) or using a custom binary path (for everything else), but not both (= conflict!) jassert (! xcodeCopyToProductInstallPathAfterBuild); - RelativePath binaryPath (config.getTargetBinaryRelativePathString(), RelativePath::projectFolder); - configurationBuildDir = sanitisePath (binaryPath.rebased (owner.projectFolder, owner.getTargetFolder(), RelativePath::buildTargetFolder) + build_tools::RelativePath binaryPath (config.getTargetBinaryRelativePathString(), + build_tools::RelativePath::projectFolder); + configurationBuildDir = sanitisePath (binaryPath.rebased (owner.projectFolder, + owner.getTargetFolder(), + build_tools::RelativePath::buildTargetFolder) .toUnixStyle()); } @@ -1523,7 +1505,7 @@ public: if (type != Target::SharedCodeTarget) { - Array extraLibs; + Array extraLibs; addExtraLibsForTargetType (config, extraLibs); @@ -1539,7 +1521,7 @@ public: { auto productName = getStaticLibbedFilename (owner.replacePreprocessorTokens (config, config.getTargetBinaryNameString())); - RelativePath sharedCodelib (productName, RelativePath::buildTargetFolder); + build_tools::RelativePath sharedCodelib (productName, build_tools::RelativePath::buildTargetFolder); flags.add (getLinkerFlagForLib (sharedCodelib.getFileNameWithoutExtension())); } } @@ -1557,193 +1539,69 @@ public: flags = getCleanedStringArray (flags); } - //========================================================================== c + //========================================================================== void writeInfoPlistFile() const { if (! shouldCreatePList()) return; - auto plist = parseXML (owner.getPListToMergeString()); + build_tools::PlistOptions options; - if (plist == nullptr || ! plist->hasTagName ("plist")) - plist.reset (new XmlElement ("plist")); + options.type = type; + options.executableName = "${EXECUTABLE_NAME}"; + options.bundleIdentifier = getBundleIdentifier(); + options.plistToMerge = owner.getPListToMergeString(); + options.iOS = owner.iOS; + options.microphonePermissionEnabled = owner.isMicrophonePermissionEnabled(); + options.microphonePermissionText = owner.getMicrophonePermissionsTextString(); + options.cameraPermissionEnabled = owner.isCameraPermissionEnabled(); + options.cameraPermissionText = owner.getCameraPermissionTextString(); + options.bluetoothPermissionEnabled = owner.isBluetoothPermissionEnabled(); + options.bluetoothPermissionText = owner.getBluetoothPermissionTextString(); + options.sendAppleEventsPermissionEnabled = owner.isSendAppleEventsPermissionEnabled(); + options.sendAppleEventsPermissionText = owner.getSendAppleEventsPermissionTextString(); + options.shouldAddStoryboardToProject = owner.shouldAddStoryboardToProject(); + options.iconFile = owner.iconFile; + options.projectName = owner.projectName; + options.version = owner.project.getVersionString(); + options.companyCopyright = owner.project.getCompanyCopyrightString(); + options.allPreprocessorDefs = owner.getAllPreprocessorDefs(); + options.documentExtensions = owner.getDocumentExtensionsString(); + options.fileSharingEnabled = owner.isFileSharingEnabled(); + options.documentBrowserEnabled = owner.isDocumentBrowserEnabled(); + options.statusBarHidden = owner.isStatusBarHidden(); + options.backgroundAudioEnabled = owner.isBackgroundAudioEnabled(); + options.backgroundBleEnabled = owner.isBackgroundBleEnabled(); + options.pushNotificationsEnabled = owner.isPushNotificationsEnabled(); + options.enableIAA = owner.project.shouldEnableIAA(); + options.IAAPluginName = owner.project.getIAAPluginName(); + options.pluginManufacturerCode = owner.project.getPluginManufacturerCodeString(); + options.IAATypeCode = owner.project.getIAATypeCode(); + options.pluginCode = owner.project.getPluginCodeString(); + options.versionAsHex = owner.project.getVersionAsHexInteger(); + options.iPhoneScreenOrientations = owner.getiPhoneScreenOrientationString(); + options.iPadScreenOrientations = owner.getiPadScreenOrientationString(); - auto* dict = plist->getChildByName ("dict"); - - if (dict == nullptr) - dict = plist->createNewChildElement ("dict"); - - if (owner.isMicrophonePermissionEnabled()) - addPlistDictionaryKey (dict, "NSMicrophoneUsageDescription", owner.getMicrophonePermissionsTextString()); - - if (owner.isCameraPermissionEnabled()) - addPlistDictionaryKey (dict, "NSCameraUsageDescription", owner.getCameraPermissionTextString()); - - if (owner.iOS) + options.storyboardName = [&] { - if (owner.isBluetoothPermissionEnabled()) - { - addPlistDictionaryKey (dict, "NSBluetoothAlwaysUsageDescription", owner.getBluetoothPermissionTextString()); - addPlistDictionaryKey (dict, "NSBluetoothPeripheralUsageDescription", owner.getBluetoothPermissionTextString()); // needed for pre iOS 13.0 - } + const auto customLaunchStoryboard = owner.getCustomLaunchStoryboardString(); - addPlistDictionaryKeyBool (dict, "LSRequiresIPhoneOS", true); + if (customLaunchStoryboard.isEmpty()) + return owner.getDefaultLaunchStoryboardName(); - if (type != AudioUnitv3PlugIn) - addPlistDictionaryKeyBool (dict, "UIViewControllerBasedStatusBarAppearance", false); + return customLaunchStoryboard.fromLastOccurrenceOf ("/", false, false) + .upToLastOccurrenceOf (".storyboard", false, false); + }(); - if (owner.shouldAddStoryboardToProject()) - { - auto customStoryboard = owner.getCustomLaunchStoryboardString(); + options.pluginName = owner.project.getPluginNameString(); + options.pluginManufacturer = owner.project.getPluginManufacturerString(); + options.pluginDescription = owner.project.getPluginDescriptionString(); + options.pluginAUExportPrefix = owner.project.getPluginAUExportPrefixString(); + options.auMainType = owner.project.getAUMainTypeString(); + options.isAuSandboxSafe = owner.project.isAUSandBoxSafe(); + options.isPluginSynth = owner.project.isPluginSynth(); - addPlistDictionaryKey (dict, "UILaunchStoryboardName", customStoryboard.isNotEmpty() ? customStoryboard.fromLastOccurrenceOf ("/", false, false) - .upToLastOccurrenceOf (".storyboard", false, false) - : owner.getDefaultLaunchStoryboardName()); - } - } - else - { - if (owner.isSendAppleEventsPermissionEnabled()) - addPlistDictionaryKey (dict, "NSAppleEventsUsageDescription", owner.getSendAppleEventsPermissionTextString()); - } - - addPlistDictionaryKey (dict, "CFBundleExecutable", "${EXECUTABLE_NAME}"); - - if (! owner.iOS) // (NB: on iOS this causes error ITMS-90032 during publishing) - addPlistDictionaryKey (dict, "CFBundleIconFile", owner.iconFile.exists() ? owner.iconFile.getFileName() : String()); - - addPlistDictionaryKey (dict, "CFBundleIdentifier", getBundleIdentifier()); - addPlistDictionaryKey (dict, "CFBundleName", owner.projectName); - - // needed by NSExtension on iOS - addPlistDictionaryKey (dict, "CFBundleDisplayName", owner.projectName); - addPlistDictionaryKey (dict, "CFBundlePackageType", xcodePackageType); - addPlistDictionaryKey (dict, "CFBundleSignature", xcodeBundleSignature); - addPlistDictionaryKey (dict, "CFBundleShortVersionString", owner.project.getVersionString()); - addPlistDictionaryKey (dict, "CFBundleVersion", owner.project.getVersionString()); - addPlistDictionaryKey (dict, "NSHumanReadableCopyright", owner.project.getCompanyCopyrightString()); - addPlistDictionaryKeyBool (dict, "NSHighResolutionCapable", true); - - auto documentExtensions = StringArray::fromTokens (replacePreprocessorDefs (owner.getAllPreprocessorDefs(), - owner.getDocumentExtensionsString()), ",", {}); - documentExtensions.trim(); - documentExtensions.removeEmptyStrings (true); - - if (documentExtensions.size() > 0 && type != AudioUnitv3PlugIn) - { - dict->createNewChildElement ("key")->addTextElement ("CFBundleDocumentTypes"); - auto* dict2 = dict->createNewChildElement ("array")->createNewChildElement ("dict"); - XmlElement* arrayTag = nullptr; - - for (auto ex : documentExtensions) - { - if (ex.startsWithChar ('.')) - ex = ex.substring (1); - - if (arrayTag == nullptr) - { - dict2->createNewChildElement ("key")->addTextElement ("CFBundleTypeExtensions"); - arrayTag = dict2->createNewChildElement ("array"); - - addPlistDictionaryKey (dict2, "CFBundleTypeName", ex); - addPlistDictionaryKey (dict2, "CFBundleTypeRole", "Editor"); - addPlistDictionaryKey (dict2, "CFBundleTypeIconFile", "Icon"); - addPlistDictionaryKey (dict2, "NSPersistentStoreTypeKey", "XML"); - } - - arrayTag->createNewChildElement ("string")->addTextElement (ex); - } - } - - if (owner.isFileSharingEnabled() && type != AudioUnitv3PlugIn) - addPlistDictionaryKeyBool (dict, "UIFileSharingEnabled", true); - - if (owner.isDocumentBrowserEnabled()) - addPlistDictionaryKeyBool (dict, "UISupportsDocumentBrowser", true); - - if (owner.isStatusBarHidden() && type != AudioUnitv3PlugIn) - addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true); - - if (owner.iOS) - { - if (type != AudioUnitv3PlugIn) - { - // Forcing full screen disables the split screen feature and prevents error ITMS-90475 - addPlistDictionaryKeyBool (dict, "UIRequiresFullScreen", true); - addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true); - - addIosScreenOrientations (dict); - addIosBackgroundModes (dict); - } - - if (type == StandalonePlugIn && owner.getProject().shouldEnableIAA()) - { - XmlElement audioComponentsPlistKey ("key"); - audioComponentsPlistKey.addTextElement ("AudioComponents"); - - dict->addChildElement (new XmlElement (audioComponentsPlistKey)); - - XmlElement audioComponentsPlistEntry ("array"); - auto* audioComponentsDict = audioComponentsPlistEntry.createNewChildElement ("dict"); - - addPlistDictionaryKey (audioComponentsDict, "name", owner.project.getIAAPluginName()); - addPlistDictionaryKey (audioComponentsDict, "manufacturer", owner.project.getPluginManufacturerCodeString().substring (0, 4)); - addPlistDictionaryKey (audioComponentsDict, "type", owner.project.getIAATypeCode()); - addPlistDictionaryKey (audioComponentsDict, "subtype", owner.project.getPluginCodeString().substring (0, 4)); - addPlistDictionaryKeyInt (audioComponentsDict, "version", owner.project.getVersionAsHexInteger()); - - dict->addChildElement (new XmlElement (audioComponentsPlistEntry)); - } - } - - for (auto& e : xcodeExtraPListEntries) - dict->addChildElement (new XmlElement (e)); - - MemoryOutputStream mo; - XmlElement::TextFormat format; - format.dtd = ""; - plist->writeTo (mo, format); - overwriteFileIfDifferentOrThrow (infoPlistFile, mo); - } - - //============================================================================== - void addIosScreenOrientations (XmlElement* dict) const - { - String screenOrientations[2] = { owner.getiPhoneScreenOrientationString(), owner.getiPadScreenOrientationString() }; - String plistSuffix[2] = { "", "~ipad" }; - auto orientationsAreTheSame = ( screenOrientations[0] == screenOrientations[1] ); - - for (int i = 0; i < (orientationsAreTheSame ? 1 : 2); ++i) - { - StringArray iOSOrientations; - - if (screenOrientations[i].contains ("portrait")) { iOSOrientations.add ("UIInterfaceOrientationPortrait"); } - if (screenOrientations[i].contains ("landscape")) { iOSOrientations.add ("UIInterfaceOrientationLandscapeLeft"); iOSOrientations.add ("UIInterfaceOrientationLandscapeRight"); } - - addArrayToPlist (dict, String ("UISupportedInterfaceOrientations") + plistSuffix[i], iOSOrientations); - } - - } - - //============================================================================== - void addIosBackgroundModes (XmlElement* dict) const - { - StringArray iosBackgroundModes; - if (owner.isBackgroundAudioEnabled()) iosBackgroundModes.add ("audio"); - if (owner.isBackgroundBleEnabled()) iosBackgroundModes.add ("bluetooth-central"); - if (owner.isPushNotificationsEnabled()) iosBackgroundModes.add ("remote-notification"); - - addArrayToPlist (dict, "UIBackgroundModes", iosBackgroundModes); - } - - //============================================================================== - static void addArrayToPlist (XmlElement* dict, String arrayKey, const StringArray& arrayElements) - { - dict->createNewChildElement ("key")->addTextElement (arrayKey); - auto* plistStringArray = dict->createNewChildElement ("array"); - - for (auto& e : arrayElements) - plistStringArray->createNewChildElement ("string")->addTextElement (e); + options.write (infoPlistFile); } //============================================================================== @@ -1795,7 +1653,7 @@ public: { // Needed to compile .r files paths.add (owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client") - .rebased (owner.projectFolder, owner.getTargetFolder(), RelativePath::buildTargetFolder) + .rebased (owner.projectFolder, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder) .toUnixStyle()); } @@ -1820,48 +1678,6 @@ public: " -I \\\"$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AudioUnit.framework/Headers\\\""; xcodeFrameworks.addArray ({ "AudioUnit", "CoreAudioKit" }); - - XmlElement plistKey ("key"); - plistKey.addTextElement ("AudioComponents"); - - XmlElement plistEntry ("array"); - auto* dict = plistEntry.createNewChildElement ("dict"); - - auto pluginManufacturerCode = owner.project.getPluginManufacturerCodeString().substring (0, 4); - auto pluginSubType = owner.project.getPluginCodeString().substring (0, 4); - - if (pluginManufacturerCode.toLowerCase() == pluginManufacturerCode) - { - throw SaveError ("AudioUnit plugin code identifiers invalid!\n\n" - "You have used only lower case letters in your AU plugin manufacturer identifier. " - "You must have at least one uppercase letter in your AU plugin manufacturer " - "identifier code."); - } - - addPlistDictionaryKey (dict, "name", owner.project.getPluginManufacturerString() - + ": " + owner.project.getPluginNameString()); - addPlistDictionaryKey (dict, "description", owner.project.getPluginDescriptionString()); - addPlistDictionaryKey (dict, "factoryFunction", owner.project.getPluginAUExportPrefixString() + "Factory"); - addPlistDictionaryKey (dict, "manufacturer", pluginManufacturerCode); - addPlistDictionaryKey (dict, "type", owner.project.getAUMainTypeString().removeCharacters ("'")); - addPlistDictionaryKey (dict, "subtype", pluginSubType); - addPlistDictionaryKeyInt (dict, "version", owner.project.getVersionAsHexInteger()); - - if (owner.project.isAUSandBoxSafe()) - { - addPlistDictionaryKeyBool (dict, "sandboxSafe", true); - } - else - { - dict->createNewChildElement ("key")->addTextElement ("resourceUsage"); - auto* resourceUsageDict = dict->createNewChildElement ("dict"); - - addPlistDictionaryKeyBool (resourceUsageDict, "network.client", true); - addPlistDictionaryKeyBool (resourceUsageDict, "temporary-exception.files.all.read-write", true); - } - - xcodeExtraPListEntries.add (plistKey); - xcodeExtraPListEntries.add (plistEntry); } void addExtraAudioUnitv3PlugInTargetSettings() @@ -1870,47 +1686,13 @@ public: if (owner.isOSX()) xcodeFrameworks.add ("AudioUnit"); - - XmlElement plistKey ("key"); - plistKey.addTextElement ("NSExtension"); - - XmlElement plistEntry ("dict"); - - addPlistDictionaryKey (&plistEntry, "NSExtensionPrincipalClass", owner.project.getPluginAUExportPrefixString() + "FactoryAUv3"); - addPlistDictionaryKey (&plistEntry, "NSExtensionPointIdentifier", "com.apple.AudioUnit-UI"); - plistEntry.createNewChildElement ("key")->addTextElement ("NSExtensionAttributes"); - - auto* dict = plistEntry.createNewChildElement ("dict"); - dict->createNewChildElement ("key")->addTextElement ("AudioComponents"); - auto* componentArray = dict->createNewChildElement ("array"); - - auto* componentDict = componentArray->createNewChildElement ("dict"); - - addPlistDictionaryKey (componentDict, "name", owner.project.getPluginManufacturerString() - + ": " + owner.project.getPluginNameString()); - addPlistDictionaryKey (componentDict, "description", owner.project.getPluginDescriptionString()); - addPlistDictionaryKey (componentDict, "factoryFunction",owner.project. getPluginAUExportPrefixString() + "FactoryAUv3"); - addPlistDictionaryKey (componentDict, "manufacturer", owner.project.getPluginManufacturerCodeString().substring (0, 4)); - addPlistDictionaryKey (componentDict, "type", owner.project.getAUMainTypeString().removeCharacters ("'")); - addPlistDictionaryKey (componentDict, "subtype", owner.project.getPluginCodeString().substring (0, 4)); - addPlistDictionaryKeyInt (componentDict, "version", owner.project.getVersionAsHexInteger()); - addPlistDictionaryKeyBool (componentDict, "sandboxSafe", true); - - componentDict->createNewChildElement ("key")->addTextElement ("tags"); - auto* tagsArray = componentDict->createNewChildElement ("array"); - - tagsArray->createNewChildElement ("string") - ->addTextElement (static_cast (owner.project.isPluginSynth()) ? "Synth" : "Effects"); - - xcodeExtraPListEntries.add (plistKey); - xcodeExtraPListEntries.add (plistEntry); } - void addExtraLibsForTargetType (const BuildConfiguration& config, Array& extraLibs) const + void addExtraLibsForTargetType (const BuildConfiguration& config, Array& extraLibs) const { if (type == AAXPlugIn) { - auto aaxLibsFolder = RelativePath (owner.getAAXPathString(), RelativePath::projectFolder).getChildFile ("Libs"); + auto aaxLibsFolder = build_tools::RelativePath (owner.getAAXPathString(), build_tools::RelativePath::projectFolder).getChildFile ("Libs"); String libraryPath (config.isDebug() ? "Debug" : "Release"); libraryPath += "/libAAXLibrary_libcpp.a"; @@ -1919,7 +1701,7 @@ public: } else if (type == RTASPlugIn) { - RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); + build_tools::RelativePath rtasFolder (owner.getRTASPathString(), build_tools::RelativePath::projectFolder); extraLibs.add (rtasFolder.getChildFile ("MacBag/Libs/Debug/libPluginLibrary.a")); extraLibs.add (rtasFolder.getChildFile ("MacBag/Libs/Release/libPluginLibrary.a")); @@ -1932,7 +1714,7 @@ public: if (type == RTASPlugIn) { - RelativePath rtasFolder (owner.getRTASPathString(), RelativePath::projectFolder); + build_tools::RelativePath rtasFolder (owner.getRTASPathString(), build_tools::RelativePath::projectFolder); targetExtraSearchPaths.add ("$(DEVELOPER_DIR)/Headers/FlatCarbon"); targetExtraSearchPaths.add ("$(SDKROOT)/Developer/Headers/FlatCarbon"); @@ -2069,8 +1851,8 @@ private: if (customLaunchStoryboard.isEmpty()) writeDefaultLaunchStoryboardFile(); else if (getProject().getProjectFolder().getChildFile (customLaunchStoryboard).existsAsFile()) - addLaunchStoryboardFileReference (RelativePath (customLaunchStoryboard, RelativePath::projectFolder) - .rebased (getProject().getProjectFolder(), getTargetFolder(), RelativePath::buildTargetFolder) + addLaunchStoryboardFileReference (build_tools::RelativePath (customLaunchStoryboard, build_tools::RelativePath::projectFolder) + .rebased (getProject().getProjectFolder(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder) .toUnixStyle()); } } @@ -2131,7 +1913,7 @@ private: if (target->shouldCreatePList()) { - RelativePath plistPath (target->infoPlistFile, getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath plistPath (target->infoPlistFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); addFileReference (plistPath.toUnixStyle()); resourceFileRefs.add (createFileRefID (plistPath)); } @@ -2140,11 +1922,12 @@ private: void addNibFiles() const { - MemoryOutputStream nib; - nib.write (BinaryData::RecentFilesMenuTemplate_nib, BinaryData::RecentFilesMenuTemplate_nibSize); - overwriteFileIfDifferentOrThrow (menuNibFile, nib); + build_tools::writeStreamToFile (menuNibFile, [&] (MemoryOutputStream& mo) + { + mo.write (BinaryData::RecentFilesMenuTemplate_nib, BinaryData::RecentFilesMenuTemplate_nibSize); + }); - RelativePath menuNibPath (menuNibFile, getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath menuNibPath (menuNibFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); addFileReference (menuNibPath.toUnixStyle()); resourceIDs.add (addBuildFile (menuNibPath, false, false)); resourceFileRefs.add (createFileRefID (menuNibPath)); @@ -2154,7 +1937,7 @@ private: { if (iconFile.exists()) { - RelativePath iconPath (iconFile, getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath iconPath (iconFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); addFileReference (iconPath.toUnixStyle()); resourceIDs.add (addBuildFile (iconPath, false, false)); resourceFileRefs.add (createFileRefID (iconPath)); @@ -2303,9 +2086,9 @@ private: { if (auto* unityTarget = getTargetOfType (XcodeTarget::UnityPlugIn)) { - RelativePath scriptPath (getProject().getGeneratedCodeFolder().getChildFile (getProject().getUnityScriptName()), - getTargetFolder(), - RelativePath::buildTargetFolder); + build_tools::RelativePath scriptPath (getProject().getGeneratedCodeFolder().getChildFile (getProject().getUnityScriptName()), + getTargetFolder(), + build_tools::RelativePath::buildTargetFolder); auto path = scriptPath.toUnixStyle(); auto refID = addFileReference (path); @@ -2318,32 +2101,8 @@ private: } } - static Image fixMacIconImageSize (Drawable& image) - { - const int validSizes[] = { 16, 32, 64, 128, 256, 512, 1024 }; - - auto w = image.getWidth(); - auto h = image.getHeight(); - - int bestSize = 16; - - for (int size : validSizes) - { - if (w == h && w == size) - { - bestSize = w; - break; - } - - if (jmax (w, h) > size) - bestSize = size; - } - - return rescaleImageForIcon (image, bestSize); - } - //============================================================================== - XcodeTarget* getTargetOfType (ProjectType::Target::Type type) const + XcodeTarget* getTargetOfType (build_tools::ProjectType::Target::Type type) const { for (auto& target : targets) if (target->type == type) @@ -2410,134 +2169,36 @@ private: return dependencies; } - static void writeIconData (MemoryOutputStream& out, const Image& image, const char* type) - { - MemoryOutputStream pngData; - PNGImageFormat pngFormat; - pngFormat.writeImageToStream (image, pngData); - - out.write (type, 4); - out.writeIntBigEndian (8 + (int) pngData.getDataSize()); - out << pngData; - } - - void writeIcnsFile (const OwnedArray& images, OutputStream& out) const - { - MemoryOutputStream data; - auto smallest = std::numeric_limits::max(); - Drawable* smallestImage = nullptr; - - for (int i = 0; i < images.size(); ++i) - { - auto image = fixMacIconImageSize (*images.getUnchecked (i)); - jassert (image.getWidth() == image.getHeight()); - - if (image.getWidth() < smallest) - { - smallest = image.getWidth(); - smallestImage = images.getUnchecked(i); - } - - switch (image.getWidth()) - { - case 16: writeIconData (data, image, "icp4"); break; - case 32: writeIconData (data, image, "icp5"); break; - case 64: writeIconData (data, image, "icp6"); break; - case 128: writeIconData (data, image, "ic07"); break; - case 256: writeIconData (data, image, "ic08"); break; - case 512: writeIconData (data, image, "ic09"); break; - case 1024: writeIconData (data, image, "ic10"); break; - default: break; - } - } - - jassert (data.getDataSize() > 0); // no suitable sized images? - - // If you only supply a 1024 image, the file doesn't work on 10.8, so we need - // to force a smaller one in there too.. - if (smallest > 512 && smallestImage != nullptr) - writeIconData (data, rescaleImageForIcon (*smallestImage, 512), "ic09"); - - out.write ("icns", 4); - out.writeIntBigEndian ((int) data.getDataSize() + 8); - out << data; - } - - void getIconImages (OwnedArray& images) const - { - if (auto icon = getBigIcon()) - images.add (std::move (icon)); - - if (auto icon = getSmallIcon()) - images.add (std::move (icon)); - } - - void createiOSIconFiles (File appIconSet) const - { - OwnedArray images; - getIconImages (images); - - if (images.size() > 0) - { - for (auto& type : getiOSAppIconTypes()) - { - auto image = rescaleImageForIcon (*images.getFirst(), type.size); - - if (image.hasAlphaChannel()) - { - Image background (Image::RGB, image.getWidth(), image.getHeight(), false); - Graphics g (background); - g.fillAll (Colours::white); - - g.drawImageWithin (image, 0, 0, image.getWidth(), image.getHeight(), - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize); - - image = background; - } - - MemoryOutputStream pngData; - PNGImageFormat pngFormat; - pngFormat.writeImageToStream (image, pngData); - - overwriteFileIfDifferentOrThrow (appIconSet.getChildFile (type.filename), pngData); - } - } - } - void createIconFile() const { - OwnedArray images; - getIconImages (images); + const auto icons = getIcons(); - if (images.size() > 0) + if (! build_tools::asArray (icons).isEmpty()) { - MemoryOutputStream mo; - writeIcnsFile (images, mo); - iconFile = getTargetFolder().getChildFile ("Icon.icns"); - overwriteFileIfDifferentOrThrow (iconFile, mo); + build_tools::writeMacIcon (icons, iconFile); } } void writeWorkspaceSettings() const { - auto settingsFile = getProjectBundle().getChildFile ("project.xcworkspace") - .getChildFile ("xcshareddata") - .getChildFile ("WorkspaceSettings.xcsettings"); + const auto settingsFile = getProjectBundle().getChildFile ("project.xcworkspace") + .getChildFile ("xcshareddata") + .getChildFile ("WorkspaceSettings.xcsettings"); - MemoryOutputStream mo; - mo.setNewLineString ("\n"); + build_tools::writeStreamToFile (settingsFile, [] (MemoryOutputStream& mo) + { + mo.setNewLineString ("\n"); - mo << "" << newLine - << "" << newLine - << "" << newLine - << "" << newLine - << "\t" << "BuildSystemType" << newLine - << "\t" << "Original" << newLine - << "" << newLine - << "" << newLine; - - overwriteFileIfDifferentOrThrow (settingsFile, mo); + mo << "" << newLine + << "" << newLine + << "" << newLine + << "" << newLine + << "\t" << "BuildSystemType" << newLine + << "\t" << "Original" << newLine + << "" << newLine + << "" << newLine; + }); } void writeInfoPlistFiles() const @@ -2571,13 +2232,13 @@ private: return "-l" + library.replace (" ", "\\\\ ").replace ("\"", "\\\\\"").replace ("\'", "\\\\\'").upToLastOccurrenceOf (".", false, false); } - String getSearchPathForStaticLibrary (const RelativePath& library) const + String getSearchPathForStaticLibrary (const build_tools::RelativePath& library) const { auto searchPath = library.toUnixStyle().upToLastOccurrenceOf ("/", false, false); if (! library.isAbsolute()) { - auto srcRoot = rebaseFromProjectFolderToBuildTarget (RelativePath (".", RelativePath::projectFolder)).toUnixStyle(); + auto srcRoot = rebaseFromProjectFolderToBuildTarget (build_tools::RelativePath (".", build_tools::RelativePath::projectFolder)).toUnixStyle(); if (srcRoot.endsWith ("/.")) srcRoot = srcRoot.dropLastCharacters (2); if (! srcRoot.endsWithChar ('/')) srcRoot << '/'; @@ -2828,7 +2489,7 @@ private: if (availableBuildProducts.empty()) continue; - auto subprojectFileType = getFileType (RelativePath (subprojectFile.getFullPathName(), RelativePath::buildTargetFolder)); + auto subprojectFileType = getFileType (build_tools::RelativePath (subprojectFile.getFullPathName(), build_tools::RelativePath::buildTargetFolder)); auto subprojectFileID = addFileOrFolderReference (subprojectFile.getFullPathName(), "", subprojectFileType); subprojectFileIDs.add (subprojectFileID); @@ -2836,7 +2497,7 @@ private: for (auto& buildProduct : availableBuildProducts) { - auto buildProductFileType = getFileType (RelativePath (buildProduct.second, RelativePath::projectFolder)); + auto buildProductFileType = getFileType (build_tools::RelativePath (buildProduct.second, build_tools::RelativePath::projectFolder)); auto containerID = addContainerItemProxy (subprojectFileID, buildProduct.first); auto proxyID = addReferenceProxy (containerID, buildProduct.second, buildProductFileType); @@ -2876,15 +2537,15 @@ private: auto customXcassetsPath = getCustomXcassetsFolderString(); if (customXcassetsPath.isEmpty()) - createXcassetsFolderFromIcons(); + addDefaultXcassetsFolders(); else addCustomResourceFolder (customXcassetsPath, "folder.assetcatalog"); } void addCustomResourceFolder (String folderPathRelativeToProjectFolder, const String fileType = "folder") const { - auto folderPath = RelativePath (folderPathRelativeToProjectFolder, RelativePath::projectFolder) - .rebased (projectFolder, getTargetFolder(), RelativePath::buildTargetFolder) + auto folderPath = build_tools::RelativePath (folderPathRelativeToProjectFolder, build_tools::RelativePath::projectFolder) + .rebased (projectFolder, getTargetFolder(), build_tools::RelativePath::buildTargetFolder) .toUnixStyle(); auto fileRefID = createFileRefID (folderPath); @@ -2962,7 +2623,7 @@ private: return fileID; } - String addBuildFile (const RelativePath& path, bool addToSourceBuildPhase, bool inhibitWarnings, XcodeTarget* xcodeTarget = nullptr) const + String addBuildFile (const build_tools::RelativePath& path, bool addToSourceBuildPhase, bool inhibitWarnings, XcodeTarget* xcodeTarget = nullptr) const { return addBuildFile (path.toUnixStyle(), createFileRefID (path), addToSourceBuildPhase, inhibitWarnings, xcodeTarget); } @@ -2970,7 +2631,7 @@ private: String addFileReference (String pathString) const { String sourceTree ("SOURCE_ROOT"); - RelativePath path (pathString, RelativePath::unknown); + build_tools::RelativePath path (pathString, build_tools::RelativePath::unknown); if (pathString.startsWith ("${")) { @@ -3058,7 +2719,7 @@ public: } private: - static String getFileType (const RelativePath& file) + static String getFileType (const build_tools::RelativePath& file) { if (file.hasFileExtension (cppFileExtensions)) return "sourcecode.cpp.cpp"; if (file.hasFileExtension (".mm")) return "sourcecode.cpp.objcpp"; @@ -3083,7 +2744,7 @@ private: return "file" + file.getFileExtension(); } - String addFile (const RelativePath& path, bool shouldBeCompiled, bool shouldBeAddedToBinaryResources, + String addFile (const build_tools::RelativePath& path, bool shouldBeCompiled, bool shouldBeAddedToBinaryResources, bool shouldBeAddedToXcodeResources, bool inhibitWarnings, XcodeTarget* xcodeTarget, const String& compilerFlags) const { auto pathAsString = path.toUnixStyle(); @@ -3107,7 +2768,7 @@ private: return refID; } - String addRezFile (const Project::Item& projectItem, const RelativePath& path) const + String addRezFile (const Project::Item& projectItem, const build_tools::RelativePath& path) const { auto pathAsString = path.toUnixStyle(); auto refID = addFileReference (path.toUnixStyle()); @@ -3126,97 +2787,28 @@ private: return {}; } - StringPairArray getEntitlements (XcodeTarget& target) const - { - StringPairArray entitlements; - - if (isiOS()) - { - if (project.isAudioPluginProject() && project.shouldEnableIAA()) - entitlements.set ("inter-app-audio", ""); - - if (isiCloudPermissionsEnabled()) - { - entitlements.set ("com.apple.developer.icloud-container-identifiers", - "\n" - " iCloud.$(CFBundleIdentifier)\n" - " "); - - entitlements.set ("com.apple.developer.icloud-services", - "\n" - " CloudDocuments\n" - " "); - - entitlements.set ("com.apple.developer.ubiquity-container-identifiers", - "\n" - " iCloud.$(CFBundleIdentifier)\n" - " "); - } - } - - if (isPushNotificationsEnabled()) - entitlements.set (isiOS() ? "aps-environment" - : "com.apple.developer.aps-environment", - "development"); - - if (isAppGroupsEnabled()) - { - auto appGroups = StringArray::fromTokens (getAppGroupIdString(), ";", {}); - auto groups = String (""); - - for (auto group : appGroups) - groups += "\n\t\t" + group.trim() + ""; - - groups += "\n\t"; - - entitlements.set ("com.apple.security.application-groups", groups); - } - - if (isHardenedRuntimeEnabled()) - for (auto& option : getHardenedRuntimeOptions()) - entitlements.set (option, ""); - - if (isAppSandboxEnabled() || (isOSX() && project.isAudioPluginProject() && target.type == XcodeTarget::AudioUnitv3PlugIn)) - { - entitlements.set ("com.apple.security.app-sandbox", ""); - - if (isAppSandboxInhertianceEnabled()) - { - // no other sandbox options can be specified if sandbox inheritance is enabled! - jassert (getAppSandboxOptions().isEmpty()); - - entitlements.set ("com.apple.security.inherit", ""); - } - - if (isAppSandboxEnabled()) - for (auto& option : getAppSandboxOptions()) - entitlements.set (option, ""); - } - - return entitlements; - } - void addEntitlementsFile (XcodeTarget& target) const { - String content = - "\n" - "\n" - "\n" - "\n"; + build_tools::EntitlementOptions options; - auto entitlements = getEntitlements (target); + options.type = target.type; + options.isiOS = isiOS(); + options.isAudioPluginProject = project.isAudioPluginProject(); + options.shouldEnableIAA = project.shouldEnableIAA(); + options.isiCloudPermissionsEnabled = isiCloudPermissionsEnabled(); + options.isPushNotificationsEnabled = isPushNotificationsEnabled(); + options.isAppGroupsEnabled = isAppGroupsEnabled(); + options.isHardenedRuntimeEnabled = isHardenedRuntimeEnabled(); + options.isAppSandboxEnabled = isAppSandboxEnabled(); + options.isAppSandboxInhertianceEnabled = isAppSandboxInhertianceEnabled(); + options.appGroupIdString = getAppGroupIdString(); + options.hardenedRuntimeOptions = getHardenedRuntimeOptions(); + options.appSandboxOptions = getAppSandboxOptions(); - for (auto& key : entitlements.getAllKeys()) - content += "\t" + key + "\n" - "\t" + entitlements[key] + "\n"; + const auto entitlementsFile = getTargetFolder().getChildFile (target.getEntitlementsFilename()); + build_tools::overwriteFileIfDifferentOrThrow (entitlementsFile, options.getEntitlementsFileContent()); - content += "\n" - "\n"; - - auto entitlementsFile = getTargetFolder().getChildFile (target.getEntitlementsFilename()); - overwriteFileIfDifferentOrThrow (entitlementsFile, content); - - RelativePath entitlementsPath (entitlementsFile, getTargetFolder(), RelativePath::buildTargetFolder); + build_tools::RelativePath entitlementsPath (entitlementsFile, getTargetFolder(), build_tools::RelativePath::buildTargetFolder); addFile (entitlementsPath, false, false, false, false, nullptr, {}); } @@ -3247,12 +2839,12 @@ private: if (projectItem.shouldBeAddedToTargetProject() && projectItem.shouldBeAddedToTargetExporter (*this)) { auto itemPath = projectItem.getFilePath(); - RelativePath path; + build_tools::RelativePath path; if (itemPath.startsWith ("${")) - path = RelativePath (itemPath, RelativePath::unknown); + path = build_tools::RelativePath (itemPath, build_tools::RelativePath::unknown); else - path = RelativePath (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder); + path = build_tools::RelativePath (projectItem.getFile(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder); if (path.hasFileExtension (".r")) return addRezFile (projectItem, path); @@ -3298,7 +2890,7 @@ private: auto fileRefID = createFileRefID (frameworkPath); - auto fileType = getFileType (RelativePath (frameworkPath, RelativePath::projectFolder)); + auto fileType = getFileType (build_tools::RelativePath (frameworkPath, build_tools::RelativePath::projectFolder)); addFileOrFolderReference (frameworkPath, "", fileType); frameworkFileIDs.add (fileRefID); @@ -3310,7 +2902,7 @@ private: { auto fileRefID = createFileRefID (path); - auto fileType = getFileType (RelativePath (path, RelativePath::projectFolder)); + auto fileType = getFileType (build_tools::RelativePath (path, build_tools::RelativePath::projectFolder)); addFileOrFolderReference (path, "", fileType); auto fileID = createID (path + "buildref"); @@ -3488,67 +3080,6 @@ private: return false; } - //============================================================================== - struct AppIconType - { - const char* idiom; - const char* sizeString; - const char* filename; - const char* scale; - int size; - }; - - static Array getiOSAppIconTypes() - { - AppIconType types[] = - { - { "iphone", "20x20", "Icon-Notification-20@2x.png", "2x", 40 }, - { "iphone", "20x20", "Icon-Notification-20@3x.png", "3x", 60 }, - { "iphone", "29x29", "Icon-29.png", "1x", 29 }, - { "iphone", "29x29", "Icon-29@2x.png", "2x", 58 }, - { "iphone", "29x29", "Icon-29@3x.png", "3x", 87 }, - { "iphone", "40x40", "Icon-Spotlight-40@2x.png", "2x", 80 }, - { "iphone", "40x40", "Icon-Spotlight-40@3x.png", "3x", 120 }, - { "iphone", "57x57", "Icon.png", "1x", 57 }, - { "iphone", "57x57", "Icon@2x.png", "2x", 114 }, - { "iphone", "60x60", "Icon-60@2x.png", "2x", 120 }, - { "iphone", "60x60", "Icon-@3x.png", "3x", 180 }, - { "ipad", "20x20", "Icon-Notifications-20.png", "1x", 20 }, - { "ipad", "20x20", "Icon-Notifications-20@2x.png", "2x", 40 }, - { "ipad", "29x29", "Icon-Small-1.png", "1x", 29 }, - { "ipad", "29x29", "Icon-Small@2x-1.png", "2x", 58 }, - { "ipad", "40x40", "Icon-Spotlight-40.png", "1x", 40 }, - { "ipad", "40x40", "Icon-Spotlight-40@2x-1.png", "2x", 80 }, - { "ipad", "50x50", "Icon-Small-50.png", "1x", 50 }, - { "ipad", "50x50", "Icon-Small-50@2x.png", "2x", 100 }, - { "ipad", "72x72", "Icon-72.png", "1x", 72 }, - { "ipad", "72x72", "Icon-72@2x.png", "2x", 144 }, - { "ipad", "76x76", "Icon-76.png", "1x", 76 }, - { "ipad", "76x76", "Icon-76@2x.png", "2x", 152 }, - { "ipad", "83.5x83.5", "Icon-83.5@2x.png", "2x", 167 }, - { "ios-marketing", "1024x1024", "Icon-AppStore-1024.png", "1x", 1024 } - }; - - return Array (types, numElementsInArray (types)); - } - - static String getiOSAppIconContents() - { - var images; - - for (auto& type : getiOSAppIconTypes()) - { - DynamicObject::Ptr d (new DynamicObject()); - d->setProperty ("idiom", type.idiom); - d->setProperty ("size", type.sizeString); - d->setProperty ("filename", type.filename); - d->setProperty ("scale", type.scale); - images.append (var (d.get())); - } - - return getiOSAssetContents (images); - } - String getProjectObjectAttributes() const { String attributes; @@ -3573,114 +3104,18 @@ private: } //============================================================================== - struct ImageType - { - const char* orientation; - const char* idiom; - const char* subtype; - const char* extent; - const char* scale; - const char* filename; - int width; - int height; - }; - - static Array getiOSLaunchImageTypes() - { - ImageType types[] = - { - { "portrait", "iphone", nullptr, "full-screen", "2x", "LaunchImage-iphone-2x.png", 640, 960 }, - { "portrait", "iphone", "retina4", "full-screen", "2x", "LaunchImage-iphone-retina4.png", 640, 1136 }, - { "portrait", "ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-portrait-1x.png", 768, 1024 }, - { "landscape","ipad", nullptr, "full-screen", "1x", "LaunchImage-ipad-landscape-1x.png", 1024, 768 }, - { "portrait", "ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-portrait-2x.png", 1536, 2048 }, - { "landscape","ipad", nullptr, "full-screen", "2x", "LaunchImage-ipad-landscape-2x.png", 2048, 1536 } - }; - - return Array (types, numElementsInArray (types)); - } - - static String getiOSLaunchImageContents() - { - var images; - - for (auto& type : getiOSLaunchImageTypes()) - { - DynamicObject::Ptr d (new DynamicObject()); - d->setProperty ("orientation", type.orientation); - d->setProperty ("idiom", type.idiom); - d->setProperty ("extent", type.extent); - d->setProperty ("minimum-system-version", "7.0"); - d->setProperty ("scale", type.scale); - d->setProperty ("filename", type.filename); - - if (type.subtype != nullptr) - d->setProperty ("subtype", type.subtype); - - images.append (var (d.get())); - } - - return getiOSAssetContents (images); - } - - static void createiOSLaunchImageFiles (const File& launchImageSet) - { - for (auto& type : getiOSLaunchImageTypes()) - { - Image image (Image::ARGB, type.width, type.height, true); // (empty black image) - image.clear (image.getBounds(), Colours::black); - - MemoryOutputStream pngData; - PNGImageFormat pngFormat; - pngFormat.writeImageToStream (image, pngData); - overwriteFileIfDifferentOrThrow (launchImageSet.getChildFile (type.filename), pngData); - } - } - - //============================================================================== - static String getiOSAssetContents (var images) - { - DynamicObject::Ptr v (new DynamicObject()); - - var info (new DynamicObject()); - info.getDynamicObject()->setProperty ("version", 1); - info.getDynamicObject()->setProperty ("author", "xcode"); - - v->setProperty ("images", images); - v->setProperty ("info", info); - - return JSON::toString (var (v.get())); - } - void writeDefaultLaunchStoryboardFile() const { - auto storyboardFile = getTargetFolder().getChildFile (getDefaultLaunchStoryboardName() + ".storyboard"); + const auto storyboardFile = getTargetFolder().getChildFile (getDefaultLaunchStoryboardName() + ".storyboard"); - MemoryOutputStream mo; - mo.setNewLineString ("\n"); + build_tools::writeStreamToFile (storyboardFile, [&] (MemoryOutputStream& mo) + { + mo << String (BinaryData::LaunchScreen_storyboard); + }); - mo << "" << newLine - << "" << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << " " << newLine - << "" << newLine; - - overwriteFileIfDifferentOrThrow (storyboardFile, mo); - - addLaunchStoryboardFileReference (RelativePath (storyboardFile, getTargetFolder(), RelativePath::buildTargetFolder).toUnixStyle()); + addLaunchStoryboardFileReference (build_tools::RelativePath (storyboardFile, + getTargetFolder(), + build_tools::RelativePath::buildTargetFolder).toUnixStyle()); } void addLaunchStoryboardFileReference (const String& relativePath) const @@ -3692,20 +3127,11 @@ private: resourceFileRefs.add (refID); } - void createXcassetsFolderFromIcons() const + void addDefaultXcassetsFolders() const { - auto assets = getTargetFolder().getChildFile (project.getProjectFilenameRootString()) - .getChildFile ("Images.xcassets"); - auto iconSet = assets.getChildFile ("AppIcon.appiconset"); - auto launchImage = assets.getChildFile ("LaunchImage.launchimage"); - - overwriteFileIfDifferentOrThrow (iconSet.getChildFile ("Contents.json"), getiOSAppIconContents()); - createiOSIconFiles (iconSet); - - overwriteFileIfDifferentOrThrow (launchImage.getChildFile ("Contents.json"), getiOSLaunchImageContents()); - createiOSLaunchImageFiles (launchImage); - - RelativePath assetsPath (assets, getTargetFolder(), RelativePath::buildTargetFolder); + const auto assetsPath = build_tools::createXcassetsFolderFromIcons (getIcons(), + getTargetFolder(), + project.getProjectFilenameRootString()); addFileReference (assetsPath.toUnixStyle()); resourceIDs.add (addBuildFile (assetsPath, false, false)); resourceFileRefs.add (createFileRefID (assetsPath)); @@ -3739,7 +3165,7 @@ private: return MD5 (rootString.toUTF8()).toHexString().substring (0, 24).toUpperCase(); } - String createFileRefID (const RelativePath& path) const { return createFileRefID (path.toUnixStyle()); } + String createFileRefID (const build_tools::RelativePath& path) const { return createFileRefID (path.toUnixStyle()); } String createFileRefID (const String& path) const { return createID ("__fileref_" + path); } String getIDForGroup (const Project::Item& item) const { return createID (item.getID()); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp index 69aa10373d..b1abe885f0 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp @@ -274,9 +274,9 @@ File ProjectExporter::getTargetFolder() const return project.resolveFilename (getTargetLocationString()); } -RelativePath ProjectExporter::rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const +build_tools::RelativePath ProjectExporter::rebaseFromProjectFolderToBuildTarget (const build_tools::RelativePath& path) const { - return path.rebased (project.getProjectFolder(), getTargetFolder(), RelativePath::buildTargetFolder); + return path.rebased (project.getProjectFolder(), getTargetFolder(), build_tools::RelativePath::buildTargetFolder); } bool ProjectExporter::shouldFileBeCompiledByDefault (const File& file) const @@ -302,7 +302,7 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) "The location of the folder in which the " + name + " project will be created. " "This path can be absolute, but it's much more sensible to make it relative to the jucer project directory."); - if ((shouldBuildTargetType (ProjectType::Target::VSTPlugIn) && project.shouldBuildVST()) || (project.isVSTPluginHost() && supportsTargetType (ProjectType::Target::VSTPlugIn))) + if ((shouldBuildTargetType (build_tools::ProjectType::Target::VSTPlugIn) && project.shouldBuildVST()) || (project.isVSTPluginHost() && supportsTargetType (build_tools::ProjectType::Target::VSTPlugIn))) { props.add (new FilePathPropertyComponent (vstLegacyPathValueWrapper.wrappedValue, "VST (Legacy) SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS(), "*", project.getProjectFolder()), @@ -310,7 +310,7 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) "This can be an absolute path, or a path relative to the Projucer project file."); } - if ((shouldBuildTargetType (ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) || (project.isVST3PluginHost() && supportsTargetType (ProjectType::Target::VST3PlugIn))) + if ((shouldBuildTargetType (build_tools::ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) || (project.isVST3PluginHost() && supportsTargetType (build_tools::ProjectType::Target::VST3PlugIn))) { props.add (new FilePathPropertyComponent (vst3PathValueWrapper.wrappedValue, "VST3 SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS(), "*", project.getProjectFolder()), @@ -318,14 +318,14 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) "This can be an absolute path, or a path relative to the Projucer project file."); } - if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn) && project.shouldBuildAAX()) + if (shouldBuildTargetType (build_tools::ProjectType::Target::AAXPlugIn) && project.shouldBuildAAX()) { props.add (new FilePathPropertyComponent (aaxPathValueWrapper.wrappedValue, "AAX SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS(), "*", project.getProjectFolder()), "If you're building an AAX plug-in, this must be the folder containing the AAX SDK. This can be an absolute path, or a path relative to the Projucer project file."); } - if (shouldBuildTargetType (ProjectType::Target::RTASPlugIn) && project.shouldBuildRTAS()) + if (shouldBuildTargetType (build_tools::ProjectType::Target::RTASPlugIn) && project.shouldBuildRTAS()) { props.add (new FilePathPropertyComponent (rtasPathValueWrapper.wrappedValue, "RTAS SDK Folder", true, getTargetOSForExporter() == TargetOS::getThisOS(), "*", project.getProjectFolder()), @@ -390,7 +390,7 @@ void ProjectExporter::createIconProperties (PropertyListBuilder& props) } //============================================================================== -void ProjectExporter::addSettingsForProjectType (const ProjectType& type) +void ProjectExporter::addSettingsForProjectType (const build_tools::ProjectType& type) { addVSTPathsIfPluginOrHost(); @@ -402,8 +402,8 @@ void ProjectExporter::addSettingsForProjectType (const ProjectType& type) void ProjectExporter::addVSTPathsIfPluginOrHost() { - if (((shouldBuildTargetType (ProjectType::Target::VSTPlugIn) && project.shouldBuildVST()) || project.isVSTPluginHost()) - || ((shouldBuildTargetType (ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) || project.isVST3PluginHost())) + if (((shouldBuildTargetType (build_tools::ProjectType::Target::VSTPlugIn) && project.shouldBuildVST()) || project.isVSTPluginHost()) + || ((shouldBuildTargetType (build_tools::ProjectType::Target::VST3PlugIn) && project.shouldBuildVST3()) || project.isVST3PluginHost())) { addLegacyVSTFolderToPathIfSpecified(); addVST3FolderToPath(); @@ -412,7 +412,7 @@ void ProjectExporter::addVSTPathsIfPluginOrHost() void ProjectExporter::addCommonAudioPluginSettings() { - if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn)) + if (shouldBuildTargetType (build_tools::ProjectType::Target::AAXPlugIn)) addAAXFoldersToPath(); // Note: RTAS paths are platform-dependent, impl -> addPlatformSpecificSettingsForProjectType @@ -423,10 +423,10 @@ void ProjectExporter::addLegacyVSTFolderToPathIfSpecified() auto vstFolder = getVSTLegacyPathString(); if (vstFolder.isNotEmpty()) - addToExtraSearchPaths (RelativePath (vstFolder, RelativePath::projectFolder), 0); + addToExtraSearchPaths (build_tools::RelativePath (vstFolder, build_tools::RelativePath::projectFolder), 0); } -RelativePath ProjectExporter::getInternalVST3SDKPath() +build_tools::RelativePath ProjectExporter::getInternalVST3SDKPath() { return getModuleFolderRelativeToProject ("juce_audio_processors") .getChildFile ("format_types") @@ -438,7 +438,7 @@ void ProjectExporter::addVST3FolderToPath() auto vst3Folder = getVST3PathString(); if (vst3Folder.isNotEmpty()) - addToExtraSearchPaths (RelativePath (vst3Folder, RelativePath::projectFolder), 0); + addToExtraSearchPaths (build_tools::RelativePath (vst3Folder, build_tools::RelativePath::projectFolder), 0); else addToExtraSearchPaths (getInternalVST3SDKPath(), 0); } @@ -449,7 +449,7 @@ void ProjectExporter::addAAXFoldersToPath() if (aaxFolder.isNotEmpty()) { - RelativePath aaxFolderPath (aaxFolder, RelativePath::projectFolder); + build_tools::RelativePath aaxFolderPath (aaxFolder, build_tools::RelativePath::projectFolder); addToExtraSearchPaths (aaxFolderPath); addToExtraSearchPaths (aaxFolderPath.getChildFile ("Interfaces")); @@ -458,7 +458,7 @@ void ProjectExporter::addAAXFoldersToPath() } //============================================================================== -StringPairArray ProjectExporter::getAllPreprocessorDefs (const BuildConfiguration& config, const ProjectType::Target::Type targetType) const +StringPairArray ProjectExporter::getAllPreprocessorDefs (const BuildConfiguration& config, const build_tools::ProjectType::Target::Type targetType) const { auto defs = mergePreprocessorDefs (config.getAllPreprocessorDefs(), parsePreprocessorDefs (getExporterPreprocessorDefsString())); @@ -476,27 +476,27 @@ StringPairArray ProjectExporter::getAllPreprocessorDefs() const return defs; } -void ProjectExporter::addTargetSpecificPreprocessorDefs (StringPairArray& defs, const ProjectType::Target::Type targetType) const +void ProjectExporter::addTargetSpecificPreprocessorDefs (StringPairArray& defs, const build_tools::ProjectType::Target::Type targetType) const { - std::pair targetFlags[] = { - {"JucePlugin_Build_VST", ProjectType::Target::VSTPlugIn}, - {"JucePlugin_Build_VST3", ProjectType::Target::VST3PlugIn}, - {"JucePlugin_Build_AU", ProjectType::Target::AudioUnitPlugIn}, - {"JucePlugin_Build_AUv3", ProjectType::Target::AudioUnitv3PlugIn}, - {"JucePlugin_Build_RTAS", ProjectType::Target::RTASPlugIn}, - {"JucePlugin_Build_AAX", ProjectType::Target::AAXPlugIn}, - {"JucePlugin_Build_Standalone", ProjectType::Target::StandalonePlugIn}, - {"JucePlugin_Build_Unity", ProjectType::Target::UnityPlugIn} + std::pair targetFlags[] = { + {"JucePlugin_Build_VST", build_tools::ProjectType::Target::VSTPlugIn}, + {"JucePlugin_Build_VST3", build_tools::ProjectType::Target::VST3PlugIn}, + {"JucePlugin_Build_AU", build_tools::ProjectType::Target::AudioUnitPlugIn}, + {"JucePlugin_Build_AUv3", build_tools::ProjectType::Target::AudioUnitv3PlugIn}, + {"JucePlugin_Build_RTAS", build_tools::ProjectType::Target::RTASPlugIn}, + {"JucePlugin_Build_AAX", build_tools::ProjectType::Target::AAXPlugIn}, + {"JucePlugin_Build_Standalone", build_tools::ProjectType::Target::StandalonePlugIn}, + {"JucePlugin_Build_Unity", build_tools::ProjectType::Target::UnityPlugIn} }; - if (targetType == ProjectType::Target::SharedCodeTarget) + if (targetType == build_tools::ProjectType::Target::SharedCodeTarget) { for (auto& flag : targetFlags) defs.set (flag.first, (shouldBuildTargetType (flag.second) ? "1" : "0")); defs.set ("JUCE_SHARED_CODE", "1"); } - else if (targetType != ProjectType::Target::unspecified) + else if (targetType != build_tools::ProjectType::Target::unspecified) { for (auto& flag : targetFlags) defs.set (flag.first, (targetType == flag.second ? "1" : "0")); @@ -513,7 +513,8 @@ void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const String ProjectExporter::replacePreprocessorTokens (const ProjectExporter::BuildConfiguration& config, const String& sourceString) const { - return replacePreprocessorDefs (getAllPreprocessorDefs (config, ProjectType::Target::unspecified), sourceString); + return build_tools::replacePreprocessorDefs (getAllPreprocessorDefs (config, + build_tools::ProjectType::Target::unspecified), sourceString); } void ProjectExporter::copyMainGroupFromProject() @@ -534,9 +535,11 @@ Project::Item& ProjectExporter::getModulesGroup() return *modulesGroup; } -void ProjectExporter::addProjectPathToBuildPathList (StringArray& pathList, const RelativePath& pathFromProjectFolder, int index) const +void ProjectExporter::addProjectPathToBuildPathList (StringArray& pathList, + const build_tools::RelativePath& pathFromProjectFolder, + int index) const { - auto localPath = RelativePath (rebaseFromProjectFolderToBuildTarget (pathFromProjectFolder)); + auto localPath = build_tools::RelativePath (rebaseFromProjectFolderToBuildTarget (pathFromProjectFolder)); auto path = isVisualStudio() ? localPath.toWindowsStyle() : localPath.toUnixStyle(); @@ -544,12 +547,12 @@ void ProjectExporter::addProjectPathToBuildPathList (StringArray& pathList, cons pathList.insert (index, path); } -void ProjectExporter::addToModuleLibPaths (const RelativePath& pathFromProjectFolder) +void ProjectExporter::addToModuleLibPaths (const build_tools::RelativePath& pathFromProjectFolder) { addProjectPathToBuildPathList (moduleLibSearchPaths, pathFromProjectFolder); } -void ProjectExporter::addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index) +void ProjectExporter::addToExtraSearchPaths (const build_tools::RelativePath& pathFromProjectFolder, int index) { addProjectPathToBuildPathList (extraSearchPaths, pathFromProjectFolder, index); } @@ -608,18 +611,18 @@ TargetOS::OS ProjectExporter::getTargetOSForExporter() const return targetOS; } -RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID) const +build_tools::RelativePath ProjectExporter::getModuleFolderRelativeToProject (const String& moduleID) const { if (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID)) - return RelativePath (project.getRelativePathForFile (project.getLocalModuleFolder (moduleID)), - RelativePath::projectFolder); + return build_tools::RelativePath (project.getRelativePathForFile (project.getLocalModuleFolder (moduleID)), + build_tools::RelativePath::projectFolder); auto path = getPathForModuleString (moduleID); if (path.isEmpty()) return getLegacyModulePath (moduleID).getChildFile (moduleID); - return RelativePath (path, RelativePath::projectFolder).getChildFile (moduleID); + return build_tools::RelativePath (path, build_tools::RelativePath::projectFolder).getChildFile (moduleID); } String ProjectExporter::getLegacyModulePath() const @@ -627,19 +630,19 @@ String ProjectExporter::getLegacyModulePath() const return getSettingString ("juceFolder"); } -RelativePath ProjectExporter::getLegacyModulePath (const String& moduleID) const +build_tools::RelativePath ProjectExporter::getLegacyModulePath (const String& moduleID) const { if (project.getEnabledModules().shouldCopyModuleFilesLocally (moduleID)) - return RelativePath (project.getRelativePathForFile (project.getGeneratedCodeFolder() - .getChildFile ("modules") - .getChildFile (moduleID)), RelativePath::projectFolder); + return build_tools::RelativePath (project.getRelativePathForFile (project.getGeneratedCodeFolder() + .getChildFile ("modules") + .getChildFile (moduleID)), build_tools::RelativePath::projectFolder); auto oldJucePath = getLegacyModulePath(); if (oldJucePath.isEmpty()) - return RelativePath(); + return build_tools::RelativePath(); - RelativePath p (oldJucePath, RelativePath::projectFolder); + build_tools::RelativePath p (oldJucePath, build_tools::RelativePath::projectFolder); if (p.getFileName() != "modules") p = p.getChildFile ("modules"); @@ -813,64 +816,6 @@ std::unique_ptr ProjectExporter::getSmallIcon() const return project.getMainGroup().findItemWithID (settings [Ids::smallIcon]).loadAsImageFile(); } -Image ProjectExporter::getBestIconForSize (int size, bool returnNullIfNothingBigEnough) const -{ - Drawable* im = nullptr; - - auto im1 = getSmallIcon(); - auto im2 = getBigIcon(); - - if (im1 != nullptr && im2 != nullptr) - { - if (im1->getWidth() >= size && im2->getWidth() >= size) - im = im1->getWidth() < im2->getWidth() ? im1.get() : im2.get(); - else if (im1->getWidth() >= size) - im = im1.get(); - else if (im2->getWidth() >= size) - im = im2.get(); - } - else - { - im = im1 != nullptr ? im1.get() : im2.get(); - } - - if (im == nullptr) - return {}; - - if (returnNullIfNothingBigEnough && im->getWidth() < size && im->getHeight() < size) - return {}; - - return rescaleImageForIcon (*im, size); -} - -Image ProjectExporter::rescaleImageForIcon (Drawable& d, const int size) -{ - if (auto* drawableImage = dynamic_cast (&d)) - { - auto im = SoftwareImageType().convert (drawableImage->getImage()); - - if (im.getWidth() == size && im.getHeight() == size) - return im; - - // (scale it down in stages for better resampling) - while (im.getWidth() > 2 * size && im.getHeight() > 2 * size) - im = im.rescaled (im.getWidth() / 2, - im.getHeight() / 2); - - Image newIm (Image::ARGB, size, size, true, SoftwareImageType()); - Graphics g (newIm); - g.drawImageWithin (im, 0, 0, size, size, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); - return newIm; - } - - Image im (Image::ARGB, size, size, true, SoftwareImageType()); - Graphics g (im); - d.drawWithin (g, im.getBounds().toFloat(), RectanglePlacement::centred, 1.0f); - return im; -} - - //============================================================================== ProjectExporter::ConfigIterator::ConfigIterator (ProjectExporter& e) : index (-1), exporter (e) diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h index f22bf58ad8..84d4243603 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h @@ -95,18 +95,18 @@ public: //============================================================================== // cross-platform audio plug-ins supported by exporter - virtual bool supportsTargetType (ProjectType::Target::Type type) const = 0; + virtual bool supportsTargetType (build_tools::ProjectType::Target::Type type) const = 0; - inline bool shouldBuildTargetType (ProjectType::Target::Type type) const + inline bool shouldBuildTargetType (build_tools::ProjectType::Target::Type type) const { return project.shouldBuildTargetType (type) && supportsTargetType (type); } - inline void callForAllSupportedTargets (std::function callback) + inline void callForAllSupportedTargets (std::function callback) { - for (int i = 0; i < ProjectType::Target::unspecified; ++i) - if (shouldBuildTargetType (static_cast (i))) - callback (static_cast (i)); + for (int i = 0; i < build_tools::ProjectType::Target::unspecified; ++i) + if (shouldBuildTargetType (static_cast (i))) + callback (static_cast (i)); } //============================================================================== @@ -158,22 +158,22 @@ public: TargetOS::OS getTargetOSForExporter() const; - RelativePath getLegacyModulePath (const String& moduleID) const; + build_tools::RelativePath getLegacyModulePath (const String& moduleID) const; String getLegacyModulePath() const; // Returns a path to the actual module folder itself - RelativePath getModuleFolderRelativeToProject (const String& moduleID) const; + build_tools::RelativePath getModuleFolderRelativeToProject (const String& moduleID) const; void updateOldModulePaths(); - RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const; - void addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index = -1); - void addToModuleLibPaths (const RelativePath& pathFromProjectFolder); + build_tools::RelativePath rebaseFromProjectFolderToBuildTarget (const build_tools::RelativePath& path) const; + void addToExtraSearchPaths (const build_tools::RelativePath& pathFromProjectFolder, int index = -1); + void addToModuleLibPaths (const build_tools::RelativePath& pathFromProjectFolder); - void addProjectPathToBuildPathList (StringArray&, const RelativePath&, int index = -1) const; + void addProjectPathToBuildPathList (StringArray&, const build_tools::RelativePath&, int index = -1) const; std::unique_ptr getBigIcon() const; std::unique_ptr getSmallIcon() const; - Image getBestIconForSize (int size, bool returnNullIfNothingBigEnough) const; + build_tools::Icons getIcons() const { return { getSmallIcon(), getBigIcon() }; } String getExporterIdentifierMacro() const { @@ -182,21 +182,8 @@ public: } // An exception that can be thrown by the create() method. - class SaveError - { - public: - SaveError (const String& error) : message (error) - {} - - SaveError (const File& fileThatFailedToWrite) - : message ("Can't write to the file: " + fileThatFailedToWrite.getFullPathName()) - {} - - String message; - }; - void createPropertyEditors (PropertyListBuilder&); - void addSettingsForProjectType (const ProjectType&); + void addSettingsForProjectType (const build_tools::ProjectType&); //============================================================================== void copyMainGroupFromProject(); @@ -339,11 +326,11 @@ public: String getExporterPreprocessorDefsString() const { return extraPPDefsValue.get(); } // includes exporter, project + config defs - StringPairArray getAllPreprocessorDefs (const BuildConfiguration& config, const ProjectType::Target::Type targetType) const; + StringPairArray getAllPreprocessorDefs (const BuildConfiguration& config, const build_tools::ProjectType::Target::Type targetType) const; // includes exporter + project defs.. StringPairArray getAllPreprocessorDefs() const; - void addTargetSpecificPreprocessorDefs (StringPairArray& defs, const ProjectType::Target::Type targetType) const; + void addTargetSpecificPreprocessorDefs (StringPairArray& defs, const build_tools::ProjectType::Target::Type targetType) const; String replacePreprocessorTokens (const BuildConfiguration&, const String& sourceString) const; @@ -363,7 +350,7 @@ protected: //============================================================================== String name; Project& project; - const ProjectType& projectType; + const build_tools::ProjectType& projectType; const String projectName; const File projectFolder; @@ -418,25 +405,13 @@ protected: static String getStaticLibbedFilename (String name) { return addSuffix (addLibPrefix (name), ".a"); } static String getDynamicLibbedFilename (String name) { return addSuffix (addLibPrefix (name), ".so"); } - virtual void addPlatformSpecificSettingsForProjectType (const ProjectType&) = 0; + virtual void addPlatformSpecificSettingsForProjectType (const build_tools::ProjectType&) = 0; //============================================================================== - static void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData) - { - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (file, newData)) - throw SaveError (file); - } - - static void overwriteFileIfDifferentOrThrow (const File& file, const String& newData) - { - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (file, newData)) - throw SaveError (file); - } - static void createDirectoryOrThrow (const File& dirToCreate) { if (! dirToCreate.createDirectory()) - throw SaveError ("Can't create folder: " + dirToCreate.getFullPathName()); + throw build_tools::SaveError ("Can't create folder: " + dirToCreate.getFullPathName()); } static void writeXmlOrThrow (const XmlElement& xml, const File& file, const String& encoding, @@ -449,11 +424,9 @@ protected: MemoryOutputStream mo (8192); xml.writeTo (mo, format); - overwriteFileIfDifferentOrThrow (file, mo); + build_tools::overwriteFileIfDifferentOrThrow (file, mo); } - static Image rescaleImageForIcon (Drawable&, int iconSize); - private: //============================================================================== void valueChanged (Value&) override { updateCompilerFlagValues(); } @@ -477,7 +450,7 @@ private: void addVSTPathsIfPluginOrHost(); void addCommonAudioPluginSettings(); void addLegacyVSTFolderToPathIfSpecified(); - RelativePath getInternalVST3SDKPath(); + build_tools::RelativePath getInternalVST3SDKPath(); void addVST3FolderToPath(); void addAAXFoldersToPath(); diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp index 00bcfdd0e0..84230b30cc 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.cpp @@ -179,7 +179,7 @@ void ProjectSaver::writeProjects (const OwnedArray& modules, cons exporter->copyMainGroupFromProject(); exporter->settings = exporter->settings.createCopy(); - exporter->addToExtraSearchPaths (RelativePath ("JuceLibraryCode", RelativePath::projectFolder)); + exporter->addToExtraSearchPaths (build_tools::RelativePath ("JuceLibraryCode", build_tools::RelativePath::projectFolder)); generatedFilesGroup.state = originalGeneratedGroup.createCopy(); exporter->addSettingsForProjectType (project.getProjectType()); @@ -202,7 +202,7 @@ void ProjectSaver::writeProjects (const OwnedArray& modules, cons } } } - catch (ProjectExporter::SaveError& saveError) + catch (build_tools::SaveError& saveError) { addError (saveError.message); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h index 9c8c4f42f9..de0b4161ae 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h @@ -214,7 +214,7 @@ public: { filesCreated.add (f); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (f, newData)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (f, newData)) { addError ("Can't write to file: " + f.getFullPathName()); return false; @@ -615,7 +615,7 @@ private: { auto binaryDataH = project.getBinaryDataHeaderFile(); - ResourceFile resourceFile (project); + JucerResourceFile resourceFile (project); if (resourceFile.getNumFiles() > 0) { @@ -626,20 +626,18 @@ private: resourceFile.setClassName (dataNamespace); - Array binaryDataFiles; - auto maxSize = project.getMaxBinaryFileSize(); if (maxSize <= 0) maxSize = 10 * 1024 * 1024; - auto r = resourceFile.write (binaryDataFiles, maxSize); + auto r = resourceFile.write (maxSize); - if (r.wasOk()) + if (r.result.wasOk()) { hasBinaryData = true; - for (auto& f : binaryDataFiles) + for (auto& f : r.filesCreated) { filesCreated.add (f); generatedFilesGroup.addFileRetainingSortOrder (f, ! f.hasFileExtension (".h")); @@ -647,7 +645,7 @@ private: } else { - addError (r.getErrorMessage()); + addError (r.result.getErrorMessage()); } } else @@ -690,15 +688,15 @@ private: void writeUnityScriptFile() { - auto unityScriptContents = replaceLineFeeds (BinaryData::jucer_UnityPluginGUIScript_cs, + auto unityScriptContents = replaceLineFeeds (BinaryData::UnityPluginGUIScript_cs_in, projectLineFeed); auto projectName = Project::addUnityPluginPrefixIfNecessary (project.getProjectNameString()); - unityScriptContents = unityScriptContents.replace ("%%plugin_class_name%%", projectName.replace (" ", "_")) - .replace ("%%plugin_name%%", projectName) - .replace ("%%plugin_vendor%%", project.getPluginManufacturerString()) - .replace ("%%plugin_description%%", project.getPluginDescriptionString()); + unityScriptContents = unityScriptContents.replace ("${plugin_class_name}", projectName.replace (" ", "_")) + .replace ("${plugin_name}", projectName) + .replace ("${plugin_vendor}", project.getPluginManufacturerString()) + .replace ("${plugin_description}", project.getPluginDescriptionString()); auto f = getGeneratedCodeFolder().getChildFile (project.getUnityScriptName()); @@ -759,7 +757,7 @@ private: if (! exporter->isCLion()) std::cout << "Finished saving: " << exporter->getName() << std::endl; } - catch (ProjectExporter::SaveError& error) + catch (build_tools::SaveError& error) { addError (error.message); } diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.cpp index 5f5c89a0f7..32c865482d 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.cpp @@ -19,20 +19,18 @@ #include "../Application/jucer_Headers.h" #include "jucer_ResourceFile.h" -static const char* resourceFileIdentifierString = "JUCER_BINARY_RESOURCE"; - //============================================================================== -ResourceFile::ResourceFile (Project& p) : project (p) +JucerResourceFile::JucerResourceFile (Project& p) : project (p) { addResourcesFromProjectItem (project.getMainGroup()); } -ResourceFile::~ResourceFile() +JucerResourceFile::~JucerResourceFile() { } //============================================================================== -void ResourceFile::addResourcesFromProjectItem (const Project::Item& projectItem) +void JucerResourceFile::addResourcesFromProjectItem (const Project::Item& projectItem) { if (projectItem.isGroup()) { @@ -45,258 +43,3 @@ void ResourceFile::addResourcesFromProjectItem (const Project::Item& projectItem addFile (projectItem.getFile()); } } - -//============================================================================== -void ResourceFile::setClassName (const String& name) -{ - className = name; -} - -void ResourceFile::addFile (const File& file) -{ - files.add (file); - - auto variableNameRoot = CodeHelpers::makeBinaryDataIdentifierName (file); - auto variableName = variableNameRoot; - - int suffix = 2; - while (variableNames.contains (variableName)) - variableName = variableNameRoot + String (suffix++); - - variableNames.add (variableName); -} - -String ResourceFile::getDataVariableFor (const File& file) const -{ - jassert (files.indexOf (file) >= 0); - return variableNames [files.indexOf (file)]; -} - -String ResourceFile::getSizeVariableFor (const File& file) const -{ - jassert (files.indexOf (file) >= 0); - return variableNames [files.indexOf (file)] + "Size"; -} - -int64 ResourceFile::getTotalDataSize() const -{ - int64 total = 0; - - for (int i = 0; i < files.size(); ++i) - total += files.getReference(i).getSize(); - - return total; -} - -static void writeComment (MemoryOutputStream& mo) -{ - mo << newLine << newLine - << " This is an auto-generated file: Any edits you make may be overwritten!" << newLine - << newLine - << "*/" << newLine - << newLine; -} - -Result ResourceFile::writeHeader (MemoryOutputStream& header) -{ - header << "/* ========================================================================================="; - writeComment (header); - header << "#pragma once" << newLine - << newLine - << "namespace " << className << newLine - << "{" << newLine; - - for (int i = 0; i < files.size(); ++i) - { - auto& file = files.getReference(i); - - if (! file.existsAsFile()) - return Result::fail ("Can't open resource file: " + file.getFullPathName()); - - auto dataSize = file.getSize(); - - auto variableName = variableNames[i]; - - FileInputStream fileStream (file); - - if (fileStream.openedOk()) - { - header << " extern const char* " << variableName << ";" << newLine; - header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine; - } - } - - header << " // Number of elements in the namedResourceList and originalFileNames arrays." << newLine - << " const int namedResourceListSize = " << files.size() << ";" << newLine - << newLine - << " // Points to the start of a list of resource names." << newLine - << " extern const char* namedResourceList[];" << newLine - << newLine - << " // Points to the start of a list of resource filenames." << newLine - << " extern const char* originalFilenames[];" << newLine - << newLine - << " // If you provide the name of one of the binary resource variables above, this function will" << newLine - << " // return the corresponding data and its size (or a null pointer if the name isn't found)." << newLine - << " const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes);" << newLine - << newLine - << " // If you provide the name of one of the binary resource variables above, this function will" << newLine - << " // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found)." << newLine - << " const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine - << "}" << newLine; - - return Result::ok(); -} - -Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize) -{ - bool isFirstFile = (i == 0); - - cpp << "/* ==================================== " << resourceFileIdentifierString << " ===================================="; - writeComment (cpp); - cpp << "namespace " << className << newLine - << "{" << newLine; - - while (i < files.size()) - { - auto& file = files.getReference(i); - auto variableName = variableNames[i]; - - FileInputStream fileStream (file); - - if (fileStream.openedOk()) - { - auto tempVariable = "temp_binary_data_" + String (i); - - cpp << newLine << "//================== " << file.getFileName() << " ==================" << newLine - << "static const unsigned char " << tempVariable << "[] =" << newLine; - - { - MemoryBlock data; - fileStream.readIntoMemoryBlock (data); - CodeHelpers::writeDataAsCppLiteral (data, cpp, true, true); - } - - cpp << newLine << newLine - << "const char* " << variableName << " = (const char*) " << tempVariable << ";" << newLine; - } - - ++i; - - if (cpp.getPosition() > maxFileSize) - break; - } - - if (isFirstFile) - { - if (i < files.size()) - { - cpp << newLine - << "}" << newLine - << newLine - << "#include \"" << headerFile.getFileName() << "\"" << newLine - << newLine - << "namespace " << className << newLine - << "{"; - } - - cpp << newLine - << newLine - << "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)" << newLine - << "{" << newLine; - - StringArray returnCodes; - for (auto& file : files) - { - auto dataSize = file.getSize(); - returnCodes.add ("numBytes = " + String (dataSize) + "; return " + variableNames[files.indexOf (file)] + ";"); - } - - CodeHelpers::createStringMatcher (cpp, "resourceNameUTF8", variableNames, returnCodes, 4); - - cpp << " numBytes = 0;" << newLine - << " return nullptr;" << newLine - << "}" << newLine - << newLine; - - cpp << "const char* namedResourceList[] =" << newLine - << "{" << newLine; - - for (int j = 0; j < files.size(); ++j) - cpp << " " << variableNames[j].quoted() << (j < files.size() - 1 ? "," : "") << newLine; - - cpp << "};" << newLine << newLine; - - cpp << "const char* originalFilenames[] =" << newLine - << "{" << newLine; - - for (auto& f : files) - cpp << " " << f.getFileName().quoted() << (files.indexOf (f) < files.size() - 1 ? "," : "") << newLine; - - cpp << "};" << newLine << newLine; - - cpp << "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8)" << newLine - << "{" << newLine - << " for (unsigned int i = 0; i < (sizeof (namedResourceList) / sizeof (namedResourceList[0])); ++i)" << newLine - << " {" << newLine - << " if (namedResourceList[i] == resourceNameUTF8)" << newLine - << " return originalFilenames[i];" << newLine - << " }" << newLine - << newLine - << " return nullptr;" << newLine - << "}" << newLine - << newLine; - } - - cpp << "}" << newLine; - - return Result::ok(); -} - -Result ResourceFile::write (Array& filesCreated, const int maxFileSize) -{ - auto projectLineFeed = project.getProjectLineFeed(); - - auto headerFile = project.getBinaryDataHeaderFile(); - - { - MemoryOutputStream mo; - mo.setNewLineString (projectLineFeed); - - auto r = writeHeader (mo); - - if (r.failed()) - return r; - - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (headerFile, mo)) - return Result::fail ("Can't write to file: " + headerFile.getFullPathName()); - - filesCreated.add (headerFile); - } - - int i = 0; - int fileIndex = 0; - - for (;;) - { - auto cpp = project.getBinaryDataCppFile (fileIndex); - - MemoryOutputStream mo; - mo.setNewLineString (projectLineFeed); - - auto r = writeCpp (mo, headerFile, i, maxFileSize); - - if (r.failed()) - return r; - - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (cpp, mo)) - return Result::fail ("Can't write to file: " + cpp.getFullPathName()); - - filesCreated.add (cpp); - ++fileIndex; - - if (i >= files.size()) - break; - } - - return Result::ok(); -} diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.h b/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.h index 43e9dd362f..bd769e1f97 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.h @@ -21,38 +21,40 @@ #include "../Project/jucer_Project.h" //============================================================================== -class ResourceFile +class JucerResourceFile { public: //============================================================================== - ResourceFile (Project& project); - ~ResourceFile(); + explicit JucerResourceFile (Project& project); + ~JucerResourceFile(); //============================================================================== - void setClassName (const String& className); - String getClassName() const { return className; } + void setClassName (const String& className) { resourceFile.setClassName (className); } + String getClassName() const { return resourceFile.getClassName(); } - void addFile (const File& file); - String getDataVariableFor (const File& file) const; - String getSizeVariableFor (const File& file) const; + void addFile (const File& file) { resourceFile.addFile (file); } + String getDataVariableFor (const File& file) const { return resourceFile.getDataVariableFor (file); } + String getSizeVariableFor (const File& file) const { return resourceFile.getSizeVariableFor (file); } - int getNumFiles() const { return files.size(); } - const File& getFile (int index) const { return files.getReference (index); } + int getNumFiles() const { return resourceFile.getNumFiles(); } + const File& getFile (int index) const { return resourceFile.getFile (index); } - int64 getTotalDataSize() const; + int64 getTotalDataSize() const { return resourceFile.getTotalDataSize(); } - Result write (Array& filesCreated, int maxFileSize); + build_tools::ResourceFile::WriteResult write (int maxFileSize) + { + return resourceFile.write (maxFileSize, + project.getProjectLineFeed(), + project.getBinaryDataHeaderFile(), + [this] (int index) { return project.getBinaryDataCppFile (index); }); + } //============================================================================== private: - Array files; - StringArray variableNames; - Project& project; - String className { "BinaryData" }; - - Result writeHeader (MemoryOutputStream&); - Result writeCpp (MemoryOutputStream&, const File& headerFile, int& index, int maxFileSize); void addResourcesFromProjectItem (const Project::Item& node); - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResourceFile) + Project& project; + build_tools::ResourceFile resourceFile; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JucerResourceFile) }; diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.cpp index 1c9c38a176..f59ae76e51 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.cpp +++ b/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.cpp @@ -60,63 +60,10 @@ namespace CodeHelpers return lines.joinIntoString (newLine); } - String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates, bool allowAsterisks) - { - if (s.isEmpty()) - return "unknown"; - - if (removeColons) - s = s.replaceCharacters (".,;:/@", "______"); - else - s = s.replaceCharacters (".,;/@", "_____"); - - for (int i = s.length(); --i > 0;) - if (CharacterFunctions::isLetter (s[i]) - && CharacterFunctions::isLetter (s[i - 1]) - && CharacterFunctions::isUpperCase (s[i]) - && ! CharacterFunctions::isUpperCase (s[i - 1])) - s = s.substring (0, i) + " " + s.substring (i); - - String allowedChars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789"); - if (allowTemplates) - allowedChars += "<>"; - - if (! removeColons) - allowedChars += ":"; - - if (allowAsterisks) - allowedChars += "*"; - - StringArray words; - words.addTokens (s.retainCharacters (allowedChars), false); - words.trim(); - - auto n = words[0]; - - if (capitalise) - n = n.toLowerCase(); - - for (int i = 1; i < words.size(); ++i) - { - if (capitalise && words[i].length() > 1) - n << words[i].substring (0, 1).toUpperCase() - << words[i].substring (1).toLowerCase(); - else - n << words[i]; - } - - if (CharacterFunctions::isDigit (n[0])) - n = "_" + n; - - if (CPlusPlusCodeTokeniser::isReservedKeyword (n)) - n << '_'; - - return n; - } String createIncludeStatement (const File& includeFile, const File& targetFile) { - return createIncludeStatement (FileHelpers::unixStylePath (FileHelpers::getRelativePathFrom (includeFile, targetFile.getParentDirectory()))); + return createIncludeStatement (build_tools::unixStylePath (build_tools::getRelativePathFrom (includeFile, targetFile.getParentDirectory()))); } String createIncludeStatement (const String& includePath) @@ -132,14 +79,6 @@ namespace CodeHelpers return "#include <" + includedFilename + ">"; } - String makeBinaryDataIdentifierName (const File& file) - { - return makeValidIdentifier (file.getFileName() - .replaceCharacters (" .", "__") - .retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"), - false, true, false); - } - String stringLiteral (const String& text, int maxLineLength) { if (text.isEmpty()) @@ -263,7 +202,7 @@ namespace CodeHelpers if (col == colours[i]) return "Colours::" + String (colourNames[i]); - return "Colour (0x" + hexString8Digits ((int) col.getARGB()) + ')'; + return "Colour (0x" + build_tools::hexString8Digits ((int) col.getARGB()) + ')'; } String justificationToCode (Justification justification) @@ -293,141 +232,7 @@ namespace CodeHelpers return "Justification (" + String (justification.getFlags()) + ")"; } - void writeDataAsCppLiteral (const MemoryBlock& mb, OutputStream& out, - bool breakAtNewLines, bool allowStringBreaks) - { - const int maxCharsOnLine = 250; - - auto data = (const unsigned char*) mb.getData(); - int charsOnLine = 0; - - bool canUseStringLiteral = mb.getSize() < 32768; // MS compilers can't handle big string literals.. - - if (canUseStringLiteral) - { - unsigned int numEscaped = 0; - - for (size_t i = 0; i < mb.getSize(); ++i) - { - auto num = (unsigned int) data[i]; - - if (! ((num >= 32 && num < 127) || num == '\t' || num == '\r' || num == '\n')) - { - if (++numEscaped > mb.getSize() / 4) - { - canUseStringLiteral = false; - break; - } - } - } - } - - if (! canUseStringLiteral) - { - out << "{ "; - - for (size_t i = 0; i < mb.getSize(); ++i) - { - auto num = (int) (unsigned int) data[i]; - out << num << ','; - - charsOnLine += 2; - - if (num >= 10) - { - ++charsOnLine; - - if (num >= 100) - ++charsOnLine; - } - - if (charsOnLine >= maxCharsOnLine) - { - charsOnLine = 0; - out << newLine; - } - } - - out << "0,0 };"; - } - else - { - out << "\""; - CppTokeniserFunctions::writeEscapeChars (out, (const char*) data, (int) mb.getSize(), - maxCharsOnLine, breakAtNewLines, false, allowStringBreaks); - out << "\";"; - } - } - //============================================================================== - static unsigned int calculateHash (const String& s, const unsigned int hashMultiplier) - { - auto t = s.toUTF8(); - unsigned int hash = 0; - - while (*t != 0) - hash = hashMultiplier * hash + (unsigned int) *t++; - - return hash; - } - - static unsigned int findBestHashMultiplier (const StringArray& strings) - { - unsigned int v = 31; - - for (;;) - { - SortedSet hashes; - bool collision = false; - - for (int i = strings.size(); --i >= 0;) - { - auto hash = calculateHash (strings[i], v); - - if (hashes.contains (hash)) - { - collision = true; - break; - } - - hashes.add (hash); - } - - if (! collision) - break; - - v += 2; - } - - return v; - } - - void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, - const StringArray& strings, const StringArray& codeToExecute, const int indentLevel) - { - jassert (strings.size() == codeToExecute.size()); - auto indent = String::repeatedString (" ", indentLevel); - auto hashMultiplier = findBestHashMultiplier (strings); - - out << indent << "unsigned int hash = 0;" << newLine - << newLine - << indent << "if (" << utf8PointerVariable << " != nullptr)" << newLine - << indent << " while (*" << utf8PointerVariable << " != 0)" << newLine - << indent << " hash = " << (int) hashMultiplier << " * hash + (unsigned int) *" << utf8PointerVariable << "++;" << newLine - << newLine - << indent << "switch (hash)" << newLine - << indent << "{" << newLine; - - for (int i = 0; i < strings.size(); ++i) - { - out << indent << " case 0x" << hexString8Digits ((int) calculateHash (strings[i], hashMultiplier)) - << ": " << codeToExecute[i] << newLine; - } - - out << indent << " default: break;" << newLine - << indent << "}" << newLine << newLine; - } - String getLeadingWhitespace (String line) { line = line.removeCharacters (line.endsWith ("\r\n") ? "\r\n" : "\n"); diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.h b/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.h index 2562cce307..09b2b7a195 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.h @@ -24,9 +24,6 @@ namespace CodeHelpers { String indent (const String& code, int numSpaces, bool indentFirstLine); String unindent (const String& code, int numSpaces); - String makeValidIdentifier (String s, bool capitalise, bool removeColons, - bool allowTemplates, bool allowAsterisks = false); - String makeBinaryDataIdentifierName (const File& file); String createIncludeStatement (const File& includedFile, const File& targetFile); String createIncludeStatement (const String& includePath); @@ -41,12 +38,6 @@ namespace CodeHelpers String alignFunctionCallParams (const String& call, const StringArray& parameters, int maxLineLength); - void writeDataAsCppLiteral (const MemoryBlock& data, OutputStream& out, - bool breakAtNewLines, bool allowStringBreaks); - - void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, - const StringArray& strings, const StringArray& codeToExecute, int indentLevel); - String getLeadingWhitespace (String line); int getBraceCount (String::CharPointerType line); bool getIndentForCurrentBlock (CodeDocument::Position pos, const String& tab, diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.cpp index beb11edc11..b9375b5924 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.cpp +++ b/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.cpp @@ -22,67 +22,6 @@ //============================================================================== namespace FileHelpers { - static uint64 calculateMemoryHashCode (const void* data, size_t numBytes) - { - uint64 t = 0; - - for (size_t i = 0; i < numBytes; ++i) - t = t * 65599 + static_cast (data)[i]; - - return t; - } - - uint64 calculateStreamHashCode (InputStream& in) - { - uint64 t = 0; - - const int bufferSize = 4096; - HeapBlock buffer; - buffer.malloc (bufferSize); - - for (;;) - { - auto num = in.read (buffer, bufferSize); - - if (num <= 0) - break; - - for (int i = 0; i < num; ++i) - t = t * 65599 + buffer[i]; - } - - return t; - } - - uint64 calculateFileHashCode (const File& file) - { - std::unique_ptr stream (file.createInputStream()); - return stream != nullptr ? calculateStreamHashCode (*stream) : 0; - } - - bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes) - { - if (file.getSize() == (int64) numBytes - && calculateMemoryHashCode (data, numBytes) == calculateFileHashCode (file)) - return true; - - if (file.exists()) - return file.replaceWithData (data, numBytes); - - return file.getParentDirectory().createDirectory() && file.appendData (data, numBytes); - } - - bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData) - { - return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize()); - } - - bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData) - { - const char* const utf8 = newData.toUTF8(); - return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8)); - } - bool containsAnyNonHiddenFiles (const File& folder) { DirectoryIterator di (folder, false); @@ -94,32 +33,10 @@ namespace FileHelpers return false; } - String unixStylePath (const String& path) { return path.replaceCharacter ('\\', '/'); } - String windowsStylePath (const String& path) { return path.replaceCharacter ('/', '\\'); } - - String currentOSStylePath (const String& path) - { - #if JUCE_WINDOWS - return windowsStylePath (path); - #else - return unixStylePath (path); - #endif - } - - bool isAbsolutePath (const String& path) - { - return File::isAbsolutePath (path) - || path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows) - || path.startsWithChar ('$') - || path.startsWithChar ('~') - || (CharacterFunctions::isLetter (path[0]) && path[1] == ':') - || path.startsWithIgnoreCase ("smb:"); - } - bool shouldPathsBeRelative (String path1, String path2) { - path1 = unixStylePath (path1); - path2 = unixStylePath (path2); + path1 = build_tools::unixStylePath (path1); + path2 = build_tools::unixStylePath (path2); const int len = jmin (path1.length(), path2.length()); int commonBitLength = 0; @@ -135,17 +52,6 @@ namespace FileHelpers return path1.substring (0, commonBitLength).removeCharacters ("/:").isNotEmpty(); } - String getRelativePathFrom (const File& file, const File& sourceFolder) - { - #if ! JUCE_WINDOWS - // On a non-windows machine, we can't know if a drive-letter path may be relative or not. - if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':') - return file.getFullPathName(); - #endif - - return file.getRelativePathFrom (sourceFolder); - } - // removes "/../" bits from the middle of the path String simplifyPath (String::CharPointerType p) { diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.h b/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.h index 39818d184b..4c0c3a41c8 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_FileHelpers.h @@ -22,24 +22,9 @@ //============================================================================== namespace FileHelpers { - uint64 calculateStreamHashCode (InputStream&); - uint64 calculateFileHashCode (const File&); - - bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes); - bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData); - bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData); - bool containsAnyNonHiddenFiles (const File& folder); - String unixStylePath (const String& path); - String windowsStylePath (const String& path); - String currentOSStylePath (const String& path); - bool shouldPathsBeRelative (String path1, String path2); - bool isAbsolutePath (const String& path); - - // A windows-aware version of File::getRelativePath() - String getRelativePathFrom (const File& file, const File& sourceFolder); // removes "/../" bits from the middle of the path String simplifyPath (String::CharPointerType path); @@ -69,14 +54,14 @@ struct FileModificationDetector { return fileModificationTime != file.getLastModificationTime() && (fileSize != file.getSize() - || FileHelpers::calculateFileHashCode (file) != fileHashCode); + || build_tools::calculateFileHashCode (file) != fileHashCode); } void updateHash() { fileModificationTime = file.getLastModificationTime(); fileSize = file.getSize(); - fileHashCode = FileHelpers::calculateFileHashCode (file); + fileHashCode = build_tools::calculateFileHashCode (file); } private: diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp index 23ffd3569e..907778ee76 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp +++ b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp @@ -79,11 +79,6 @@ String createAlphaNumericUID() return uid; } -String hexString8Digits (int value) -{ - return String::toHexString (value).paddedLeft ('0', 8); -} - String createGUID (const String& seed) { auto hex = MD5 ((seed + "_guidsalt").toUTF8()).toHexString().toUpperCase(); @@ -183,19 +178,6 @@ String createGCCPreprocessorFlags (const StringPairArray& defs) return s; } -String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString) -{ - for (int i = 0; i < definitions.size(); ++i) - { - const String key (definitions.getAllKeys()[i]); - const String value (definitions.getAllValues()[i]); - - sourceString = sourceString.replace ("${" + key + "}", value); - } - - return sourceString; -} - StringArray getSearchPathsFromString (const String& searchPath) { StringArray s; @@ -217,58 +199,6 @@ StringArray getCleanedStringArray (StringArray s) return s; } -//============================================================================== -static bool keyFoundAndNotSequentialDuplicate (XmlElement* xml, const String& key) -{ - forEachXmlChildElementWithTagName (*xml, element, "key") - { - if (element->getAllSubText().trim().equalsIgnoreCase (key)) - { - if (element->getNextElement() != nullptr && element->getNextElement()->hasTagName ("key")) - { - // found broken plist format (sequential duplicate), fix by removing - xml->removeChildElement (element, true); - return false; - } - - // key found (not sequential duplicate) - return true; - } - } - - // key not found - return false; -} - -static bool addKeyIfNotFound (XmlElement* xml, const String& key) -{ - if (! keyFoundAndNotSequentialDuplicate (xml, key)) - { - xml->createNewChildElement ("key")->addTextElement (key); - return true; - } - - return false; -} - -void addPlistDictionaryKey (XmlElement* xml, const String& key, const String& value) -{ - if (addKeyIfNotFound (xml, key)) - xml->createNewChildElement ("string")->addTextElement (value); -} - -void addPlistDictionaryKeyBool (XmlElement* xml, const String& key, const bool value) -{ - if (addKeyIfNotFound (xml, key)) - xml->createNewChildElement (value ? "true" : "false"); -} - -void addPlistDictionaryKeyInt (XmlElement* xml, const String& key, int value) -{ - if (addKeyIfNotFound (xml, key)) - xml->createNewChildElement ("integer")->addTextElement (String (value)); -} - //============================================================================== void autoScrollForMouseEvent (const MouseEvent& e, bool scrollX, bool scrollY) { @@ -349,37 +279,43 @@ bool isJUCEModule (const String& moduleID) noexcept StringArray getModulesRequiredForConsole() noexcept { - return { "juce_core", - "juce_data_structures", - "juce_events" - }; + return + { + "juce_core", + "juce_data_structures", + "juce_events" + }; } StringArray getModulesRequiredForComponent() noexcept { - return { "juce_core", - "juce_data_structures", - "juce_events", - "juce_graphics", - "juce_gui_basics" - }; + return + { + "juce_core", + "juce_data_structures", + "juce_events", + "juce_graphics", + "juce_gui_basics" + }; } StringArray getModulesRequiredForAudioProcessor() noexcept { - return { "juce_audio_basics", - "juce_audio_devices", - "juce_audio_formats", - "juce_audio_plugin_client", - "juce_audio_processors", - "juce_audio_utils", - "juce_core", - "juce_data_structures", - "juce_events", - "juce_graphics", - "juce_gui_basics", - "juce_gui_extra" - }; + return + { + "juce_audio_basics", + "juce_audio_devices", + "juce_audio_formats", + "juce_audio_plugin_client", + "juce_audio_processors", + "juce_audio_utils", + "juce_core", + "juce_data_structures", + "juce_events", + "juce_graphics", + "juce_gui_basics", + "juce_gui_extra" + }; } bool isPIPFile (const File& file) noexcept diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h index d0a693ef69..6b1b1fe171 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h @@ -29,8 +29,6 @@ var parseJUCEHeaderMetadata (const File&); String trimCommentCharsFromStartOfLine (const String& line); -String hexString8Digits (int value); - String createAlphaNumericUID(); String createGUID (const String& seed); // Turns a seed into a windows GUID @@ -40,7 +38,6 @@ String addQuotesIfContainsSpaces (const String& text); StringPairArray parsePreprocessorDefs (const String& defs); StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, const StringPairArray& overridingDefs); String createGCCPreprocessorFlags (const StringPairArray& defs); -String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString); StringArray getCleanedStringArray (StringArray); StringArray getSearchPathsFromString (const String& searchPath); @@ -48,10 +45,6 @@ StringArray getCommaOrWhitespaceSeparatedItems (const String&); void setValueIfVoid (Value value, const var& defaultValue); -void addPlistDictionaryKey (XmlElement* xml, const String& key, const String& value); -void addPlistDictionaryKeyBool (XmlElement* xml, const String& key, bool value); -void addPlistDictionaryKeyInt (XmlElement* xml, const String& key, int value); - bool fileNeedsCppSyntaxHighlighting (const File& file); StringArray getJUCEModules() noexcept; diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h index ad5d1ccacf..938572bed9 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h @@ -328,6 +328,8 @@ namespace Ids DECLARE_ID (pluginCode); DECLARE_ID (pluginChannelConfigs); DECLARE_ID (pluginCharacteristicsValue); + DECLARE_ID (pluginCharacteristics); + DECLARE_ID (extraPluginFormats); DECLARE_ID (pluginIsSynth); DECLARE_ID (pluginWantsMidiIn); DECLARE_ID (pluginProducesMidiOut); diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_RelativePath.h b/extras/Projucer/Source/Utility/Helpers/jucer_RelativePath.h deleted file mode 100644 index e2fe6dd08f..0000000000 --- a/extras/Projucer/Source/Utility/Helpers/jucer_RelativePath.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE 6 technical preview. - Copyright (c) 2017 - ROLI Ltd. - - You may use this code under the terms of the GPL v3 - (see www.gnu.org/licenses). - - For this technical preview, this file is not subject to commercial licensing. - - JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER - EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE - DISCLAIMED. - - ============================================================================== -*/ - -#pragma once - - -//============================================================================== -/** Manipulates a cross-platform partial file path. (Needed because File is designed - for absolute paths on the active OS) -*/ -class RelativePath -{ -public: - //============================================================================== - enum RootFolder - { - unknown, - projectFolder, - buildTargetFolder - }; - - //============================================================================== - RelativePath() - : root (unknown) - {} - - RelativePath (const String& relPath, const RootFolder rootType) - : path (FileHelpers::unixStylePath (relPath)), root (rootType) - { - } - - RelativePath (const File& file, const File& rootFolder, const RootFolder rootType) - : path (FileHelpers::unixStylePath (FileHelpers::getRelativePathFrom (file, rootFolder))), root (rootType) - { - } - - RootFolder getRoot() const { return root; } - - String toUnixStyle() const { return FileHelpers::unixStylePath (path); } - String toWindowsStyle() const { return FileHelpers::windowsStylePath (path); } - - String getFileName() const { return getFakeFile().getFileName(); } - String getFileNameWithoutExtension() const { return getFakeFile().getFileNameWithoutExtension(); } - - String getFileExtension() const { return getFakeFile().getFileExtension(); } - bool hasFileExtension (juce::StringRef extension) const { return getFakeFile().hasFileExtension (extension); } - bool isAbsolute() const { return FileHelpers::isAbsolutePath (path); } - - RelativePath withFileExtension (const String& extension) const - { - return RelativePath (path.upToLastOccurrenceOf (".", ! extension.startsWithChar ('.'), false) + extension, root); - } - - RelativePath getParentDirectory() const - { - String p (path); - if (path.endsWithChar ('/')) - p = p.dropLastCharacters (1); - - return RelativePath (p.upToLastOccurrenceOf ("/", false, false), root); - } - - RelativePath getChildFile (const String& subpath) const - { - if (FileHelpers::isAbsolutePath (subpath)) - return RelativePath (subpath, root); - - String p (toUnixStyle()); - if (! p.endsWithChar ('/')) - p << '/'; - - return RelativePath (p + subpath, root); - } - - RelativePath rebased (const File& originalRoot, const File& newRoot, const RootFolder newRootType) const - { - if (isAbsolute()) - return RelativePath (path, newRootType); - - return RelativePath (FileHelpers::getRelativePathFrom (originalRoot.getChildFile (toUnixStyle()), newRoot), newRootType); - } - -private: - //============================================================================== - String path; - RootFolder root; - - File getFakeFile() const - { - #if JUCE_WINDOWS - if (FileHelpers::isAbsolutePath (path)) - { - // This is a hack to convert unix-style absolute paths into valid absolute Windows paths to avoid hitting - // an assertion in File::parseAbsolutePath(). - if (path.startsWithChar (L'/') || path.startsWithChar (L'$') || path.startsWithChar (L'~')) - return File (String ("C:\\") + FileHelpers::windowsStylePath (path.substring (1))); - - return File (path); - } - #endif - - // This method gets called very often, so we'll cache this directory. - static const File currentWorkingDirectory (File::getCurrentWorkingDirectory()); - return currentWorkingDirectory.getChildFile (path); - } -}; diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp index 4fa9b72362..c59feb961f 100644 --- a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp @@ -22,17 +22,6 @@ #include "../../Project/jucer_Module.h" //============================================================================== -static String removeEnclosed (const String& input, const String& start, const String& end) -{ - auto startIndex = input.indexOf (start); - auto endIndex = input.indexOf (end) + end.length(); - - if (startIndex != -1 && endIndex != -1) - return input.replaceSection (startIndex, endIndex - startIndex, {}); - - return input; -} - static void ensureSingleNewLineAfterIncludes (StringArray& lines) { int lastIncludeIndex = -1; @@ -394,8 +383,12 @@ Result PIPGenerator::setProjectSettings (ValueTree& jucerTree) jucerTree.setProperty (Ids::pluginFormats, pluginFormatsToBuild.joinIntoString (","), nullptr); - if (! getPluginCharacteristics().isEmpty()) - jucerTree.setProperty (Ids::pluginCharacteristicsValue, getPluginCharacteristics().joinIntoString (","), nullptr); + const auto characteristics = metadata[Ids::pluginCharacteristics].toString(); + + if (characteristics.isNotEmpty()) + jucerTree.setProperty (Ids::pluginCharacteristicsValue, + characteristics.removeCharacters (" \t\n\r"), + nullptr); } return Result::ok(); @@ -422,52 +415,40 @@ void PIPGenerator::setModuleFlags (ValueTree& jucerTree) String PIPGenerator::getMainFileTextForType() { - String mainTemplate (BinaryData::jucer_PIPMain_cpp); + const auto type = metadata[Ids::type].toString(); - auto includeFilename = [&] + const auto mainTemplate = [&] + { + if (type == "Console") + return String (BinaryData::PIPConsole_cpp_in); + + if (type == "Component") + return String (BinaryData::PIPComponent_cpp_in) + .replace ("${JUCE_PIP_NAME}", metadata[Ids::name].toString()) + .replace ("${PROJECT_VERSION}", metadata[Ids::version].toString()) + .replace ("${JUCE_PIP_MAIN_CLASS}", metadata[Ids::mainClass].toString()); + + if (type == "AudioProcessor") + return String (BinaryData::PIPAudioProcessor_cpp_in) + .replace ("${JUCE_PIP_MAIN_CLASS}", metadata[Ids::mainClass].toString()); + + return String{}; + }(); + + if (mainTemplate.isEmpty()) + return {}; + + const auto includeFilename = [&] { if (useLocalCopy) return pipFile.getFileName(); if (isTemp) return pipFile.getFullPathName(); - return RelativePath (pipFile, outputDirectory.getChildFile ("Source"), RelativePath::unknown).toUnixStyle(); + return build_tools::RelativePath (pipFile, + outputDirectory.getChildFile ("Source"), + build_tools::RelativePath::unknown).toUnixStyle(); }(); - mainTemplate = mainTemplate.replace ("%%filename%%", includeFilename) - .replace ("%%include_juce%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename())); - - auto type = metadata[Ids::type].toString(); - - if (type == "Console") - { - mainTemplate = removeEnclosed (mainTemplate, "%%component_begin%%", "%%component_end%%"); - mainTemplate = removeEnclosed (mainTemplate, "%%audioprocessor_begin%%", "%%audioprocessor_end%%"); - mainTemplate = mainTemplate.replace ("%%console_begin%%", {}).replace ("%%console_end%%", {}); - - return ensureCorrectWhitespace (mainTemplate); - } - else if (type == "Component") - { - mainTemplate = removeEnclosed (mainTemplate, "%%audioprocessor_begin%%", "%%audioprocessor_end%%"); - mainTemplate = removeEnclosed (mainTemplate, "%%console_begin%%", "%%console_end%%"); - mainTemplate = mainTemplate.replace ("%%component_begin%%", {}).replace ("%%component_end%%", {}); - - mainTemplate = mainTemplate.replace ("%%project_name%%", metadata[Ids::name].toString()); - mainTemplate = mainTemplate.replace ("%%project_version%%", metadata[Ids::version].toString()); - - return ensureCorrectWhitespace (mainTemplate.replace ("%%startup%%", "mainWindow.reset (new MainWindow (" + metadata[Ids::name].toString().quoted() - + ", new " + metadata[Ids::mainClass].toString() + "(), *this));") - .replace ("%%shutdown%%", "mainWindow = nullptr;")); - } - else if (type == "AudioProcessor") - { - mainTemplate = removeEnclosed (mainTemplate, "%%component_begin%%", "%%component_end%%"); - mainTemplate = removeEnclosed (mainTemplate, "%%console_begin%%", "%%console_end%%"); - mainTemplate = mainTemplate.replace ("%%audioprocessor_begin%%", {}).replace ("%%audioprocessor_end%%", {}); - - return ensureCorrectWhitespace (mainTemplate.replace ("%%class_name%%", metadata[Ids::mainClass].toString())); - } - - return {}; + return ensureCorrectWhitespace (mainTemplate.replace ("${JUCE_PIP_HEADER}", includeFilename)); } //============================================================================== @@ -509,34 +490,20 @@ bool PIPGenerator::copyRelativeFileToLocalSourceDirectory (const File& fileToCop StringArray PIPGenerator::getExtraPluginFormatsToBuild() const { - auto name = metadata[Ids::name].toString(); + auto tokens = StringArray::fromTokens (metadata[Ids::extraPluginFormats].toString(), ",", {}); - if (name == "AUv3SynthPlugin" || name == "AudioPluginDemo") - return { Ids::buildAUv3.toString() }; - else if (name == "InterAppAudioEffectPlugin") - return { Ids::enableIAA.toString() }; + for (auto& token : tokens) + { + token = [&] + { + if (token == "IAA") + return Ids::enableIAA.toString(); - return {}; -} + return "build" + token; + }(); + } -StringArray PIPGenerator::getPluginCharacteristics() const -{ - auto name = metadata[Ids::name].toString(); - - if (name == "AudioPluginDemo") - return { Ids::pluginIsSynth.toString(), - Ids::pluginWantsMidiIn.toString(), - Ids::pluginProducesMidiOut.toString(), - Ids::pluginEditorRequiresKeys.toString() }; - else if (name == "AUv3SynthPlugin" || name == "MultiOutSynthPlugin") - return { Ids::pluginIsSynth.toString(), - Ids::pluginWantsMidiIn.toString() }; - else if (name == "ArpeggiatorPlugin") - return { Ids::pluginWantsMidiIn.toString(), - Ids::pluginProducesMidiOut.toString(), - Ids::pluginIsMidiEffectPlugin.toString() }; - - return {}; + return tokens; } String PIPGenerator::getPathForModule (const String& moduleID) const @@ -548,7 +515,9 @@ String PIPGenerator::getPathForModule (const String& moduleID) const if (isTemp) return juceModulesPath.getFullPathName(); - return RelativePath (juceModulesPath, outputDirectory, RelativePath::projectFolder).toUnixStyle(); + return build_tools::RelativePath (juceModulesPath, + outputDirectory, + build_tools::RelativePath::projectFolder).toUnixStyle(); } } else if (availableUserModules != nullptr) @@ -558,7 +527,9 @@ String PIPGenerator::getPathForModule (const String& moduleID) const if (isTemp) return moduleRoot.getFullPathName(); - return RelativePath (moduleRoot , outputDirectory, RelativePath::projectFolder).toUnixStyle(); + return build_tools::RelativePath (moduleRoot, + outputDirectory, + build_tools::RelativePath::projectFolder).toUnixStyle(); } return {}; diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h index 7906c13259..e3604421ba 100644 --- a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h @@ -64,7 +64,6 @@ private: bool copyRelativeFileToLocalSourceDirectory (const File&) const noexcept; StringArray getExtraPluginFormatsToBuild() const; - StringArray getPluginCharacteristics() const; String getPathForModule (const String&) const; File getExamplesDirectory() const; diff --git a/extras/Projucer/Source/Wizards/jucer_NewFileWizard.cpp b/extras/Projucer/Source/Wizards/jucer_NewFileWizard.cpp index 21d2302da5..e25bd0d6ad 100644 --- a/extras/Projucer/Source/Wizards/jucer_NewFileWizard.cpp +++ b/extras/Projucer/Source/Wizards/jucer_NewFileWizard.cpp @@ -36,7 +36,7 @@ namespace static bool fillInNewCppFileTemplate (const File& file, const Project::Item& item, const char* templateName) { - return FileHelpers::overwriteFileWithNewDataIfDifferent (file, fillInBasicTemplateFields (file, item, templateName)); + return build_tools::overwriteFileWithNewDataIfDifferent (file, fillInBasicTemplateFields (file, item, templateName)); } const int menuBaseID = 0x12d83f0; @@ -145,7 +145,7 @@ public: const String className (aw.getTextEditorContents (getClassNameFieldName()).trim()); - if (className == CodeHelpers::makeValidIdentifier (className, false, true, false)) + if (className == build_tools::makeValidIdentifier (className, false, true, false)) { const File newFile (askUserToChooseNewFile (className + ".h", "*.h;*.cpp", parent)); @@ -166,7 +166,7 @@ public: content = replaceLineFeeds (content, parent.project.getProjectLineFeed()); - if (FileHelpers::overwriteFileWithNewDataIfDifferent (newFile, content)) + if (build_tools::overwriteFileWithNewDataIfDifferent (newFile, content)) { parent.addFileRetainingSortOrder (newFile, true); return true; diff --git a/extras/Projucer/Source/Wizards/jucer_NewProjectWizard.h b/extras/Projucer/Source/Wizards/jucer_NewProjectWizard.h index d74a8a3af4..64daa669f3 100644 --- a/extras/Projucer/Source/Wizards/jucer_NewProjectWizard.h +++ b/extras/Projucer/Source/Wizards/jucer_NewProjectWizard.h @@ -66,18 +66,18 @@ struct NewProjectWizard { return { - "juce_core", - "juce_events", - "juce_graphics", - "juce_data_structures", - "juce_gui_basics", - "juce_gui_extra", - "juce_cryptography", - "juce_opengl", "juce_audio_basics", "juce_audio_devices", "juce_audio_formats", - "juce_audio_processors" + "juce_audio_processors", + "juce_core", + "juce_cryptography", + "juce_data_structures", + "juce_events", + "juce_graphics", + "juce_gui_basics", + "juce_gui_extra", + "juce_opengl", }; } diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Animated.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Animated.h index 5d2d040bf8..5fa286e7d9 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Animated.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Animated.h @@ -57,7 +57,7 @@ struct AnimatedAppWizard : public NewProjectWizard File contentCompH = contentCompCpp.withFileExtension (".h"); String contentCompName = "MainComponent"; - project.setProjectType (ProjectType_GUIApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_GUIApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); @@ -72,7 +72,7 @@ struct AnimatedAppWizard : public NewProjectWizard .replace ("%%include_juce%%", juceHeaderInclude) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) failedFiles.add (contentCompH.getFullPathName()); sourceGroup.addFileAtIndex (contentCompH, -1, false); @@ -84,7 +84,7 @@ struct AnimatedAppWizard : public NewProjectWizard .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) failedFiles.add (contentCompCpp.getFullPathName()); sourceGroup.addFileAtIndex (contentCompCpp, -1, true); @@ -93,11 +93,11 @@ struct AnimatedAppWizard : public NewProjectWizard // create main cpp String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp") .replace ("%%app_headers%%", appHeaders, false) - .replace ("%%app_class_name%%", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) + .replace ("%%app_class_name%%", build_tools::makeValidIdentifier (appTitle + "Application", false, true, false), false) .replace ("%%content_component_class%%", contentCompName, false) .replace ("%%allow_more_than_one_instance%%", "true", false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFileAtIndex (mainCppFile,-1, true); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioApp.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioApp.h index 064ac07684..06282b527d 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioApp.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioApp.h @@ -57,7 +57,7 @@ struct AudioAppWizard : public NewProjectWizard File contentCompH = contentCompCpp.withFileExtension (".h"); String contentCompName = "MainComponent"; - project.setProjectType (ProjectType_GUIApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_GUIApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); @@ -72,7 +72,7 @@ struct AudioAppWizard : public NewProjectWizard .replace ("%%include_juce%%", juceHeaderInclude) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) failedFiles.add (contentCompH.getFullPathName()); sourceGroup.addFileAtIndex (contentCompH, -1, false); @@ -86,7 +86,7 @@ struct AudioAppWizard : public NewProjectWizard - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) failedFiles.add (contentCompCpp.getFullPathName()); sourceGroup.addFileAtIndex (contentCompCpp, -1, true); @@ -95,11 +95,11 @@ struct AudioAppWizard : public NewProjectWizard // create main cpp String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp") .replace ("%%app_headers%%", appHeaders, false) - .replace ("%%app_class_name%%", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) + .replace ("%%app_class_name%%", build_tools::makeValidIdentifier (appTitle + "Application", false, true, false), false) .replace ("%%content_component_class%%", contentCompName, false) .replace ("%%allow_more_than_one_instance%%", "true", false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFileAtIndex (mainCppFile, -1, true); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioPlugin.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioPlugin.h index 16ba8d755a..2d9bf7d35a 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioPlugin.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioPlugin.h @@ -41,7 +41,7 @@ struct AudioPluginAppWizard : public NewProjectWizard { createSourceFolder(); - String filterClassName = CodeHelpers::makeValidIdentifier (appTitle, true, true, false) + "AudioProcessor"; + String filterClassName = build_tools::makeValidIdentifier (appTitle, true, true, false) + "AudioProcessor"; filterClassName = filterClassName.substring (0, 1).toUpperCase() + filterClassName.substring (1); String editorClassName = filterClassName + "Editor"; @@ -50,7 +50,7 @@ struct AudioPluginAppWizard : public NewProjectWizard File editorCppFile = getSourceFilesFolder().getChildFile ("PluginEditor.cpp"); File editorHFile = editorCppFile.withFileExtension (".h"); - project.setProjectType (ProjectType_AudioPlugin::getTypeName()); + project.setProjectType (build_tools::ProjectType_AudioPlugin::getTypeName()); setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle)); @@ -77,16 +77,16 @@ struct AudioPluginAppWizard : public NewProjectWizard .replace ("%%filter_class_name%%", filterClassName, false) .replace ("%%editor_class_name%%", editorClassName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterCppFile, filterCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (filterCppFile, filterCpp)) failedFiles.add (filterCppFile.getFullPathName()); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (filterHFile, filterH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (filterHFile, filterH)) failedFiles.add (filterHFile.getFullPathName()); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorCppFile, editorCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (editorCppFile, editorCpp)) failedFiles.add (editorCppFile.getFullPathName()); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (editorHFile, editorH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (editorHFile, editorH)) failedFiles.add (editorHFile.getFullPathName()); Project::Item sourceGroup (createSourceGroup (project)); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Blank.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Blank.h index 6e706fc534..c096bace45 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Blank.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Blank.h @@ -31,7 +31,7 @@ struct BlankAppWizard : public NewProjectWizard bool initialiseProject (Project& project) override { createSourceFolder(); - project.setProjectType (ProjectType_GUIApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_GUIApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle)); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Console.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Console.h index f985ff8c69..be8df71b39 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Console.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_Console.h @@ -52,7 +52,7 @@ struct ConsoleAppWizard : public NewProjectWizard { createSourceFolder(); - project.setProjectType (ProjectType_ConsoleApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_ConsoleApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); @@ -65,7 +65,7 @@ struct ConsoleAppWizard : public NewProjectWizard String mainCpp = project.getFileTemplate ("jucer_MainConsoleAppTemplate_cpp") .replace ("%%app_headers%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()), false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFileAtIndex (mainCppFile, -1, true); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_DLL.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_DLL.h index 8c7fe94d46..084b4da099 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_DLL.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_DLL.h @@ -31,7 +31,7 @@ struct DynamicLibraryWizard : public NewProjectWizard bool initialiseProject (Project& project) override { createSourceFolder(); - project.setProjectType (ProjectType_DLL::getTypeName()); + project.setProjectType (build_tools::ProjectType_DLL::getTypeName()); createSourceGroup (project); setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle)); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_GUIApp.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_GUIApp.h index ed35d1fc56..accfbf3fc4 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_GUIApp.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_GUIApp.h @@ -61,7 +61,7 @@ struct GUIAppWizard : public NewProjectWizard File contentCompH = contentCompCpp.withFileExtension (".h"); String contentCompName = "MainComponent"; - project.setProjectType (ProjectType_GUIApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_GUIApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); @@ -79,7 +79,7 @@ struct GUIAppWizard : public NewProjectWizard .replace ("%%include_juce%%", juceHeaderInclude) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) failedFiles.add (contentCompH.getFullPathName()); sourceGroup.addFileAtIndex (contentCompH, -1, false); @@ -91,7 +91,7 @@ struct GUIAppWizard : public NewProjectWizard .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) failedFiles.add (contentCompCpp.getFullPathName()); sourceGroup.addFileAtIndex (contentCompCpp, -1, true); @@ -103,11 +103,11 @@ struct GUIAppWizard : public NewProjectWizard String mainCpp = project.getFileTemplate (createWindow ? "jucer_MainTemplate_Window_cpp" : "jucer_MainTemplate_NoWindow_cpp") .replace ("%%app_headers%%", appHeaders, false) - .replace ("%%app_class_name%%", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) + .replace ("%%app_class_name%%", build_tools::makeValidIdentifier (appTitle + "Application", false, true, false), false) .replace ("%%content_component_class%%", contentCompName, false) .replace ("%%allow_more_than_one_instance%%", "true", false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFileAtIndex (mainCppFile, -1, true); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_StaticLibrary.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_StaticLibrary.h index 5dedd3f661..327ac6fc9b 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_StaticLibrary.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_StaticLibrary.h @@ -31,7 +31,7 @@ struct StaticLibraryWizard : public NewProjectWizard bool initialiseProject (Project& project) override { createSourceFolder(); - project.setProjectType (ProjectType_StaticLibrary::getTypeName()); + project.setProjectType (build_tools::ProjectType_StaticLibrary::getTypeName()); createSourceGroup (project); setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle)); diff --git a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_openGL.h b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_openGL.h index 4562f657b3..8a88bf8457 100644 --- a/extras/Projucer/Source/Wizards/jucer_ProjectWizard_openGL.h +++ b/extras/Projucer/Source/Wizards/jucer_ProjectWizard_openGL.h @@ -57,7 +57,7 @@ struct OpenGLAppWizard : public NewProjectWizard File contentCompH = contentCompCpp.withFileExtension (".h"); String contentCompName = "MainComponent"; - project.setProjectType (ProjectType_GUIApp::getTypeName()); + project.setProjectType (build_tools::ProjectType_GUIApp::getTypeName()); Project::Item sourceGroup (createSourceGroup (project)); @@ -72,7 +72,7 @@ struct OpenGLAppWizard : public NewProjectWizard .replace ("%%include_juce%%", juceHeaderInclude) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompH, windowH)) failedFiles.add (contentCompH.getFullPathName()); sourceGroup.addFileAtIndex (contentCompH, -1, false); @@ -84,7 +84,7 @@ struct OpenGLAppWizard : public NewProjectWizard .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false) .replace ("%%content_component_class%%", contentCompName, false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (contentCompCpp, windowCpp)) failedFiles.add (contentCompCpp.getFullPathName()); sourceGroup.addFileAtIndex (contentCompCpp, -1, true); @@ -93,11 +93,11 @@ struct OpenGLAppWizard : public NewProjectWizard // create main cpp String mainCpp = project.getFileTemplate ("jucer_MainTemplate_SimpleWindow_cpp") .replace ("%%app_headers%%", appHeaders, false) - .replace ("%%app_class_name%%", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) + .replace ("%%app_class_name%%", build_tools::makeValidIdentifier (appTitle + "Application", false, true, false), false) .replace ("%%content_component_class%%", contentCompName, false) .replace ("%%allow_more_than_one_instance%%", "true", false); - if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) + if (!build_tools::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp)) failedFiles.add (mainCppFile.getFullPathName()); sourceGroup.addFileAtIndex (mainCppFile, -1, true); diff --git a/extras/UnitTestRunner/CMakeLists.txt b/extras/UnitTestRunner/CMakeLists.txt new file mode 100644 index 0000000000..cea9e1a8d2 --- /dev/null +++ b/extras/UnitTestRunner/CMakeLists.txt @@ -0,0 +1,36 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_console_app(UnitTestRunner) + +juce_generate_juce_header(UnitTestRunner) + +target_sources(UnitTestRunner PRIVATE Source/Main.cpp) + +target_compile_definitions(UnitTestRunner PRIVATE + JUCE_UNIT_TESTS=1 + JUCE_USE_CURL=0 + JUCE_WEB_BROWSER=0) + +target_link_libraries(UnitTestRunner PRIVATE + juce::juce_analytics + juce::juce_audio_utils + juce::juce_blocks_basics + juce::juce_dsp + juce::juce_opengl + juce::juce_osc + juce::juce_product_unlocking + juce::juce_video) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 0000000000..f2b01872ee --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,41 @@ +# ============================================================================== +# +# This file is part of the JUCE 6 technical preview. +# Copyright (c) 2020 - ROLI Ltd. +# +# You may use this code under the terms of the GPL v3 +# (see www.gnu.org/licenses). +# +# For this technical preview, this file is not subject to commercial licensing. +# +# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER +# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE +# DISCLAIMED. +# +# ============================================================================== + +juce_add_modules( + INSTALL_PATH "include/JUCE-${JUCE_VERSION}/modules" + INSTALL_EXPORT JUCE + ALIAS_NAMESPACE juce + juce_analytics + juce_audio_basics + juce_audio_devices + juce_audio_formats + juce_audio_plugin_client + juce_audio_processors + juce_audio_utils + juce_blocks_basics + juce_box2d + juce_core + juce_cryptography + juce_data_structures + juce_dsp + juce_events + juce_graphics + juce_gui_basics + juce_gui_extra + juce_opengl + juce_osc + juce_product_unlocking + juce_video) diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index f45703e87b..7e5778aeda 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -356,7 +356,6 @@ public: return false; } - #if JUCE_MODULE_AVAILABLE_juce_gui_basics Image getIAAHostIcon (int size) { #if JUCE_IOS && JucePlugin_Enable_IAA @@ -368,7 +367,6 @@ public: return {}; } - #endif static StandalonePluginHolder* getInstance(); diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client.h b/modules/juce_audio_plugin_client/juce_audio_plugin_client.h index 32732e3c6b..4fe4c16733 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client.h +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client.h @@ -34,7 +34,7 @@ website: http://www.juce.com/juce license: GPL/Commercial - dependencies: juce_gui_basics, juce_audio_basics, juce_audio_processors + dependencies: juce_audio_processors END_JUCE_MODULE_DECLARATION diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index af1a07f323..b9df89ed99 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -211,20 +211,16 @@ void AudioProcessorEditor::setScaleFactor (float newScale) } //============================================================================== -#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity - typedef ComponentPeer* (*createUnityPeerFunctionType) (Component&); - createUnityPeerFunctionType juce_createUnityPeerFn = nullptr; -#endif +typedef ComponentPeer* (*createUnityPeerFunctionType) (Component&); +createUnityPeerFunctionType juce_createUnityPeerFn = nullptr; ComponentPeer* AudioProcessorEditor::createNewPeer (int styleFlags, void* nativeWindow) { - #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity if (juce_createUnityPeerFn != nullptr) { ignoreUnused (styleFlags, nativeWindow); return juce_createUnityPeerFn (*this); } - #endif return Component::createNewPeer (styleFlags, nativeWindow); } diff --git a/modules/juce_audio_utils/juce_audio_utils.h b/modules/juce_audio_utils/juce_audio_utils.h index e70469c45a..1750327477 100644 --- a/modules/juce_audio_utils/juce_audio_utils.h +++ b/modules/juce_audio_utils/juce_audio_utils.h @@ -34,7 +34,7 @@ website: http://www.juce.com/juce license: GPL/Commercial - dependencies: juce_gui_extra, juce_audio_processors, juce_audio_formats, juce_audio_devices + dependencies: juce_audio_processors, juce_audio_formats, juce_audio_devices OSXFrameworks: CoreAudioKit DiscRecording iOSFrameworks: CoreAudioKit diff --git a/modules/juce_blocks_basics/juce_blocks_basics.h b/modules/juce_blocks_basics/juce_blocks_basics.h index f3bb2de4eb..f4ebdeac8f 100644 --- a/modules/juce_blocks_basics/juce_blocks_basics.h +++ b/modules/juce_blocks_basics/juce_blocks_basics.h @@ -39,7 +39,7 @@ license: ISC minimumCppStandard: 14 - dependencies: juce_events juce_audio_devices + dependencies: juce_audio_devices END_JUCE_MODULE_DECLARATION diff --git a/modules/juce_core/native/javacore/app/com/roli/juce/JuceApp.java b/modules/juce_core/native/javacore/app/com/roli/juce/JuceApp.java index 4b070034f4..7077186db3 100644 --- a/modules/juce_core/native/javacore/app/com/roli/juce/JuceApp.java +++ b/modules/juce_core/native/javacore/app/com/roli/juce/JuceApp.java @@ -29,9 +29,9 @@ import android.app.Application; public class JuceApp extends Application { @Override - public void onCreate () + public void onCreate() { - super.onCreate (); + super.onCreate(); Java.initialiseJUCE (this); } } diff --git a/modules/juce_dsp/juce_dsp.h b/modules/juce_dsp/juce_dsp.h index 856d97b20f..ee923fa466 100644 --- a/modules/juce_dsp/juce_dsp.h +++ b/modules/juce_dsp/juce_dsp.h @@ -35,7 +35,7 @@ license: GPL/Commercial minimumCppStandard: 14 - dependencies: juce_audio_basics, juce_audio_formats + dependencies: juce_audio_formats OSXFrameworks: Accelerate iOSFrameworks: Accelerate diff --git a/modules/juce_osc/juce_osc.h b/modules/juce_osc/juce_osc.h index ce9c2b4a7b..e308b63811 100644 --- a/modules/juce_osc/juce_osc.h +++ b/modules/juce_osc/juce_osc.h @@ -34,7 +34,7 @@ website: http://www.juce.com/juce license: GPL/Commercial - dependencies: juce_core, juce_events + dependencies: juce_events END_JUCE_MODULE_DECLARATION diff --git a/modules/juce_product_unlocking/juce_product_unlocking.h b/modules/juce_product_unlocking/juce_product_unlocking.h index b38b46c648..2bd1dd9749 100644 --- a/modules/juce_product_unlocking/juce_product_unlocking.h +++ b/modules/juce_product_unlocking/juce_product_unlocking.h @@ -34,7 +34,7 @@ website: http://www.juce.com/juce license: GPL/Commercial - dependencies: juce_cryptography juce_core, juce_events + dependencies: juce_cryptography END_JUCE_MODULE_DECLARATION