Repository: McMartin/FRUT Branch: main Commit: 0b31a99ca902 Files: 586 Total size: 2.4 MB Directory structure: gitextract_b0ewfza2/ ├── .appveyor.yml ├── .azure-pipelines.yml ├── .cirrus.yml ├── .clang-format ├── .github/ │ └── pull_request_template.md ├── .gitignore ├── .readthedocs.yaml ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Jucer2CMake/ │ ├── CMakeLists.txt │ ├── src/ │ │ ├── argh.hpp │ │ ├── juce6.hpp │ │ ├── juce_core.hpp │ │ ├── main.cpp │ │ ├── reprojucer.hpp │ │ └── utils.hpp │ └── tests/ │ ├── .gitignore │ ├── apply-Jucer2CMake-juce6-to-test-jucers.cmake │ ├── audioplug6/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ ├── PluginEditor.cpp │ │ │ ├── PluginEditor.h │ │ │ ├── PluginProcessor.cpp │ │ │ └── PluginProcessor.h │ │ └── audioplug6.jucer │ ├── audioplug6-default/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ ├── PluginEditor.cpp │ │ │ ├── PluginEditor.h │ │ │ ├── PluginProcessor.cpp │ │ │ └── PluginProcessor.h │ │ └── audioplug6.jucer │ ├── consoleapp6/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ └── Main.cpp │ │ └── consoleapp6.jucer │ ├── consoleapp6-default/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ └── Main.cpp │ │ └── consoleapp6.jucer │ ├── guiapp6/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ ├── Main.cpp │ │ │ ├── MainComponent.cpp │ │ │ └── MainComponent.h │ │ └── guiapp6.jucer │ └── guiapp6-default/ │ ├── CMakeLists.txt │ ├── Source/ │ │ ├── Main.cpp │ │ ├── MainComponent.cpp │ │ └── MainComponent.h │ └── guiapp6.jucer ├── LICENSE ├── README.rst ├── ci/ │ ├── AllJuceProjects/ │ │ └── CMakeLists.txt │ ├── apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake │ ├── apply-Jucer2CMake-reprojucer-to-test-jucers.cmake │ ├── azure-pipelines/ │ │ ├── steps-Makefiles.yml │ │ ├── steps-VS.yml │ │ ├── steps-Xcode.yml │ │ └── steps-iOS.yml │ └── fake-SDKs/ │ ├── AAX/ │ │ └── Interfaces/ │ │ └── AAX_Exports.cpp │ ├── VST/ │ │ ├── pluginterfaces/ │ │ │ └── vst2.x/ │ │ │ └── aeffect.h │ │ └── public.sdk/ │ │ └── source/ │ │ └── vst2.x/ │ │ └── audioeffectx.h │ └── VST3/ │ └── base/ │ └── source/ │ └── baseiids.cpp ├── cmake/ │ ├── Reprojucer.cmake │ ├── data/ │ │ ├── AppConfig-4.h.in │ │ ├── AppConfig-5.h.in │ │ ├── AppConfig.h.in │ │ ├── Info.plist.in │ │ ├── JuceHeader.h.in │ │ ├── JuceLibraryCode-Wrapper.cpp.in │ │ ├── JucePluginDefines.h.in │ │ ├── LaunchScreen.storyboard │ │ ├── PkgInfo │ │ ├── UnityScript.cs.in │ │ ├── failed-to.md.in │ │ ├── juce_runtime_arch_detection.cpp │ │ ├── resources.rc.in │ │ ├── script.in │ │ └── target.entitlements.in │ └── tools/ │ ├── BinaryDataBuilder/ │ │ ├── CMakeLists.txt │ │ ├── extras/ │ │ │ └── Projucer/ │ │ │ └── Source/ │ │ │ ├── Project/ │ │ │ │ └── jucer_Project.h │ │ │ ├── Project Saving/ │ │ │ │ ├── jucer_ResourceFile.cpp │ │ │ │ └── jucer_ResourceFile.h │ │ │ ├── Utility/ │ │ │ │ ├── jucer_CodeHelpers.cpp │ │ │ │ ├── jucer_CodeHelpers.h │ │ │ │ ├── jucer_FileHelpers.cpp │ │ │ │ ├── jucer_FileHelpers.h │ │ │ │ ├── jucer_MiscUtilities.cpp │ │ │ │ └── jucer_MiscUtilities.h │ │ │ └── jucer_Headers.h │ │ ├── main.cpp │ │ └── modules/ │ │ └── juce_gui_extra/ │ │ ├── code_editor/ │ │ │ ├── juce_CPlusPlusCodeTokeniser.cpp │ │ │ ├── juce_CPlusPlusCodeTokeniser.h │ │ │ └── juce_CPlusPlusCodeTokeniserFunctions.h │ │ ├── juce_gui_extra.cpp │ │ └── juce_gui_extra.h │ ├── CMakeLists.txt │ ├── IconBuilder/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ ├── Project Saving/ │ │ │ │ ├── jucer_ProjectExport_MSVC.h │ │ │ │ ├── jucer_ProjectExport_XCode.h │ │ │ │ ├── jucer_ProjectExporter.cpp │ │ │ │ └── jucer_ProjectExporter.h │ │ │ ├── Utility/ │ │ │ │ ├── jucer_FileHelpers.cpp │ │ │ │ └── jucer_FileHelpers.h │ │ │ └── jucer_Headers.h │ │ └── main.cpp │ ├── PListMerger/ │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── XcassetsBuilder/ │ │ ├── CMakeLists.txt │ │ ├── Source/ │ │ │ ├── ProjectSaving/ │ │ │ │ ├── jucer_ProjectExport_Xcode.h │ │ │ │ ├── jucer_ProjectExporter.cpp │ │ │ │ └── jucer_ProjectExporter.h │ │ │ ├── Utility/ │ │ │ │ ├── jucer_FileHelpers.cpp │ │ │ │ └── jucer_FileHelpers.h │ │ │ └── jucer_Headers.h │ │ └── main.cpp │ ├── juce_core.cmake │ └── juce_gui_basics.cmake ├── docs/ │ ├── Reprojucer.cmake/ │ │ ├── command/ │ │ │ ├── jucer_appconfig_header.rst │ │ │ ├── jucer_audio_plugin_settings.rst │ │ │ ├── jucer_export_target.rst │ │ │ ├── jucer_export_target_configuration.rst │ │ │ ├── jucer_project_begin.rst │ │ │ ├── jucer_project_end.rst │ │ │ ├── jucer_project_files.rst │ │ │ ├── jucer_project_module.rst │ │ │ └── jucer_project_settings.rst │ │ └── index.rst │ ├── conf.py │ ├── index.rst │ └── requirements.txt ├── generated/ │ ├── JUCE-4.2.0/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ ├── AUv3Synth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AnimationAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AudioAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BouncingBallWavetableDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── ComponentTutorialExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── Demo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── HelloWorld/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MPETest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MidiTest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── NetworkGraphicsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCMonitor/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCReceiver/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCSender/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OpenGLAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PluckedStringsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PlugInSamples/ │ │ │ │ ├── Arpeggiator/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── GainPlugIn/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── MultiOutSynth/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── NoiseGate/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── Surround/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── SimpleFFTExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── audio plugin demo/ │ │ │ │ └── CMakeLists.txt │ │ │ └── audio plugin host/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ ├── binarybuilder/ │ │ │ └── CMakeLists.txt │ │ └── windows dll/ │ │ └── CMakeLists.txt │ ├── JUCE-4.3.1/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ ├── AUv3Synth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AnimationAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AudioAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BLOCKS/ │ │ │ │ ├── BlocksDrawing/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── BlocksMonitor/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── BlocksSynth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BouncingBallWavetableDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── ComponentTutorialExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── Demo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── HelloWorld/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MPETest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MidiTest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── NetworkGraphicsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCMonitor/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCReceiver/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCSender/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OpenGLAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PluckedStringsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PlugInSamples/ │ │ │ │ ├── Arpeggiator/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── GainPlugIn/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── MultiOutSynth/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── NoiseGate/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── Surround/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── SimpleFFTExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── audio plugin demo/ │ │ │ │ └── CMakeLists.txt │ │ │ └── audio plugin host/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ ├── binarybuilder/ │ │ │ └── CMakeLists.txt │ │ └── windows dll/ │ │ └── CMakeLists.txt │ ├── JUCE-5.0.0/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ ├── AUv3Synth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AnimationAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AudioAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BLOCKS/ │ │ │ │ ├── BlocksDrawing/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── BlocksMonitor/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── BlocksSynth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BouncingBallWavetableDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── ComponentTutorialExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── Demo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── HelloWorld/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MPETest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MidiTest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── NetworkGraphicsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCMonitor/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCReceiver/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCSender/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OpenGLAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PluckedStringsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PlugInSamples/ │ │ │ │ ├── Arpeggiator/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── GainPlugIn/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── InterAppAudioEffect/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── MultiOutSynth/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── NoiseGate/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── Surround/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── SimpleFFTExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── audio plugin demo/ │ │ │ │ └── CMakeLists.txt │ │ │ └── audio plugin host/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ ├── binarybuilder/ │ │ │ └── CMakeLists.txt │ │ └── windows dll/ │ │ └── CMakeLists.txt │ ├── JUCE-5.2.1/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ ├── AUv3Synth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AnalyticsCollection/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AnimationAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── AudioAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BLOCKS/ │ │ │ │ ├── BlocksDrawing/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── BlocksMonitor/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── BlocksSynth/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── BouncingBallWavetableDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── ComponentTutorialExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── DSP module plugin demo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── DSPDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── Demo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── HelloWorld/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── InAppPurchase/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MPETest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── MidiTest/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── NetworkGraphicsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCMonitor/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCReceiver/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OSCSender/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── OpenGLAppExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PluckedStringsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PlugInSamples/ │ │ │ │ ├── Arpeggiator/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── GainPlugIn/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── InterAppAudioEffect/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── MultiOutSynth/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ ├── NoiseGate/ │ │ │ │ │ └── CMakeLists.txt │ │ │ │ └── Surround/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── PushNotificationsDemo/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── SimpleFFTExample/ │ │ │ │ └── CMakeLists.txt │ │ │ ├── audio plugin demo/ │ │ │ │ └── CMakeLists.txt │ │ │ └── audio plugin host/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ ├── binarybuilder/ │ │ │ └── CMakeLists.txt │ │ └── windows dll/ │ │ └── CMakeLists.txt │ ├── JUCE-5.3.1/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ └── DemoRunner/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── AudioPluginHost/ │ │ │ └── CMakeLists.txt │ │ ├── BinaryBuilder/ │ │ │ └── CMakeLists.txt │ │ ├── NetworkGraphicsDemo/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ └── WindowsDLL/ │ │ └── CMakeLists.txt │ ├── JUCE-5.4.3/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ └── DemoRunner/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── AudioPluginHost/ │ │ │ └── CMakeLists.txt │ │ ├── BinaryBuilder/ │ │ │ └── CMakeLists.txt │ │ ├── NetworkGraphicsDemo/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ └── WindowsDLL/ │ │ └── CMakeLists.txt │ ├── JUCE-5.4.7/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ └── DemoRunner/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── AudioPluginHost/ │ │ │ └── CMakeLists.txt │ │ ├── BinaryBuilder/ │ │ │ └── CMakeLists.txt │ │ ├── NetworkGraphicsDemo/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ └── WindowsDLL/ │ │ └── CMakeLists.txt │ ├── JUCE-6.0.5/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ └── DemoRunner/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── AudioPluginHost/ │ │ │ └── CMakeLists.txt │ │ ├── BinaryBuilder/ │ │ │ └── CMakeLists.txt │ │ ├── NetworkGraphicsDemo/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ └── WindowsDLL/ │ │ └── CMakeLists.txt │ ├── JUCE-6.1.6/ │ │ ├── CMakeLists.txt │ │ ├── README.rst │ │ ├── examples/ │ │ │ └── DemoRunner/ │ │ │ └── CMakeLists.txt │ │ └── extras/ │ │ ├── AudioPerformanceTest/ │ │ │ └── CMakeLists.txt │ │ ├── AudioPluginHost/ │ │ │ └── CMakeLists.txt │ │ ├── BinaryBuilder/ │ │ │ └── CMakeLists.txt │ │ ├── NetworkGraphicsDemo/ │ │ │ └── CMakeLists.txt │ │ ├── Projucer/ │ │ │ └── CMakeLists.txt │ │ ├── UnitTestRunner/ │ │ │ └── CMakeLists.txt │ │ └── WindowsDLL/ │ │ └── CMakeLists.txt │ └── JUCE-7.0.7/ │ ├── CMakeLists.txt │ ├── README.rst │ ├── examples/ │ │ └── DemoRunner/ │ │ └── CMakeLists.txt │ └── extras/ │ ├── AudioPerformanceTest/ │ │ └── CMakeLists.txt │ ├── AudioPluginHost/ │ │ └── CMakeLists.txt │ ├── BinaryBuilder/ │ │ └── CMakeLists.txt │ ├── NetworkGraphicsDemo/ │ │ └── CMakeLists.txt │ ├── Projucer/ │ │ └── CMakeLists.txt │ ├── UnitTestRunner/ │ │ └── CMakeLists.txt │ └── WindowsDLL/ │ └── CMakeLists.txt ├── tests/ │ ├── diff-compiler-args.cmake │ ├── issue-246/ │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── test-projects/ │ │ ├── entitlements-generation/ │ │ │ ├── .gitignore │ │ │ ├── guiapp-MacOSX/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── binary_dir/ │ │ │ │ ├── AllSettings.entitlements │ │ │ │ ├── PushNotificationsCapability.entitlements │ │ │ │ ├── UseAppSandbox_Inheritance.entitlements │ │ │ │ ├── UseAppSandbox_NoOptions.entitlements │ │ │ │ ├── UseAppSandbox_OneOption.entitlements │ │ │ │ ├── UseAppSandbox_SeveralOptions.entitlements │ │ │ │ ├── UseHardenedRuntime_NoOptions.entitlements │ │ │ │ ├── UseHardenedRuntime_OneOption.entitlements │ │ │ │ ├── UseHardenedRuntime_SeveralOptions.entitlements │ │ │ │ └── default.entitlements │ │ │ ├── guiapp-iOS/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── binary_dir/ │ │ │ │ ├── AppGroupsCapability-empty.entitlements │ │ │ │ ├── AppGroupsCapability-one_ID.entitlements │ │ │ │ ├── AppGroupsCapability-three_IDs.entitlements │ │ │ │ ├── PushNotificationsCapability.entitlements │ │ │ │ ├── default.entitlements │ │ │ │ └── iCloudPermissions.entitlements │ │ │ ├── plugin-MacOSX/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ └── binary_dir/ │ │ │ │ ├── AUv3-AllSettings.entitlements │ │ │ │ ├── AUv3-PushNotificationsCapability.entitlements │ │ │ │ ├── AUv3-UseAppSandbox_Inheritance.entitlements │ │ │ │ ├── AUv3-UseAppSandbox_NoOptions.entitlements │ │ │ │ ├── AUv3-UseAppSandbox_OneOption.entitlements │ │ │ │ ├── AUv3-UseAppSandbox_SeveralOptions.entitlements │ │ │ │ ├── AUv3-UseHardenedRuntime_NoOptions.entitlements │ │ │ │ ├── AUv3-UseHardenedRuntime_OneOption.entitlements │ │ │ │ ├── AUv3-UseHardenedRuntime_SeveralOptions.entitlements │ │ │ │ ├── AUv3-default.entitlements │ │ │ │ ├── AllSettings.entitlements │ │ │ │ ├── PushNotificationsCapability.entitlements │ │ │ │ ├── UseAppSandbox_Inheritance.entitlements │ │ │ │ ├── UseAppSandbox_NoOptions.entitlements │ │ │ │ ├── UseAppSandbox_OneOption.entitlements │ │ │ │ ├── UseAppSandbox_SeveralOptions.entitlements │ │ │ │ ├── UseHardenedRuntime_NoOptions.entitlements │ │ │ │ ├── UseHardenedRuntime_OneOption.entitlements │ │ │ │ ├── UseHardenedRuntime_SeveralOptions.entitlements │ │ │ │ └── default.entitlements │ │ │ └── plugin-iOS/ │ │ │ ├── CMakeLists.txt │ │ │ └── binary_dir/ │ │ │ ├── AUv3-EnableIAA.entitlements │ │ │ ├── AUv3-PushNotificationsCapability.entitlements │ │ │ ├── AUv3-default.entitlements │ │ │ ├── EnableIAA.entitlements │ │ │ ├── PushNotificationsCapability.entitlements │ │ │ └── default.entitlements │ │ ├── no-modules/ │ │ │ ├── consoleapp420/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Builds/ │ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ │ └── consoleapp420.cbp │ │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ │ └── consoleapp420.cbp │ │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ │ └── Makefile │ │ │ │ │ ├── MacOSX/ │ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ │ └── consoleapp420.xcodeproj/ │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ │ ├── consoleapp420.sln │ │ │ │ │ │ ├── consoleapp420.vcxproj │ │ │ │ │ │ ├── consoleapp420.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ └── VisualStudio2015/ │ │ │ │ │ ├── consoleapp420.sln │ │ │ │ │ ├── consoleapp420.vcxproj │ │ │ │ │ ├── consoleapp420.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── JuceLibraryCode/ │ │ │ │ │ ├── AppConfig.h │ │ │ │ │ ├── JuceHeader.h │ │ │ │ │ └── ReadMe.txt │ │ │ │ ├── Source/ │ │ │ │ │ └── foo.cpp │ │ │ │ └── consoleapp420.jucer │ │ │ ├── consoleapp431/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Builds/ │ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ │ └── consoleapp431.cbp │ │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ │ └── consoleapp431.cbp │ │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ │ └── Makefile │ │ │ │ │ ├── MacOSX/ │ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ │ └── consoleapp431.xcodeproj/ │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ │ ├── consoleapp431.sln │ │ │ │ │ │ ├── consoleapp431.vcxproj │ │ │ │ │ │ ├── consoleapp431.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ └── VisualStudio2015/ │ │ │ │ │ ├── consoleapp431.sln │ │ │ │ │ ├── consoleapp431.vcxproj │ │ │ │ │ ├── consoleapp431.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── JuceLibraryCode/ │ │ │ │ │ ├── AppConfig.h │ │ │ │ │ ├── JuceHeader.h │ │ │ │ │ └── ReadMe.txt │ │ │ │ ├── Source/ │ │ │ │ │ └── foo.cpp │ │ │ │ └── consoleapp431.jucer │ │ │ ├── consoleapp500/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Builds/ │ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ │ └── consoleapp500.cbp │ │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ │ └── consoleapp500.cbp │ │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ │ └── Makefile │ │ │ │ │ ├── MacOSX/ │ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ │ └── consoleapp500.xcodeproj/ │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ │ ├── consoleapp500.sln │ │ │ │ │ │ ├── consoleapp500_ConsoleApp.vcxproj │ │ │ │ │ │ └── resources.rc │ │ │ │ │ ├── VisualStudio2015/ │ │ │ │ │ │ ├── consoleapp500.sln │ │ │ │ │ │ ├── consoleapp500_ConsoleApp.vcxproj │ │ │ │ │ │ └── resources.rc │ │ │ │ │ └── VisualStudio2017/ │ │ │ │ │ ├── consoleapp500.sln │ │ │ │ │ ├── consoleapp500_ConsoleApp.vcxproj │ │ │ │ │ └── resources.rc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── JuceLibraryCode/ │ │ │ │ │ ├── AppConfig.h │ │ │ │ │ ├── JuceHeader.h │ │ │ │ │ └── ReadMe.txt │ │ │ │ ├── Source/ │ │ │ │ │ └── foo.cpp │ │ │ │ └── consoleapp500.jucer │ │ │ ├── consoleapp521/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Builds/ │ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ │ └── consoleapp521.cbp │ │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ │ └── consoleapp521.cbp │ │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ │ └── Makefile │ │ │ │ │ ├── MacOSX/ │ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ │ └── consoleapp521.xcodeproj/ │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ │ ├── consoleapp521.sln │ │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj │ │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ ├── VisualStudio2015/ │ │ │ │ │ │ ├── consoleapp521.sln │ │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj │ │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ └── VisualStudio2017/ │ │ │ │ │ ├── consoleapp521.sln │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj │ │ │ │ │ ├── consoleapp521_ConsoleApp.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── JuceLibraryCode/ │ │ │ │ │ ├── AppConfig.h │ │ │ │ │ ├── JuceHeader.h │ │ │ │ │ └── ReadMe.txt │ │ │ │ ├── Source/ │ │ │ │ │ └── foo.cpp │ │ │ │ └── consoleapp521.jucer │ │ │ ├── consoleapp531/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Builds/ │ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ │ └── consoleapp531.cbp │ │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ │ └── consoleapp531.cbp │ │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ │ └── Makefile │ │ │ │ │ ├── MacOSX/ │ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ │ └── consoleapp531.xcodeproj/ │ │ │ │ │ │ └── project.pbxproj │ │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ │ ├── consoleapp531.sln │ │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj │ │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ ├── VisualStudio2015/ │ │ │ │ │ │ ├── consoleapp531.sln │ │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj │ │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj.filters │ │ │ │ │ │ └── resources.rc │ │ │ │ │ └── VisualStudio2017/ │ │ │ │ │ ├── consoleapp531.sln │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj │ │ │ │ │ ├── consoleapp531_ConsoleApp.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── JuceLibraryCode/ │ │ │ │ │ ├── AppConfig.h │ │ │ │ │ ├── JuceHeader.h │ │ │ │ │ └── ReadMe.txt │ │ │ │ ├── Source/ │ │ │ │ │ └── foo.cpp │ │ │ │ └── consoleapp531.jucer │ │ │ └── consoleapp543/ │ │ │ ├── .gitignore │ │ │ ├── Builds/ │ │ │ │ ├── CodeBlocksLinux/ │ │ │ │ │ ├── consoleapp543.cbp │ │ │ │ │ └── resources.rc │ │ │ │ ├── CodeBlocksWindows/ │ │ │ │ │ ├── consoleapp543.cbp │ │ │ │ │ └── resources.rc │ │ │ │ ├── LinuxMakefile/ │ │ │ │ │ └── Makefile │ │ │ │ ├── MacOSX/ │ │ │ │ │ ├── RecentFilesMenuTemplate.nib │ │ │ │ │ └── consoleapp543.xcodeproj/ │ │ │ │ │ ├── project.pbxproj │ │ │ │ │ └── project.xcworkspace/ │ │ │ │ │ └── xcshareddata/ │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ │ ├── VisualStudio2013/ │ │ │ │ │ ├── consoleapp543.sln │ │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj │ │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ ├── VisualStudio2015/ │ │ │ │ │ ├── consoleapp543.sln │ │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj │ │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj.filters │ │ │ │ │ └── resources.rc │ │ │ │ └── VisualStudio2017/ │ │ │ │ ├── consoleapp543.sln │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj │ │ │ │ ├── consoleapp543_ConsoleApp.vcxproj.filters │ │ │ │ └── resources.rc │ │ │ ├── CMakeLists.txt │ │ │ ├── JuceLibraryCode/ │ │ │ │ ├── AppConfig.h │ │ │ │ ├── JuceHeader.h │ │ │ │ └── ReadMe.txt │ │ │ ├── Source/ │ │ │ │ └── foo.cpp │ │ │ └── consoleapp543.jucer │ │ └── plist-generation/ │ │ ├── .gitignore │ │ ├── guiapp-MacOSX/ │ │ │ ├── CMakeLists.txt │ │ │ └── binary_dir/ │ │ │ ├── Info-App-BluetoothUsage-custom.plist │ │ │ ├── Info-App-BluetoothUsage-default.plist │ │ │ ├── Info-App-BundleIdentifier.plist │ │ │ ├── Info-App-CameraUsage-custom.plist │ │ │ ├── Info-App-CameraUsage-default.plist │ │ │ ├── Info-App-Copyright-pre-5.2.0.plist │ │ │ ├── Info-App-Copyright.plist │ │ │ ├── Info-App-DocumentTypes.plist │ │ │ ├── Info-App-ExporterBundleIdentifier.plist │ │ │ ├── Info-App-IconFile.plist │ │ │ ├── Info-App-MicrophoneUsage-custom.plist │ │ │ ├── Info-App-MicrophoneUsage-default.plist │ │ │ ├── Info-App-SendAppleEvents-custom.plist │ │ │ ├── Info-App-SendAppleEvents-default.plist │ │ │ ├── Info-App-Version.plist │ │ │ ├── Info-App-default.plist │ │ │ └── Info-App-pre-5.2.0.plist │ │ ├── guiapp-iOS/ │ │ │ ├── CMakeLists.txt │ │ │ └── binary_dir/ │ │ │ ├── Info-App-AllBackgroundCapabilities.plist │ │ │ ├── Info-App-AudioBackgroundCapability.plist │ │ │ ├── Info-App-BluetoothMIDIBackgroundCapability.plist │ │ │ ├── Info-App-BluetoothUsage-custom.plist │ │ │ ├── Info-App-BluetoothUsage-default.plist │ │ │ ├── Info-App-BundleIdentifier.plist │ │ │ ├── Info-App-CameraUsage-custom.plist │ │ │ ├── Info-App-CameraUsage-default.plist │ │ │ ├── Info-App-Copyright.plist │ │ │ ├── Info-App-ExporterBundleIdentifier.plist │ │ │ ├── Info-App-FileSharingEnabled.plist │ │ │ ├── Info-App-MicrophoneUsage-custom.plist │ │ │ ├── Info-App-MicrophoneUsage-default.plist │ │ │ ├── Info-App-PushNotificationsCapability.plist │ │ │ ├── Info-App-RequiresFullScreen-off.plist │ │ │ ├── Info-App-ScreenOrientations-default.plist │ │ │ ├── Info-App-ScreenOrientations-different.plist │ │ │ ├── Info-App-ScreenOrientations-identical.plist │ │ │ ├── Info-App-StatusBarHidden-pre-6.0.8.plist │ │ │ ├── Info-App-StatusBarHidden.plist │ │ │ ├── Info-App-SupportDocumentBrowser.plist │ │ │ ├── Info-App-Version.plist │ │ │ ├── Info-App-default.plist │ │ │ └── Info-App-pre-6.0.8.plist │ │ ├── plugin-MacOSX/ │ │ │ ├── CMakeLists.txt │ │ │ └── binary_dir/ │ │ │ ├── Info-AAX-default.plist │ │ │ ├── Info-AU-default.plist │ │ │ ├── Info-AU-factoryFunction.plist │ │ │ ├── Info-AU-pre-5.4.0.plist │ │ │ ├── Info-AU-sandboxSafe.plist │ │ │ ├── Info-AUv3_AppExtension-ExporterBundleIdentifier.plist │ │ │ ├── Info-AUv3_AppExtension-Synth.plist │ │ │ ├── Info-AUv3_AppExtension-default.plist │ │ │ ├── Info-AUv3_AppExtension-factoryFunction.plist │ │ │ ├── Info-AUv3_AppExtension-pre-5.0.0.plist │ │ │ ├── Info-AUv3_Standalone-pre-5.0.0.plist │ │ │ ├── Info-RTAS-default.plist │ │ │ ├── Info-Standalone_Plugin-default.plist │ │ │ ├── Info-Unity_Plugin-default.plist │ │ │ ├── Info-VST-default.plist │ │ │ ├── Info-VST3-default.plist │ │ │ └── Info-VST3-pre-5.2.0.plist │ │ └── plugin-iOS/ │ │ ├── CMakeLists.txt │ │ └── binary_dir/ │ │ ├── Info-AUv3_AppExtension-ExporterBundleIdentifier.plist │ │ ├── Info-AUv3_AppExtension-Synth.plist │ │ ├── Info-AUv3_AppExtension-default.plist │ │ ├── Info-AUv3_AppExtension-factoryFunction.plist │ │ ├── Info-AUv3_AppExtension-pre-6.0.8.plist │ │ ├── Info-Standalone_Plugin-IAA.plist │ │ └── Info-Standalone_Plugin-default.plist │ └── test-utils/ │ ├── cmake_make_program/ │ │ └── CMakeLists.txt │ └── simplediff/ │ ├── simplediff.cmake │ └── test_simplediff.cmake └── third-party/ ├── .clang-format └── argh/ ├── LICENSE └── argh.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .appveyor.yml ================================================ branches: only: - main clone_depth: 50 environment: matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 GENERATOR: MinGW Makefiles - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 GENERATOR: Visual Studio 12 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 GENERATOR: Visual Studio 15 2017 install: - cmake --version - git clone --branch=4.2.0 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-4.2.0 - git clone --branch=4.3.1 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-4.3.1 - git clone --branch=5.0.0 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-5.0.0 - git clone --branch=5.2.1 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-5.2.1 - git clone --branch=5.3.1 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-5.3.1 - git clone --branch=5.4.3 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-5.4.3 - git clone --branch=5.4.7 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-5.4.7 - git clone --branch=6.0.5 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-6.0.5 - git clone --branch=6.1.6 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-6.1.6 - git clone --branch=7.0.7 --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-7.0.7 for: - matrix: only: - GENERATOR: MinGW Makefiles build_script: - set PATH=%PATH:C:\Program Files\Git\usr\bin;=% - set PATH=C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin;%PATH% - mkdir %APPVEYOR_BUILD_FOLDER%\build_Debug - mkdir %APPVEYOR_BUILD_FOLDER%\build_Release # Configure and build FRUT with JUCE 4.2.0 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.2.0" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.2.0" # Configure and build FRUT with JUCE 4.3.1 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.3.1" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.3.1" # JUCE 5.0.0 doesn't build with MinGW due to some undeclared symbols in # modules/juce_gui_basics/native/juce_win32_Windowing.cpp # Configure and build FRUT with JUCE 5.2.1 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.2.1" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.2.1" # JUCE 5.3.1 doesn't build with MinGW due to some undeclared symbols in # modules/juce_core/native/juce_win32_Files.cpp # Configure and build FRUT with JUCE 5.4.3 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.3" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.3" # Configure and build FRUT with JUCE 5.4.7 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.7" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.7" # Configure and build FRUT with JUCE 6.0.5 - cd %APPVEYOR_BUILD_FOLDER%\build_Debug - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.0.5" - cmake --build . --parallel - cd %APPVEYOR_BUILD_FOLDER%\build_Release - > cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.0.5" # JUCE 6.1.6 doesn't build with MinGW 5.3.0 due to how juce::UUIDGetter is defined # in juce_core/native/juce_win32_ComSmartPtr.h # Build and install FRUT in ./prefix - cmake .. -DCMAKE_INSTALL_PREFIX="%APPVEYOR_BUILD_FOLDER%/prefix" - cmake --build . --target install --parallel test_script: # Check that generated CMakeLists.txt files are up-to-date - cd %APPVEYOR_BUILD_FOLDER% - > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake - > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake - > cmake -DJUCE_VERSION="4.2.0" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="4.3.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.0.0" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.2.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.3.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.4.3" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.4.7" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="6.0.5" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="6.1.6" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - git diff --exit-code - matrix: only: - GENERATOR: Visual Studio 12 2013 build_script: - mkdir %APPVEYOR_BUILD_FOLDER%\build - cd %APPVEYOR_BUILD_FOLDER%\build # Configure and build FRUT with JUCE 4.2.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.2.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 4.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.0.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.0.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.2.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.2.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.4.3 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.3" - cmake --build . --config Debug --parallel # JUCE 5.4.3 is the last JUCE version that supports Visual Studio 2013 # Build and install FRUT in ./prefix - cmake .. -DCMAKE_INSTALL_PREFIX="%APPVEYOR_BUILD_FOLDER%/prefix" - cmake --build . --config Release --target install --parallel - matrix: only: - GENERATOR: Visual Studio 14 2015 build_script: - mkdir %APPVEYOR_BUILD_FOLDER%\build - cd %APPVEYOR_BUILD_FOLDER%\build # Configure and build FRUT with JUCE 4.2.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.2.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 4.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.0.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.0.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.2.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.2.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.4.3 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.3" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.4.7 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.7" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 6.0.5 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.0.5" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 6.1.6 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.1.6" - cmake --build . --config Debug --parallel # JUCE 6.1.6 is the last JUCE version that supports Visual Studio 2015 # Build and install FRUT in ./prefix - cmake .. -DCMAKE_INSTALL_PREFIX="%APPVEYOR_BUILD_FOLDER%/prefix" - cmake --build . --config Release --target install --parallel build_script: - mkdir %APPVEYOR_BUILD_FOLDER%\build - cd %APPVEYOR_BUILD_FOLDER%\build # Configure and build FRUT with JUCE 4.2.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.2.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 4.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-4.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.0.0 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.0.0" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.2.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.2.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.3.1 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.3.1" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.4.3 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.3" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 5.4.7 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-5.4.7" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 6.0.5 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.0.5" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 6.1.6 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-6.1.6" - cmake --build . --config Debug --parallel # Configure and build FRUT with JUCE 7.0.7 - cmake .. -G "%GENERATOR%" -DJUCE_ROOT="%APPVEYOR_BUILD_FOLDER%/ci/tmp/JUCE-7.0.7" - cmake --build . --config Debug --parallel # Build and install FRUT in ./prefix - cmake .. -DCMAKE_INSTALL_PREFIX="%APPVEYOR_BUILD_FOLDER%/prefix" - cmake --build . --config Release --target install --parallel test_script: # Check that generated CMakeLists.txt files are up-to-date - cd %APPVEYOR_BUILD_FOLDER% - > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake - > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake - > cmake -DJUCE_VERSION="4.2.0" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="4.3.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.0.0" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.2.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.3.1" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.4.3" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="5.4.7" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="6.0.5" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="6.1.6" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - > cmake -DJUCE_VERSION="7.0.7" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake - git diff --quiet - mkdir %APPVEYOR_BUILD_FOLDER%\ci\AllJuceProjects\build - cd %APPVEYOR_BUILD_FOLDER%\ci\AllJuceProjects\build # Configure all JUCE 4.2.0 projects - > cmake .. -G "%GENERATOR%" -DJUCE_VERSION="4.2.0" -DJUCER_AAX_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST3" -DJUCER_VST_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST" # Configure all JUCE 4.3.1 projects - > cmake .. -G "%GENERATOR%" -DJUCE_VERSION="4.3.1" -DJUCER_AAX_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST3" # Configure all JUCE 5.0.0 projects - > cmake .. -G "%GENERATOR%" -DJUCE_VERSION="5.0.0" -DJUCER_AAX_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST3" # Configure all JUCE 5.2.1 projects - > cmake .. -G "%GENERATOR%" -DJUCE_VERSION="5.2.1" -DJUCER_AAX_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST3" # Configure all JUCE 5.3.1 projects - > cmake .. -G "%GENERATOR%" -DJUCE_VERSION="5.3.1" -DJUCER_VST3_SDK_FOLDER="%APPVEYOR_BUILD_FOLDER%/ci/fake-SDKs/VST3" # Configure all JUCE 5.4.3 projects - cmake .. -G "%GENERATOR%" -DJUCE_VERSION="5.4.3" # Configure all JUCE 5.4.7 projects - cmake .. -G "%GENERATOR%" -DJUCE_VERSION="5.4.7" # Configure all JUCE 6.0.5 projects - cmake .. -G "%GENERATOR%" -DJUCE_VERSION="6.0.5" # Configure all JUCE 6.1.6 projects - cmake .. -G "%GENERATOR%" -DJUCE_VERSION="6.1.6" # Configure all JUCE 7.0.7 projects - cmake .. -G "%GENERATOR%" -DJUCE_VERSION="7.0.7" ================================================ FILE: .azure-pipelines.yml ================================================ trigger: branches: include: - main parameters: - name: juceVersions type: object default: [4.2.0, 4.3.1, 5.0.0, 5.2.1, 5.3.1, 5.4.3, 5.4.7, 6.0.5, 6.1.6, 7.0.7] jobs: - job: iOS displayName: iOS / Xcode pool: vmImage: macOS-13 steps: - template: ci/azure-pipelines/steps-iOS.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: Linux_CodeBlocks displayName: Linux / CodeBlocks - Unix Makefiles pool: vmImage: ubuntu-20.04 variables: cmakeGenerator: "CodeBlocks - Unix Makefiles" steps: - script: > sudo apt update && sudo apt install libxcursor-dev libxinerama-dev libxrandr-dev displayName: Install apt packages - script: > sudo apt install gcc-8 g++-8 && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 10 && sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 10 displayName: Install GCC 8 (old versions of JUCE don't build with GCC 9) - template: ci/azure-pipelines/steps-Makefiles.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: Linux_Make displayName: Linux / Unix Makefiles pool: vmImage: ubuntu-20.04 variables: cmakeGenerator: "Unix Makefiles" steps: - script: > sudo apt update && sudo apt install gcc-8 g++-8 libasound2-dev libcurl4-openssl-dev libxcursor-dev libxinerama-dev libxrandr-dev libwebkit2gtk-4.0-dev displayName: Install apt packages - script: > sudo apt install gcc-8 g++-8 && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 10 && sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 10 displayName: Install GCC 8 (old versions of JUCE don't build with GCC 9) - template: ci/azure-pipelines/steps-Makefiles.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: macOS_Make displayName: macOS / Unix Makefiles pool: vmImage: macOS-12 variables: cmakeGenerator: "Unix Makefiles" steps: - template: ci/azure-pipelines/steps-Makefiles.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: macOS_Xcode displayName: macOS / Xcode pool: vmImage: macOS-12 steps: - template: ci/azure-pipelines/steps-Xcode.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: Windows_VS2019 displayName: Windows / Visual Studio 2019 pool: vmImage: windows-2019 variables: cmakeGenerator: "Visual Studio 16 2019" steps: - template: ci/azure-pipelines/steps-VS.yml parameters: juceVersions: ${{ parameters.juceVersions }} - job: Windows_VS2022 displayName: Windows / Visual Studio 2022 pool: vmImage: windows-2022 variables: cmakeGenerator: "Visual Studio 17 2022" steps: - template: ci/azure-pipelines/steps-VS.yml parameters: juceVersions: ${{ parameters.juceVersions }} ================================================ FILE: .cirrus.yml ================================================ task: name: clang-format only_if: $CIRRUS_BASE_BRANCH == "main" || $CIRRUS_BRANCH == "main" container: image: rsmmr/clang:9.0 test_script: - clang-format -version - 'git ls-files {Jucer2CMake/src,cmake/tools}/"*."{cpp,h,hpp} | xargs -d\\n clang-format -i -style=file -verbose' - git diff --exit-code ================================================ FILE: .clang-format ================================================ # Using clang-format 9.0.0 AllowShortFunctionsOnASingleLine: false AlwaysBreakTemplateDeclarations: true BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Allman BreakConstructorInitializersBeforeComma: true ColumnLimit: 90 ConstructorInitializerIndentWidth: 2 ContinuationIndentWidth: 2 IndentPPDirectives: BeforeHash MaxEmptyLinesToKeep: 2 PenaltyReturnTypeOnItsOwnLine: 120 PointerAlignment: Left ================================================ FILE: .github/pull_request_template.md ================================================ Before pressing the "Create pull request" button: - double-check that docs are up-to-date - delete this list ================================================ FILE: .gitignore ================================================ *build/ *prefix/ .DS_Store /ci/tmp/ /cmake/bin/ ================================================ FILE: .readthedocs.yaml ================================================ version: 2 sphinx: configuration: "docs/conf.py" python: install: - requirements: "docs/requirements.txt" ================================================ FILE: CMakeLists.txt ================================================ # Copyright (C) 2018-2021 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . cmake_minimum_required(VERSION 3.4) project(FRUT) add_subdirectory(Jucer2CMake) set(JUCE_modules_DIRS "${JUCE_ROOT}/modules") add_subdirectory(cmake/tools) install(FILES "${CMAKE_CURRENT_LIST_DIR}/cmake/Reprojucer.cmake" DESTINATION "FRUT/cmake") install(DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/cmake/data" DESTINATION "FRUT/cmake") ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at amartin@keytrol.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ================================================ FILE: CONTRIBUTING.md ================================================ # How to contribute to FRUT? Contributions to FRUT are very welcomed and you can contribute even if you don't know anything about CMake. ## Just do it! You can simply convert your existing JUCE projects using `Jucer2CMake` and build them using CMake (see https://github.com/McMartin/FRUT#getting-started). Then create issues (https://github.com/McMartin/FRUT/issues/new) to report any unwanted differences with how your projects are usually built when using Projucer. ## Show your interest Several existing issues are labeled ["missing feature"][missing-feature-issues] and are only waiting for you to comment on them to express your interest for these features. If FRUT is missing another feature that you need and there is no issue for that feature, feel free to create one! ## Help needed Some of the issues are also labeled ["help wanted"][help-wanted-issues] because they concern features that require acquiring third-party SDKs and tools. We need developers who are familiar with these SDKs and tools to build and test theirs JUCE projects while we are adding these features to FRUT. [help-wanted-issues]: https://github.com/McMartin/FRUT/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22 [missing-feature-issues]: https://github.com/McMartin/FRUT/issues?q=is%3Aissue+is%3Aopen+label%3A%22missing+feature%22 ================================================ FILE: Jucer2CMake/CMakeLists.txt ================================================ # Copyright (C) 2020-2023 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . cmake_minimum_required(VERSION 3.4) if(NOT DEFINED JUCE_ROOT) message(FATAL_ERROR "JUCE_ROOT must be defined") endif() get_filename_component(JUCE_ROOT "${JUCE_ROOT}" ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") if(NOT IS_DIRECTORY "${JUCE_ROOT}") message(FATAL_ERROR "No such directory: ${JUCE_ROOT}") endif() project(Jucer2CMake) if(NOT DEFINED CMAKE_CONFIGURATION_TYPES) if(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") message(STATUS "Setting CMAKE_BUILD_TYPE to \"Debug\" as it was not specified.") set(CMAKE_BUILD_TYPE Debug) endif() endif() set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD 17) add_library(Jucer2CMake_JUCE STATIC "") if(APPLE) target_sources(Jucer2CMake_JUCE PRIVATE "${JUCE_ROOT}/modules/juce_core/juce_core.mm") else() target_sources(Jucer2CMake_JUCE PRIVATE "${JUCE_ROOT}/modules/juce_core/juce_core.cpp") endif() target_include_directories(Jucer2CMake_JUCE PUBLIC "${JUCE_ROOT}/modules") target_compile_definitions(Jucer2CMake_JUCE PUBLIC $<$:DEBUG=1> $<$:_DEBUG=1> $<$>:NDEBUG=1> JUCE_DISABLE_JUCE_VERSION_PRINTING=1 JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1 JUCE_MODULE_AVAILABLE_juce_core=1 JUCE_STANDALONE_APPLICATION=1 JUCE_USE_CURL=0 ) if(APPLE) target_compile_options(Jucer2CMake_JUCE PRIVATE -Wno-deprecated-declarations -Wno-register ) find_library(Cocoa_framework "Cocoa") find_library(Foundation_framework "Foundation") find_library(IOKit_framework "IOKit") find_library(Security_framework "Security") target_link_libraries(Jucer2CMake_JUCE PUBLIC ${Cocoa_framework} ${Foundation_framework} ${IOKit_framework} ${Security_framework} ) endif() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") target_compile_options(Jucer2CMake_JUCE PUBLIC -pthread) target_link_libraries(Jucer2CMake_JUCE PUBLIC dl pthread) endif() if(WIN32 AND NOT MSVC) target_compile_options(Jucer2CMake_JUCE PRIVATE -Wno-cpp) target_link_libraries(Jucer2CMake_JUCE PUBLIC -lshlwapi -lversion -lwininet -lwinmm -lws2_32 ) endif() option(Jucer2CMake_WRITE_CRLF_LINE_ENDINGS "Write CR+LF line endings in generated CMakeLists.txt files" OFF ) set(Jucer2CMake_JUCE_LICENSE "Personal" CACHE STRING "JUCE License. Changes the default value for settings that depend on the license." ) set_property(CACHE Jucer2CMake_JUCE_LICENSE PROPERTY STRINGS "Education" "GPL" "Indie" "Personal" "Pro" ) string(CONCAT is_paid_or_gpl "$," "$," "$>" ) add_executable(Jucer2CMake "${CMAKE_CURRENT_LIST_DIR}/src/main.cpp") target_include_directories(Jucer2CMake PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../third-party") target_compile_definitions(Jucer2CMake PRIVATE IS_PAID_OR_GPL=${is_paid_or_gpl} WRITE_CRLF_LINE_ENDINGS=$ ) target_link_libraries(Jucer2CMake PRIVATE Jucer2CMake_JUCE) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options(Jucer2CMake PRIVATE -Werror -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-padded ) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") target_compile_options(Jucer2CMake PRIVATE -Werror -Wall -Wextra) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") target_compile_options(Jucer2CMake PRIVATE /WX /W4 /wd4512) endif() install(TARGETS Jucer2CMake DESTINATION "FRUT/bin") ================================================ FILE: Jucer2CMake/src/argh.hpp ================================================ // Copyright (C) 2021 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" #elif defined(__GNUC__) #pragma GCC diagnostic push #elif defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4800) #endif #include #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #elif defined(_MSC_VER) #pragma warning(pop) #endif ================================================ FILE: Jucer2CMake/src/juce6.hpp ================================================ // Copyright (C) 2021 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #include "utils.hpp" #include "juce_core.hpp" #include #include namespace Jucer2CMake { inline const juce::XmlElement& getRequiredChild(const juce::XmlElement& element, const juce::StringRef childName) { if (const auto pChild = element.getChildByName(childName)) { return *pChild; } printError(element.getTagName() + " element doesn't have " + childName + " child element."); throw ExitException{1}; } inline bool hasModule(const juce::XmlElement& modules, const juce::StringRef moduleId) { for (auto pModule = modules.getFirstChildElement(); pModule != nullptr; pModule = pModule->getNextElement()) { if (pModule->isTextElement()) { continue; } if (pModule->getStringAttribute("id") == moduleId) { return true; } } return false; } inline bool isJuceOptionEnabled(const juce::XmlElement& juceOptions, const juce::StringRef optionName) { return juceOptions.hasAttribute(optionName) && toBoolLikeVar(juceOptions.getStringAttribute(optionName)); } inline void writeJuce6CMakeLists(const Arguments&, const juce::XmlElement& jucerProject, juce::MemoryOutputStream& outputStream) { LineWriter wLn{outputStream}; const auto& projectType = jucerProject.getStringAttribute("projectType"); const auto& jucerProjectName = jucerProject.getStringAttribute("name"); // Preamble { const auto cmakeVersion = projectType == "audioplug" ? "3.15" : "3.12"; wLn(); wLn("cmake_minimum_required(VERSION ", cmakeVersion, ")"); wLn(); wLn("project(\"", jucerProjectName, "\")"); wLn(); wLn(); wLn("find_package(JUCE CONFIG REQUIRED)"); wLn(); wLn(); } const auto& targetName = jucerProjectName; const auto& modules = getRequiredChild(jucerProject, "MODULES"); const auto& juceOptions = getRequiredChild(jucerProject, "JUCEOPTIONS"); const auto writeProjectSettingIfDefined = [&jucerProject, &wLn](juce::StringRef attribute, juce::StringRef keyword) { if (jucerProject.hasAttribute(attribute)) { wLn(" ", keyword, " \"", jucerProject.getStringAttribute(attribute), "\""); } }; const auto writeKeywordAndList = [&wLn](const juce::StringRef keyword, const juce::StringArray& values) { wLn(" ", keyword); for (const auto& item : values) { wLn(" \"", item, "\""); } }; // juce_add_{console_app,gui_app,plugin} { const auto juceAddFunction = [&projectType]() -> juce::String { if (projectType == "guiapp") return "juce_add_gui_app"; if (projectType == "consoleapp") return "juce_add_console_app"; if (projectType == "audioplug") return "juce_add_plugin"; return {}; }(); wLn(juceAddFunction, "(", targetName); // TODO: PRODUCT_NAME wLn(" VERSION \"" + jucerProject.getStringAttribute("version", "1.0.0") + "\""); writeProjectSettingIfDefined("bundleIdentifier", "BUNDLE_ID"); writeProjectSettingIfDefined("companyName", "COMPANY_NAME"); writeProjectSettingIfDefined("companyCopyright", "COMPANY_COPYRIGHT"); writeProjectSettingIfDefined("companyWebsite", "COMPANY_WEBSITE"); writeProjectSettingIfDefined("companyEmail", "COMPANY_EMAIL"); wLn.needsEmptyLine = true; if (projectType == "audioplug") { const auto formats = jucerProject.hasAttribute("pluginFormats") ? convertIdsToStrings( juce::StringArray::fromTokens( jucerProject.getStringAttribute("pluginFormats"), ",", {}), {{"buildVST3", "VST3"}, {"buildAU", "AU"}, {"buildAUv3", "AUv3"}, {"buildAAX", "AAX"}, {"buildStandalone", "Standalone"}, {"buildUnity", "Unity"}, {"buildVST", "VST"}}) : juce::StringArray{"VST3", "AU", "Standalone"}; if (formats.isEmpty()) { wLn(" # FORMATS"); } else { writeKeywordAndList("FORMATS", formats); } writeProjectSettingIfDefined("pluginName", "PLUGIN_NAME"); writeProjectSettingIfDefined("pluginDesc", "DESCRIPTION"); writeProjectSettingIfDefined("pluginManufacturerCode", "PLUGIN_MANUFACTURER_CODE"); writeProjectSettingIfDefined("pluginCode", "PLUGIN_CODE"); const auto characteristics = juce::StringArray::fromTokens( jucerProject.getStringAttribute("pluginCharacteristicsValue"), ",", {}); if (characteristics.contains("pluginIsSynth")) { wLn(" IS_SYNTH TRUE"); } if (characteristics.contains("pluginWantsMidiIn")) { wLn(" NEEDS_MIDI_INPUT TRUE"); } if (characteristics.contains("pluginProducesMidiOut")) { wLn(" NEEDS_MIDI_OUTPUT TRUE"); } if (characteristics.contains("pluginIsMidiEffectPlugin")) { wLn(" IS_MIDI_EFFECT TRUE"); } if (characteristics.contains("pluginEditorRequiresKeys")) { wLn(" EDITOR_WANTS_KEYBOARD_FOCUS TRUE"); } if (characteristics.contains("pluginAAXDisableBypass")) { wLn(" DISABLE_AAX_BYPASS TRUE"); } if (characteristics.contains("pluginAAXDisableMultiMono")) { wLn(" DISABLE_AAX_MULTI_MONO TRUE"); } writeProjectSettingIfDefined("aaxIdentifier", "AAX_IDENTIFIER"); writeProjectSettingIfDefined("pluginAUExportPrefix", "AU_EXPORT_PREFIX"); if (jucerProject.hasAttribute("pluginAUMainType")) { wLn(" AU_MAIN_TYPE \"", getAUMainTypeConstantFromQuotedFourChars( jucerProject.getStringAttribute("pluginAUMainType")), "\""); } if (jucerProject.hasAttribute("pluginAUIsSandboxSafe")) { wLn(" AU_SANDBOX_SAFE ", toBoolLikeVar(jucerProject.getStringAttribute("pluginAUIsSandboxSafe")) ? "TRUE" : "FALSE"); } writeProjectSettingIfDefined("pluginVSTNumMidiInputs", "VST_NUM_MIDI_INS"); writeProjectSettingIfDefined("pluginVSTNumMidiOutputs", "VST_NUM_MIDI_OUTS"); if (jucerProject.hasAttribute("pluginVST3Category")) { const auto vst3Categories = juce::StringArray::fromTokens( jucerProject.getStringAttribute("pluginVST3Category"), ",", {}); if (vst3Categories.isEmpty()) { wLn(" # VST3_CATEGORIES"); } else { writeKeywordAndList("VST3_CATEGORIES", vst3Categories); } } // TODO: AAX_CATEGORY writeProjectSettingIfDefined("pluginVSTCategory", "VST2_CATEGORY"); // TODO: COPY_PLUGIN_AFTER_BUILD // TODO: VST3_COPY_DIR // TODO: AU_COPY_DIR // TODO: AAX_COPY_DIR // TODO: UNITY_COPY_DIR // TODO: VST_COPY_DIR } wLn.needsEmptyLine = true; // TODO: ICON_SMALL // TODO: ICON_BIG // TODO: CUSTOM_XCASSETS_FOLDER // TODO: LAUNCH_STORYBOARD_FILE wLn.needsEmptyLine = true; // TODO: TARGETED_DEVICE_FAMILY // TODO: IPHONE_SCREEN_ORIENTATIONS // TODO: IPAD_SCREEN_ORIENTATIONS // TODO: FILE_SHARING_ENABLED // TODO: DOCUMENT_BROWSER_ENABLED // TODO: STATUS_BAR_HIDDEN // TODO: REQUIRES_FULL_SCREEN // TODO: DOCUMENT_EXTENSIONS // TODO: APP_SANDBOX_ENABLED // TODO: APP_SANDBOX_INHERIT // TODO: APP_SANDBOX_OPTIONS // TODO: HARDENED_RUNTIME_ENABLED // TODO: HARDENED_RUNTIME_OPTIONS // TODO: MICROPHONE_PERMISSION_ENABLED // TODO: MICROPHONE_PERMISSION_TEXT // TODO: CAMERA_PERMISSION_ENABLED // TODO: CAMERA_PERMISSION_TEXT // TODO: BLUETOOTH_PERMISSION_ENABLED // TODO: BLUETOOTH_PERMISSION_TEXT // TODO: SEND_APPLE_EVENTS_PERMISSION_ENABLED // TODO: SEND_APPLE_EVENTS_PERMISSION_TEXT // TODO: BACKGROUND_AUDIO_ENABLED // TODO: BACKGROUND_BLE_ENABLED // TODO: APP_GROUPS_ENABLED // TODO: APP_GROUP_IDS // TODO: ICLOUD_PERMISSIONS_ENABLED // TODO: PUSH_NOTIFICATIONS_ENABLED // TODO: SUPPRESS_AU_PLIST_RESOURCE_USAGE // TODO: PLIST_TO_MERGE wLn.needsEmptyLine = true; if (hasModule(modules, "juce_core") && isJuceOptionEnabled(juceOptions, "JUCE_USE_CURL")) { wLn(" NEEDS_CURL TRUE"); } // TODO: NEEDS_STORE_KIT if (hasModule(modules, "juce_gui_extra") && isJuceOptionEnabled(juceOptions, "JUCE_WEB_BROWSER")) { wLn(" NEEDS_WEB_BROWSER TRUE"); } if (hasModule(modules, "juce_audio_processors") && isJuceOptionEnabled(juceOptions, "JUCE_PLUGINHOST_AU")) { wLn(" PLUGINHOST_AU TRUE"); } wLn.needsEmptyLine = false; wLn(")"); wLn(); } // juce_generate_juce_header { wLn("juce_generate_juce_header(", targetName, ")"); wLn(); } const auto kIgnoreCase = false; // target_compile_definitions { const auto scope = projectType == "audioplug" ? "PUBLIC" : "PRIVATE"; wLn("target_compile_definitions(", targetName); wLn(" ", scope); juce::StringArray moduleConfigFlags; for (auto i = 0, numAttributes = juceOptions.getNumAttributes(); i < numAttributes; ++i) { moduleConfigFlags.add(juceOptions.getAttributeName(i) + "=" + juceOptions.getAttributeValue(i)); } if (hasModule(modules, "juce_core") && !juceOptions.hasAttribute("JUCE_USE_CURL")) { moduleConfigFlags.add("JUCE_USE_CURL=0"); } if (hasModule(modules, "juce_gui_extra") && !juceOptions.hasAttribute("JUCE_WEB_BROWSER")) { moduleConfigFlags.add("JUCE_WEB_BROWSER=0"); } moduleConfigFlags.sort(kIgnoreCase); for (const auto& item : moduleConfigFlags) { wLn(" ", item); } wLn(")"); wLn(); } juce::StringArray sources; juce::StringArray binarySources; std::function processGroup = [&processGroup, &sources, &binarySources](const juce::XmlElement& group) { for (auto pFileOrGroup = group.getFirstChildElement(); pFileOrGroup != nullptr; pFileOrGroup = pFileOrGroup->getNextElement()) { if (pFileOrGroup->isTextElement()) { continue; } if (pFileOrGroup->hasTagName("FILE")) { const auto& file = *pFileOrGroup; if (file.getStringAttribute("compile").getIntValue() == 1) { sources.add(file.getStringAttribute("file")); } if (file.getStringAttribute("resource").getIntValue() == 1) { binarySources.add(file.getStringAttribute("file")); } } else { processGroup(*pFileOrGroup); } } }; processGroup(getRequiredChild(jucerProject, "MAINGROUP")); sources.sort(kIgnoreCase); binarySources.sort(kIgnoreCase); // target_sources { wLn("target_sources(", targetName); writeKeywordAndList("PRIVATE", sources); wLn(")"); wLn(); } // juce_add_binary_data if (!binarySources.isEmpty()) { wLn("juce_add_binary_data(", targetName, "_BinaryData"); writeProjectSettingIfDefined("binaryDataNamespace", "NAMESPACE"); writeKeywordAndList("SOURCES", binarySources); wLn(")"); wLn(); } // target_link_libraries { wLn("target_link_libraries(", targetName); wLn(" PRIVATE"); if (!binarySources.isEmpty()) { wLn(" ", targetName, "_BinaryData"); } for (auto pModule = modules.getFirstChildElement(); pModule != nullptr; pModule = pModule->getNextElement()) { if (pModule->isTextElement()) { continue; } wLn(" juce::", pModule->getStringAttribute("id")); } wLn(" PUBLIC"); wLn(" juce::juce_recommended_config_flags"); wLn(" juce::juce_recommended_lto_flags"); wLn(" juce::juce_recommended_warning_flags"); wLn(")"); } } } // namespace Jucer2CMake ================================================ FILE: Jucer2CMake/src/juce_core.hpp ================================================ // Copyright (C) 2021-2023 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #if defined(__clang__) #pragma clang diagnostic push #if __has_warning("-Watomic-implicit-seq-cst") #pragma clang diagnostic ignored "-Watomic-implicit-seq-cst" #endif #pragma clang diagnostic ignored "-Wcast-align" #pragma clang diagnostic ignored "-Wcast-qual" #pragma clang diagnostic ignored "-Wdocumentation" #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" #pragma clang diagnostic ignored "-Wextra-semi" #pragma clang diagnostic ignored "-Wglobal-constructors" #pragma clang diagnostic ignored "-Wimplicit-fallthrough" #if __has_warning("-Winconsistent-missing-destructor-override") #pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override" #endif #pragma clang diagnostic ignored "-Wmissing-variable-declarations" #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wsign-conversion" #if __has_warning("-Wsuggest-destructor-override") #pragma clang diagnostic ignored "-Wsuggest-destructor-override" #endif #if __has_warning("-Wsuggest-override") #pragma clang diagnostic ignored "-Wsuggest-override" #endif #pragma clang diagnostic ignored "-Wundef" #if __has_warning("-Wundefined-func-template") #pragma clang diagnostic ignored "-Wundefined-func-template" #endif #if __has_warning("-Wunused-template") #pragma clang diagnostic ignored "-Wunused-template" #endif #pragma clang diagnostic ignored "-Wweak-vtables" #if __has_warning("-Wzero-as-null-pointer-constant") #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #elif defined(__GNUC__) #pragma GCC diagnostic push #if __GNUC__ >= 6 #pragma GCC diagnostic ignored "-Wmisleading-indentation" #endif #if __GNUC__ >= 8 #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif #elif defined(_MSC_VER) #pragma warning(push) #endif #include #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #elif defined(_MSC_VER) #pragma warning(pop) #endif ================================================ FILE: Jucer2CMake/src/main.cpp ================================================ // Copyright (C) 2017-2022 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #include "argh.hpp" #include "juce6.hpp" #include "juce_core.hpp" #include "reprojucer.hpp" #include "utils.hpp" #include #include #include #include #include #include using namespace Jucer2CMake; namespace { Arguments parseArguments(const int argc, const char* const argv[]) { const auto knownModes = juce::StringArray{"juce6", "reprojucer"}; const auto knownFlags = std::map{ {"juce6", {"h", "help"}}, {"reprojucer", {"h", "help", "relocatable"}}, }; const auto knownParams = std::map{ {"juce6", {}}, {"reprojucer", {"jucer-version", "juce-modules", "user-modules"}}, }; argh::parser argumentParser; for (const auto& modeAndParams : knownParams) { for (const auto& param : modeAndParams.second) { argumentParser.add_param(param.toStdString()); } } argumentParser.parse(argc, argv); const auto askingForHelp = argumentParser[{"-h", "--help"}]; auto errorInArguments = false; auto mode = juce::String{argumentParser[1]}; if (argumentParser.size() >= 2 && !knownModes.contains(mode)) { printError("invalid mode \"" + mode + "\""); mode = ""; errorInArguments = true; } if (!askingForHelp) { if (argumentParser.size() < 3) { printError("not enough positional arguments"); errorInArguments = true; } else if (argumentParser.size() > 4) { printError("too many positional arguments"); errorInArguments = true; } } if (mode.isNotEmpty()) { for (const auto& flag : argumentParser.flags()) { if (knownParams.at(mode).contains(juce::String{flag})) { printError("expected one argument for \"" + flag + "\""); errorInArguments = true; } else if (!knownFlags.at(mode).contains(juce::String{flag})) { printError("unknown option \"" + flag + "\""); errorInArguments = true; } } for (const auto& paramAndValue : argumentParser.params()) { const auto& param = std::get<0>(paramAndValue); if (knownFlags.at(mode).contains(juce::String{param})) { const auto& value = std::get<1>(paramAndValue); printError("unexpected argument \"" + value + "\" for \"" + param + "\""); errorInArguments = true; } else if (!knownParams.at(mode).contains(juce::String{param})) { printError("unknown option \"" + param + "\""); errorInArguments = true; } } } const auto noModeUsage = askingForHelp ? "usage: Jucer2CMake [--help] []\n" : "usage: Jucer2CMake {juce6,reprojucer} " "[--help] []\n"; const auto noModeHelpText = "\n" "Converts a .jucer file into a CMakeLists.txt file.\n" "The CMakeLists.txt file is written next to the .jucer file (juce6 mode) or in\n" "the current working directory (reprojucer mode).\n" "\n" " what the generated CMakeLists.txt uses:\n" " juce6 - JUCE 6's CMake support\n" " reprojucer - FRUT's Reprojucer\n" "\n" " path to the .jucer file to convert\n" "\n" " -h, --help show this help message and exit\n"; const auto juce6Usage = "usage: Jucer2CMake juce6 [--help]\n"; const auto juce6HelpText = "\n" "Converts a .jucer file into a CMakeLists.txt file that uses JUCE 6's CMake\n" "support.\n" "The CMakeLists.txt file is written next to the .jucer file.\n" "\n" " path to the .jucer file to convert\n" "\n" " -h, --help show this help message and exit\n"; const auto reprojucerUsage = "usage: Jucer2CMake reprojucer []\n" " [--help] [--juce-modules=] [--user-modules=]\n" " [--relocatable]\n"; const auto reprojucerHelpText = "\n" "Converts a .jucer file into a CMakeLists.txt file that uses Reprojucer.cmake.\n" "The CMakeLists.txt file is written in the current working directory.\n" "\n" " path to the .jucer file to convert\n" " path to Reprojucer.cmake\n" "\n" " -h, --help show this help message and exit\n" " --jucer-version version of Projucer that last saved the .jucer file\n" " --juce-modules global path to JUCE modules\n" " --user-modules global path to user modules\n" " --relocatable makes the CMakeLists.txt file independent from\n" " the location of the .jucer file, but requires\n" " defining a variable when calling cmake\n"; const auto usage = std::map{ {"", noModeUsage}, {"juce6", juce6Usage}, {"reprojucer", reprojucerUsage}}; const auto helpText = std::map{ {"", noModeHelpText}, {"juce6", juce6HelpText}, {"reprojucer", reprojucerHelpText}}; if (askingForHelp || errorInArguments) { std::cerr << usage.at(mode) << std::flush; if (askingForHelp) { std::cerr << helpText.at(mode) << std::flush; } throw ExitException{askingForHelp ? 0 : 1}; } const auto existingFilePath = [&argumentParser](juce::StringRef name, size_t index) { if (argumentParser.size() > index) { auto path = juce::String{argumentParser[index]}; if (path.isEmpty() || !getChildFileFromWorkingDirectory(path).existsAsFile()) { printError("No such file (" + name + "): '" + path + "'"); throw ExitException{1}; } return path; } return juce::String{}; }; auto jucerFilePath = existingFilePath("", 2); auto reprojucerFilePath = existingFilePath("", 3); auto jucerVersion = juce::String{argumentParser("--jucer-version", "").str()}; const auto existingDirectoryPath = [&argumentParser](const std::string& name) { if (const auto stream = argumentParser(name)) { auto path = juce::String{stream.str()}; if (path.isEmpty() || !getChildFileFromWorkingDirectory(path).isDirectory()) { printError("No such directory (" + juce::String{name} + "): '" + path + "'"); throw ExitException{1}; } return path; } return juce::String{}; }; auto juceModulesPath = existingDirectoryPath("--juce-modules"); auto userModulesPath = existingDirectoryPath("--user-modules"); auto outputDir = mode == "juce6" ? getChildFileFromWorkingDirectory(jucerFilePath).getParentDirectory() : juce::File::getCurrentWorkingDirectory(); return {std::move(mode), std::move(jucerFilePath), std::move(reprojucerFilePath), std::move(jucerVersion), std::move(juceModulesPath), std::move(userModulesPath), std::move(outputDir), argumentParser["--relocatable"]}; } } // namespace int main(int argc, char* argv[]) { try { const auto args = parseArguments(argc, argv); const auto jucerFile = getChildFileFromWorkingDirectory(args.jucerFilePath); const auto pJucerProject = std::unique_ptr{juce::XmlDocument::parse(jucerFile)}; if (pJucerProject == nullptr || !pJucerProject->hasTagName("JUCERPROJECT")) { printError("'" + args.jucerFilePath + "' is not a valid Jucer project."); return 1; } const auto& jucerProject = *pJucerProject; juce::MemoryOutputStream outputStream; outputStream << "# This file was generated by FRUT's Jucer2CMake from \"" << jucerFile.getFileName() << "\"\n"; if (args.mode == "juce6") { writeJuce6CMakeLists(args, jucerProject, outputStream); } else if (args.mode == "reprojucer") { writeReprojucerCMakeLists(args, jucerProject, outputStream); } else { printError("There is a bug in Jucer2CMake's CLI!"); return 1; } const auto outputFile = args.outputDir.getChildFile("CMakeLists.txt"); std::unique_ptr fileStream{outputFile.createInputStream()}; if (fileStream) { juce::MemoryOutputStream fileContents; fileContents.writeFromInputStream(*fileStream, -1); if (fileContents.getDataSize() == outputStream.getDataSize() && std::memcmp(fileContents.getData(), outputStream.getData(), fileContents.getDataSize()) == 0) { std::cout << outputFile.getFullPathName() << " is already up-to-date." << std::endl; return 0; } } if (outputFile.replaceWithData(outputStream.getData(), outputStream.getDataSize())) { std::cout << outputFile.getFullPathName() << " has been successfully generated." << std::endl; } else { printError("Failed to write to " + outputFile.getFullPathName()); return 1; } } catch (const ExitException& e) { return e.returnValue(); } return 0; } ================================================ FILE: Jucer2CMake/src/reprojucer.hpp ================================================ // Copyright (C) 2017 Matthieu Talbot // Copyright (C) 2017-2022 Alain Martin // Copyright (C) 2017 Florian Goltz // Copyright (C) 2019 Johannes Elliesen // Copyright (C) 2022 Thiébaud Fuchs // Copyright (C) 2023 Adrian Ostrowski // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #include "argh.hpp" #include "juce_core.hpp" #include "utils.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(IS_PAID_OR_GPL) #error IS_PAID_OR_GPL must be defined #endif #if IS_PAID_OR_GPL static const auto kDefaultLicenseBasedValue = "OFF"; #else static const auto kDefaultLicenseBasedValue = "ON"; #endif namespace Jucer2CMake { inline juce::String makeValidIdentifier(juce::String s) { if (s.isEmpty()) { return "unknown"; } s = s.replaceCharacters(".,;:/@", "______") .retainCharacters( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"); if (juce::CharacterFunctions::isDigit(s[0])) { s = "_" + s; } return s; } // Matches _FRUT_make_valid_configuration_name in Reprojucer.cmake. inline juce::String makeValidConfigurationName(const juce::String& configurationName) { auto validName = configurationName.toStdString(); validName = std::regex_replace(validName, std::regex{"[^A-Za-z0-9_]+"}, " "); validName = juce::String{validName}.trim().toStdString(); validName = std::regex_replace(validName, std::regex{"[ ]+"}, "_"); return validName; } inline juce::String cmakePath(const juce::String& path) { return (juce::File::isAbsolutePath(path) ? path : "${CMAKE_CURRENT_LIST_DIR}/" + path) .replace("\\", "/"); } inline juce::String escape(const juce::String& charsToEscape, juce::String value) { auto pos = 0; while ((pos = value.indexOfAnyOf(charsToEscape, pos)) != -1) { value = value.replaceSection(pos, 0, "\\"); pos += 2; } return value; } inline juce::StringArray parsePreprocessorDefinitions(const juce::String& input) { juce::StringArray definitions; for (auto s = input.getCharPointer(); !s.isEmpty();) { s = s.findEndOfWhitespace(); juce::String definition; while (!s.isEmpty() && !s.isWhitespace() && *s != '=') { definition << s.getAndAdvance(); } s = s.findEndOfWhitespace(); juce::String value; if (*s == '=') { ++s; while (!s.isEmpty() && *s == ' ') { ++s; } while (!s.isEmpty() && !s.isWhitespace()) { if (*s == ',') { ++s; break; } if (*s == '\\' && (s[1] == ' ' || s[1] == ',')) { ++s; } value << s.getAndAdvance(); } } if (definition.isNotEmpty()) { definitions.add(value.isEmpty() ? definition : definition + '=' + value); } } return definitions; } inline juce::StringArray parseSearchPaths(const juce::String& input) { juce::StringArray unquotedPaths; for (const auto& path : juce::StringArray::fromTokens(input, ";\r\n", {})) { if (path.isNotEmpty()) { unquotedPaths.add(path.unquoted()); } } return unquotedPaths; } inline const juce::XmlElement& getFallbackXmlElement() noexcept { static const juce::XmlElement fallbackXmlElement{":"}; return fallbackXmlElement; } inline const juce::XmlElement& safeGetChildByName(const juce::XmlElement& element, const juce::StringRef childName) { if (const auto pChild = element.getChildByName(childName)) { return *pChild; } return getFallbackXmlElement(); } inline const juce::XmlElement* getChildByAttributeRecursively( const juce::XmlElement& parent, const juce::StringRef attributeName, const juce::StringRef attributeValue) { if (const auto pChild = parent.getChildByAttribute(attributeName, attributeValue)) { return pChild; } for (auto pChild = parent.getFirstChildElement(); pChild != nullptr; pChild = pChild->getNextElement()) { if (!pChild->isTextElement()) { if (const auto pGrandChild = getChildByAttributeRecursively(*pChild, attributeName, attributeValue)) { return pGrandChild; } } } return nullptr; } inline std::unique_ptr parseProjucerSettings() { const auto projucerSettingsDirectory = #if defined(JUCE_LINUX) && JUCE_LINUX juce::File{"~/.config/Projucer"}; #elif defined(JUCE_MAC) && JUCE_MAC juce::File{"~/Library/Application Support/Projucer"}; #elif defined(JUCE_WINDOWS) && JUCE_WINDOWS juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory) .getChildFile("Projucer"); #else #error Unknown platform #endif return std::unique_ptr{juce::XmlDocument::parse( projucerSettingsDirectory.getChildFile("Projucer.settings"))}; } inline void writeUserNotes(LineWriter& wLn, const juce::XmlElement& element) { if (element.hasAttribute("userNotes")) { wLn(" # NOTES"); const auto& userNotes = element.getStringAttribute("userNotes"); for (const auto& line : juce::StringArray::fromLines(userNotes)) { wLn(" # ", line); } } } inline void writeReprojucerCMakeLists(const Arguments& args, const juce::XmlElement& jucerProject, juce::MemoryOutputStream& outputStream) { const auto jucerFile = getChildFileFromWorkingDirectory(args.jucerFilePath); const auto jucerVersion = args.jucerVersion.isNotEmpty() ? args.jucerVersion : jucerProject.getStringAttribute("jucerVersion", "latest"); const auto jucerVersionTokens = juce::StringArray::fromTokens( jucerVersion == "latest" ? "1000.0.0" : jucerVersion, ".", {}); if (jucerVersionTokens.size() != 3) { printError("'" + jucerVersion + "' is not a valid Jucer version."); throw ExitException{1}; } using Version = std::tuple; const auto jucerVersionAsTuple = [&jucerVersionTokens, &args]() { try { return Version{std::stoi(jucerVersionTokens[0].toStdString()), std::stoi(jucerVersionTokens[1].toStdString()), std::stoi(jucerVersionTokens[2].toStdString())}; } catch (const std::invalid_argument&) { printError("'" + args.jucerFilePath + "' is not a valid Jucer project."); throw ExitException{1}; } }(); if (args.reprojucerFilePath.isNotEmpty() && !args.reprojucerFilePath.endsWith("Reprojucer.cmake")) { printError("'" + args.reprojucerFilePath + "' is not a valid Reprojucer.cmake file."); throw ExitException{1}; } auto needsJuceModulesGlobalPath = false; auto needsUserModulesGlobalPath = false; if (const auto pModules = jucerProject.getChildByName("MODULES")) { for (auto pModule = pModules->getFirstChildElement(); pModule != nullptr; pModule = pModule->getNextElement()) { if (pModule->isTextElement()) { continue; } if (toBoolLikeVar(pModule->getStringAttribute("useGlobalPath"))) { if (pModule->getStringAttribute("id").startsWith("juce_")) { needsJuceModulesGlobalPath = true; } else { needsUserModulesGlobalPath = true; } } } } const auto shouldParseProjucerSettings = (needsJuceModulesGlobalPath && args.juceModulesPath.isEmpty()) || (needsUserModulesGlobalPath && args.userModulesPath.isEmpty()); const auto pProjucerSettings = shouldParseProjucerSettings ? parseProjucerSettings() : nullptr; const auto pProjucerGlobalPaths = [&pProjucerSettings]() -> juce::XmlElement* { if (pProjucerSettings && pProjucerSettings->hasTagName("PROPERTIES")) { if (const auto pValue = pProjucerSettings->getChildByAttribute("name", "PROJECT_DEFAULT_SETTINGS")) { return pValue->getChildByName("PROJECT_DEFAULT_SETTINGS"); } } return nullptr; }(); const auto& juceModulesGlobalPath = args.juceModulesPath.isNotEmpty() ? args.juceModulesPath : needsJuceModulesGlobalPath && pProjucerGlobalPaths ? pProjucerGlobalPaths->getStringAttribute("defaultJuceModulePath") : juce::String{}; if (needsJuceModulesGlobalPath && juceModulesGlobalPath.isEmpty()) { printError( "At least one JUCE module used in " + args.jucerFilePath + " relies on the global \"JUCE Modules\" path set in Projucer. You must " "provide this path using --juce-modules=\"\"."); throw ExitException{1}; } const auto& userModulesGlobalPath = args.userModulesPath.isNotEmpty() ? args.userModulesPath : needsUserModulesGlobalPath && pProjucerGlobalPaths ? pProjucerGlobalPaths->getStringAttribute("defaultUserModulePath") : juce::String{}; if (needsUserModulesGlobalPath && userModulesGlobalPath.isEmpty()) { printError( "At least one user module used in " + args.jucerFilePath + " relies on the global \"User Modules\" path set in Projucer. You must " "provide this path using --user-modules=\"\"."); throw ExitException{1}; } LineWriter wLn{outputStream}; const auto writeUnquoted = [&wLn](const juce::String& cmakeKeyword, const juce::String& value) { if (value.isEmpty()) { wLn(" # ", cmakeKeyword); } else { wLn(" ", cmakeKeyword, " ", value); } }; const auto writeBracket = [&wLn](const juce::String& cmakeKeyword, const juce::String& value) { if (value.isEmpty()) { wLn(" # ", cmakeKeyword); } else { wLn(" ", cmakeKeyword, " [=[", value, "]=]"); } }; const auto writeQuoted = [&wLn](const juce::String& cmakeKeyword, const juce::String& value) { if (value.isEmpty()) { wLn(" # ", cmakeKeyword); } else { wLn(" ", cmakeKeyword, " \"", escape("\\\";", value.trimCharactersAtEnd("\\")), "\""); } }; const auto writeList = [&wLn](const juce::String& cmakeKeyword, const juce::StringArray& values) { if (values.isEmpty()) { wLn(" # ", cmakeKeyword); } else { wLn(" ", cmakeKeyword); for (const auto& item : values) { if (item.isNotEmpty()) { wLn(" \"", escape("\\\";", item.trimCharactersAtEnd("\\")), "\""); } } } }; const auto convertSetting = [&writeQuoted](const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { const auto value = converterFn ? converterFn(element.getStringAttribute(attributeName)) : element.getStringAttribute(attributeName); writeQuoted(cmakeKeyword, value); }; const auto convertSettingIfDefined = [&convertSetting]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { if (element.hasAttribute(attributeName)) { convertSetting(element, attributeName, cmakeKeyword, converterFn); } }; const auto convertSettingWithDefault = [&convertSetting]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const juce::String& defaultValue) { if (element.hasAttribute(attributeName)) { convertSetting(element, attributeName, cmakeKeyword, {}); } else { convertSetting(element, attributeName, cmakeKeyword, [&defaultValue](const juce::String&) { return defaultValue; }); } }; const auto convertOnOffSetting = [&writeUnquoted]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { const auto value = converterFn ? converterFn(element.getStringAttribute(attributeName)) : juce::String{ element.hasAttribute(attributeName) ? toBoolLikeVar(element.getStringAttribute(attributeName)) ? "ON" : "OFF" : ""}; writeUnquoted(cmakeKeyword, value); }; const auto convertOnOffSettingIfDefined = [&convertOnOffSetting]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { if (element.hasAttribute(attributeName)) { convertOnOffSetting(element, attributeName, cmakeKeyword, converterFn); } }; const auto convertOnOffSettingWithDefault = [&convertOnOffSetting]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const juce::String& defaultValue) { if (element.hasAttribute(attributeName)) { convertOnOffSetting(element, attributeName, cmakeKeyword, {}); } else { convertOnOffSetting(element, attributeName, cmakeKeyword, [&defaultValue](const juce::String&) { return defaultValue; }); } }; const auto convertRawStringSetting = [&writeBracket](const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { const auto value = converterFn ? converterFn(element.getStringAttribute(attributeName)) : element.getStringAttribute(attributeName); writeBracket(cmakeKeyword, value); }; const auto convertRawStringSettingIfDefined = [&convertRawStringSetting]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { if (element.hasAttribute(attributeName)) { convertRawStringSetting(element, attributeName, cmakeKeyword, converterFn); } }; const auto convertSettingAsList = [&writeList]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { const auto values = converterFn ? converterFn(element.getStringAttribute(attributeName)) : juce::StringArray::fromLines(element.getStringAttribute(attributeName)); writeList(cmakeKeyword, values); }; const auto convertSettingAsListIfDefined = [&convertSettingAsList]( const juce::XmlElement& element, const juce::StringRef attributeName, const juce::String& cmakeKeyword, const std::function& converterFn) { if (element.hasAttribute(attributeName)) { convertSettingAsList(element, attributeName, cmakeKeyword, converterFn); } }; const auto jucerFileName = jucerFile.getFileName(); const auto& jucerProjectName = jucerProject.getStringAttribute("name"); // Preamble { wLn(); wLn("cmake_minimum_required(VERSION 3.4)"); wLn(); wLn("project(\"", jucerProjectName, "\")"); wLn(); wLn(); } // include(Reprojucer) { if (args.reprojucerFilePath.isNotEmpty()) { const auto relativeReprojucerDirPath = getChildFileFromWorkingDirectory(args.reprojucerFilePath) .getParentDirectory() .getRelativePathFrom(args.outputDir); wLn("list(APPEND CMAKE_MODULE_PATH \"", cmakePath(relativeReprojucerDirPath), "\")"); } else { wLn("# list(APPEND CMAKE_MODULE_PATH" " \"${CMAKE_CURRENT_LIST_DIR}//cmake\")"); } wLn("include(Reprojucer)"); wLn(); wLn(); } auto escapedJucerFileName = jucerFileName.toStdString(); std::replace_if( escapedJucerFileName.begin(), escapedJucerFileName.end(), [](const std::string::value_type& c) { return !(std::isalpha(c, std::locale::classic()) || std::isdigit(c, std::locale::classic())); }, '_'); const auto jucerFileCMakeVar = juce::String{escapedJucerFileName} + "_FILE"; // get_filename_component() or set(*_FILE) { if (args.relocatable) { wLn("if(NOT DEFINED ", jucerFileCMakeVar, ")"); wLn(" message(FATAL_ERROR \"", jucerFileCMakeVar, " must be defined\")"); wLn("endif()"); wLn(); wLn("get_filename_component(", jucerFileCMakeVar); wLn(" \"${", jucerFileCMakeVar, "}\" ABSOLUTE"); wLn(" BASE_DIR \"${CMAKE_BINARY_DIR}\""); wLn(")"); } else { wLn("set(", jucerFileCMakeVar); const auto relativeJucerFilePath = getChildFileFromWorkingDirectory(args.jucerFilePath) .getRelativePathFrom(args.outputDir); wLn(" \"", cmakePath(relativeJucerFilePath), "\""); wLn(")"); } wLn(); wLn(); } // set({JUCE,USER}_MODULES_GLOBAL_PATH) { if (juceModulesGlobalPath.isNotEmpty()) { std::cout << "Using '" << juceModulesGlobalPath << "' as global \"JUCE Modules\" path." << std::endl; wLn("set(JUCE_MODULES_GLOBAL_PATH \"", cmakePath(juceModulesGlobalPath), "\")"); } if (userModulesGlobalPath.isNotEmpty()) { std::cout << "Using '" << userModulesGlobalPath << "' as global \"User Modules\" path." << std::endl; wLn("set(USER_MODULES_GLOBAL_PATH \"", cmakePath(userModulesGlobalPath), "\")"); } if (juceModulesGlobalPath.isNotEmpty() || userModulesGlobalPath.isNotEmpty()) { wLn(); wLn(); } } // jucer_project_begin() { wLn("jucer_project_begin("); if (jucerProject.hasAttribute("jucerFormatVersion")) { writeQuoted("JUCER_FORMAT_VERSION", jucerProject.getStringAttribute("jucerFormatVersion")); } if (jucerVersion != "latest") { writeQuoted("JUCER_VERSION", jucerVersion); } writeQuoted("PROJECT_FILE", "${" + jucerFileCMakeVar + "}"); convertSetting(jucerProject, "id", "PROJECT_ID", {}); wLn(")"); wLn(); } const auto& projectType = jucerProject.getStringAttribute("projectType"); // jucer_project_settings() { wLn("jucer_project_settings("); convertSetting(jucerProject, "name", "PROJECT_NAME", {}); convertSettingWithDefault(jucerProject, "version", "PROJECT_VERSION", "1.0.0"); convertSettingIfDefined(jucerProject, "companyName", "COMPANY_NAME", {}); convertSettingIfDefined(jucerProject, "companyCopyright", "COMPANY_COPYRIGHT", {}); convertSettingIfDefined(jucerProject, "companyWebsite", "COMPANY_WEBSITE", {}); convertSettingIfDefined(jucerProject, "companyEmail", "COMPANY_EMAIL", {}); convertOnOffSettingIfDefined(jucerProject, "useAppConfig", "USE_GLOBAL_APPCONFIG_HEADER", {}); convertOnOffSettingIfDefined(jucerProject, "addUsingNamespaceToJuceHeader", "ADD_USING_NAMESPACE_JUCE_TO_JUCE_HEADER", {}); const auto tagLine = juce::String{" # Required for closed source applications" " without an Indie or Pro JUCE license"}; if (jucerVersionAsTuple >= Version{5, 0, 0} && jucerVersionAsTuple < Version{6, 0, 0}) { if (jucerProject.hasAttribute("reportAppUsage")) { convertOnOffSetting(jucerProject, "reportAppUsage", "REPORT_JUCE_APP_USAGE", [&tagLine](const juce::String& value) { return (toBoolLikeVar(value) ? "ON" : "OFF") + tagLine; }); } else { writeUnquoted("REPORT_JUCE_APP_USAGE", kDefaultLicenseBasedValue + tagLine); } } if (jucerVersionAsTuple >= Version{5, 0, 0}) { if (jucerProject.hasAttribute("displaySplashScreen")) { convertOnOffSetting(jucerProject, "displaySplashScreen", "DISPLAY_THE_JUCE_SPLASH_SCREEN", [&tagLine](const juce::String& value) { return (toBoolLikeVar(value) ? "ON" : "OFF") + tagLine; }); } else { writeUnquoted("DISPLAY_THE_JUCE_SPLASH_SCREEN", kDefaultLicenseBasedValue + tagLine); } convertSettingIfDefined(jucerProject, "splashScreenColour", "SPLASH_SCREEN_COLOUR", {}); } const auto projectTypeDescription = [&projectType]() -> juce::String { if (projectType == "guiapp") return "GUI Application"; if (projectType == "consoleapp") return "Console Application"; if (projectType == "library") return "Static Library"; if (projectType == "dll") return "Dynamic Library"; if (projectType == "audioplug") return "Audio Plug-in"; return {}; }(); writeQuoted("PROJECT_TYPE", projectTypeDescription); const auto defaultCompanyName = [&jucerProject]() { const auto& companyNameString = jucerProject.getStringAttribute("companyName"); return companyNameString.isEmpty() ? "yourcompany" : companyNameString; }(); const auto defaultBundleIdentifier = jucerVersionAsTuple >= Version{5, 4, 0} ? "com." + makeValidIdentifier(defaultCompanyName) + "." + makeValidIdentifier(jucerProjectName) : "com.yourcompany." + makeValidIdentifier(jucerProjectName); convertSettingWithDefault(jucerProject, "bundleIdentifier", "BUNDLE_IDENTIFIER", defaultBundleIdentifier); convertSettingIfDefined(jucerProject, "maxBinaryFileSize", "BINARYDATACPP_SIZE_LIMIT", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "Default"; return juce::File::descriptionOfSizeInBytes( value.getIntValue()); }); if (jucerProject.hasAttribute("includeBinaryInJuceHeader")) { convertOnOffSetting(jucerProject, "includeBinaryInJuceHeader", "INCLUDE_BINARYDATA", {}); } else { convertOnOffSettingIfDefined(jucerProject, "includeBinaryInAppConfig", "INCLUDE_BINARYDATA", {}); } convertSettingIfDefined(jucerProject, "binaryDataNamespace", "BINARYDATA_NAMESPACE", {}); if (jucerProject.hasAttribute("cppLanguageStandard")) { convertSetting(jucerProject, "cppLanguageStandard", "CXX_LANGUAGE_STANDARD", [](const juce::String& value) -> juce::String { if (value == "11") return "C++11"; if (value == "14") return "C++14"; if (value == "17") return "C++17"; if (value == "20") return "C++20"; if (value == "latest") return "Use Latest"; return {}; }); } else if (jucerVersionAsTuple >= Version{7, 0, 3}) { writeQuoted("CXX_LANGUAGE_STANDARD", "C++17"); } else if (jucerVersionAsTuple > Version{5, 2, 0}) { writeQuoted("CXX_LANGUAGE_STANDARD", "C++14"); } else if (jucerVersionAsTuple > Version{5, 0, 2}) { writeQuoted("CXX_LANGUAGE_STANDARD", "C++11"); } convertSettingAsListIfDefined(jucerProject, "defines", "PREPROCESSOR_DEFINITIONS", parsePreprocessorDefinitions); convertSettingAsListIfDefined(jucerProject, "headerPath", "HEADER_SEARCH_PATHS", parseSearchPaths); convertRawStringSettingIfDefined(jucerProject, "postExportShellCommandPosix", "POST_EXPORT_SHELL_COMMAND_MACOS_LINUX", {}); convertRawStringSettingIfDefined(jucerProject, "postExportShellCommandWin", "POST_EXPORT_SHELL_COMMAND_WINDOWS", {}); writeUserNotes(wLn, jucerProject); wLn(")"); wLn(); // jucer_audio_plugin_settings() if (projectType == "audioplug") { wLn("jucer_audio_plugin_settings("); const auto vstIsLegacy = jucerVersionAsTuple > Version{5, 3, 2}; if (jucerVersionAsTuple >= Version{5, 3, 1}) { if (jucerProject.hasAttribute("pluginFormats")) { convertSettingAsList( jucerProject, "pluginFormats", "PLUGIN_FORMATS", [&jucerVersionAsTuple, &vstIsLegacy](const juce::String& value) { const auto supportsUnity = jucerVersionAsTuple >= Version{5, 3, 2}; return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{vstIsLegacy ? "" : "buildVST", vstIsLegacy ? "" : "VST"}, {"buildVST3", "VST3"}, {"buildAU", "AU"}, {"buildAUv3", "AUv3"}, {"buildRTAS", "RTAS"}, {"buildAAX", "AAX"}, {"buildStandalone", "Standalone"}, {supportsUnity ? "buildUnity" : "", supportsUnity ? "Unity" : ""}, {"enableIAA", "Enable IAA"}, {vstIsLegacy ? "buildVST" : "", vstIsLegacy ? "VST (Legacy)" : ""}}); }); } else { convertSettingAsList( jucerProject, "pluginFormats", "PLUGIN_FORMATS", [&vstIsLegacy](const juce::String&) { return juce::StringArray{vstIsLegacy ? "VST3" : "VST", "AU", "Standalone"}; }); } if (jucerProject.hasAttribute("pluginCharacteristicsValue")) { convertSettingAsList( jucerProject, "pluginCharacteristicsValue", "PLUGIN_CHARACTERISTICS", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"pluginIsSynth", "Plugin is a Synth"}, {"pluginWantsMidiIn", "Plugin MIDI Input"}, {"pluginProducesMidiOut", "Plugin MIDI Output"}, {"pluginIsMidiEffectPlugin", "MIDI Effect Plugin"}, {"pluginEditorRequiresKeys", "Plugin Editor Requires Keyboard Focus"}, {"pluginRTASDisableBypass", "Disable RTAS Bypass"}, {"pluginAAXDisableBypass", "Disable AAX Bypass"}, {"pluginRTASDisableMultiMono", "Disable RTAS Multi-Mono"}, {"pluginAAXDisableMultiMono", "Disable AAX Multi-Mono"}}); }); } else { wLn(" # PLUGIN_CHARACTERISTICS"); } } else { convertOnOffSettingWithDefault(jucerProject, "buildVST", "BUILD_VST", "ON"); convertOnOffSettingWithDefault(jucerProject, "buildVST3", "BUILD_VST3", "OFF"); convertOnOffSettingWithDefault(jucerProject, "buildAU", "BUILD_AUDIOUNIT", "ON"); convertOnOffSettingWithDefault(jucerProject, "buildAUv3", "BUILD_AUDIOUNIT_V3", "OFF"); convertOnOffSettingWithDefault(jucerProject, "buildRTAS", "BUILD_RTAS", "OFF"); convertOnOffSettingWithDefault(jucerProject, "buildAAX", "BUILD_AAX", "OFF"); if (jucerVersionAsTuple >= Version{5, 0, 0}) { convertOnOffSettingWithDefault(jucerProject, "buildStandalone", "BUILD_STANDALONE_PLUGIN", "OFF"); convertOnOffSettingWithDefault(jucerProject, "enableIAA", "ENABLE_INTER_APP_AUDIO", "OFF"); } } convertSettingWithDefault(jucerProject, "pluginName", "PLUGIN_NAME", jucerProjectName); convertSettingWithDefault(jucerProject, "pluginDesc", "PLUGIN_DESCRIPTION", jucerProjectName); convertSettingWithDefault(jucerProject, "pluginManufacturer", "PLUGIN_MANUFACTURER", defaultCompanyName); convertSettingWithDefault(jucerProject, "pluginManufacturerCode", "PLUGIN_MANUFACTURER_CODE", "Manu"); const auto defaultPluginCode = [&jucerProject]() { const auto& projectId = jucerProject.getStringAttribute("id"); const auto s = makeValidIdentifier(projectId + projectId) + "xxxx"; return s.substring(0, 1).toUpperCase() + s.substring(1, 4).toLowerCase(); }(); convertSettingWithDefault(jucerProject, "pluginCode", "PLUGIN_CODE", defaultPluginCode); convertSetting(jucerProject, "pluginChannelConfigs", "PLUGIN_CHANNEL_CONFIGURATIONS", {}); const auto pluginCharacteristics = juce::StringArray::fromTokens( jucerProject.getStringAttribute("pluginCharacteristicsValue"), ",", {}); const auto isSynthAudioPlugin = jucerVersionAsTuple >= Version{5, 3, 1} ? pluginCharacteristics.contains("pluginIsSynth") : toBoolLikeVar(jucerProject.getStringAttribute("pluginIsSynth")); if (jucerVersionAsTuple < Version{5, 3, 1}) { wLn(juce::String{" PLUGIN_IS_A_SYNTH "} + (isSynthAudioPlugin ? "ON" : "OFF")); convertOnOffSettingWithDefault(jucerProject, "pluginWantsMidiIn", "PLUGIN_MIDI_INPUT", "OFF"); convertOnOffSettingWithDefault(jucerProject, "pluginProducesMidiOut", "PLUGIN_MIDI_OUTPUT", "OFF"); convertOnOffSettingWithDefault(jucerProject, "pluginIsMidiEffectPlugin", "MIDI_EFFECT_PLUGIN", "OFF"); convertOnOffSettingWithDefault(jucerProject, "pluginEditorRequiresKeys", "KEY_FOCUS", "OFF"); } if (jucerVersionAsTuple >= Version{5, 3, 1}) { convertSettingWithDefault(jucerProject, "aaxIdentifier", "PLUGIN_AAX_IDENTIFIER", defaultBundleIdentifier); } convertSettingWithDefault(jucerProject, "pluginAUExportPrefix", "PLUGIN_AU_EXPORT_PREFIX", makeValidIdentifier(jucerProjectName) + "AU"); if (jucerVersionAsTuple >= Version{5, 3, 1}) { if (jucerProject.hasAttribute("pluginAUMainType")) { convertSetting(jucerProject, "pluginAUMainType", "PLUGIN_AU_MAIN_TYPE", getAUMainTypeConstantFromQuotedFourChars); } else { convertSetting(jucerProject, "pluginAUMainType", "PLUGIN_AU_MAIN_TYPE", [&pluginCharacteristics](const juce::String&) -> juce::String { if (pluginCharacteristics.contains("pluginIsMidiEffectPlugin")) return "kAudioUnitType_MIDIProcessor"; // 'aumi' if (pluginCharacteristics.contains("pluginIsSynth")) return "kAudioUnitType_MusicDevice"; // 'aumu' if (pluginCharacteristics.contains("pluginWantsMidiIn")) return "kAudioUnitType_MusicEffect"; // 'aumf' return "kAudioUnitType_Effect"; // 'aufx' }); } } else { convertSetting(jucerProject, "pluginAUMainType", "PLUGIN_AU_MAIN_TYPE", {}); } convertOnOffSettingIfDefined(jucerProject, "pluginAUIsSandboxSafe", "PLUGIN_AU_IS_SANDBOX_SAFE", {}); if (jucerProject.hasAttribute("pluginVSTNumMidiInputs") || (jucerVersionAsTuple >= Version{5, 4, 2} && pluginCharacteristics.contains("pluginWantsMidiIn"))) { convertSettingWithDefault(jucerProject, "pluginVSTNumMidiInputs", "PLUGIN_VST_NUM_MIDI_INPUTS", "16"); } if (jucerProject.hasAttribute("pluginVSTNumMidiOutputs") || (jucerVersionAsTuple >= Version{5, 4, 2} && pluginCharacteristics.contains("pluginProducesMidiOut"))) { convertSettingWithDefault(jucerProject, "pluginVSTNumMidiOutputs", "PLUGIN_VST_NUM_MIDI_OUTPUTS", "16"); } if (!vstIsLegacy) { convertSettingWithDefault( jucerProject, "pluginVSTCategory", jucerVersionAsTuple > Version{5, 3, 0} ? "PLUGIN_VST_CATEGORY" : "VST_CATEGORY", jucerVersionAsTuple >= Version{5, 3, 1} ? (isSynthAudioPlugin ? "kPlugCategSynth" : "kPlugCategEffect") : ""); } if (jucerProject.hasAttribute("pluginVST3Category") || jucerVersionAsTuple >= Version{5, 3, 1}) { if (jucerProject.hasAttribute("pluginVST3Category")) { convertSettingAsList( jucerProject, "pluginVST3Category", "PLUGIN_VST3_CATEGORY", [](const juce::String& value) { auto vst3Categories = juce::StringArray::fromTokens(value, ",", {}); if (vst3Categories.contains("Instrument")) { vst3Categories.move(vst3Categories.indexOf("Instrument"), 0); } if (vst3Categories.contains("Fx")) { vst3Categories.move(vst3Categories.indexOf("Fx"), 0); } return vst3Categories; }); } else { convertSettingAsList(jucerProject, "pluginVST3Category", "PLUGIN_VST3_CATEGORY", [isSynthAudioPlugin](const juce::String&) { return isSynthAudioPlugin ? juce::StringArray{"Instrument", "Synth"} : juce::StringArray{"Fx"}; }); } } if (jucerVersionAsTuple >= Version{5, 3, 1}) { if (jucerProject.hasAttribute("pluginRTASCategory")) { convertSettingAsList(jucerProject, "pluginRTASCategory", "PLUGIN_RTAS_CATEGORY", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"0", "ePlugInCategory_None"}, {"1", "ePlugInCategory_EQ"}, {"2", "ePlugInCategory_Dynamics"}, {"4", "ePlugInCategory_PitchShift"}, {"8", "ePlugInCategory_Reverb"}, {"16", "ePlugInCategory_Delay"}, {"32", "ePlugInCategory_Modulation"}, {"64", "ePlugInCategory_Harmonic"}, {"128", "ePlugInCategory_NoiseReduction"}, {"256", "ePlugInCategory_Dither"}, {"512", "ePlugInCategory_SoundField"}, {"1024", "ePlugInCategory_HWGenerators"}, {"2048", "ePlugInCategory_SWGenerators"}, {"4096", "ePlugInCategory_WrappedPlugin"}, {"8192", "ePlugInCategory_Effect"}}); }); } else { convertSettingAsList(jucerProject, "pluginRTASCategory", "PLUGIN_RTAS_CATEGORY", [isSynthAudioPlugin](const juce::String&) { return juce::StringArray{ isSynthAudioPlugin ? "ePlugInCategory_SWGenerators" : "ePlugInCategory_None"}; }); } if (jucerProject.hasAttribute("pluginAAXCategory")) { convertSettingAsList(jucerProject, "pluginAAXCategory", "PLUGIN_AAX_CATEGORY", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"0", "AAX_ePlugInCategory_None"}, {"1", "AAX_ePlugInCategory_EQ"}, {"2", "AAX_ePlugInCategory_Dynamics"}, {"4", "AAX_ePlugInCategory_PitchShift"}, {"8", "AAX_ePlugInCategory_Reverb"}, {"16", "AAX_ePlugInCategory_Delay"}, {"32", "AAX_ePlugInCategory_Modulation"}, {"64", "AAX_ePlugInCategory_Harmonic"}, {"128", "AAX_ePlugInCategory_NoiseReduction"}, {"256", "AAX_ePlugInCategory_Dither"}, {"512", "AAX_ePlugInCategory_SoundField"}, {"1024", "AAX_ePlugInCategory_HWGenerators"}, {"2048", "AAX_ePlugInCategory_SWGenerators"}, {"4096", "AAX_ePlugInCategory_WrappedPlugin"}, {"8192", "AAX_EPlugInCategory_Effect"}}); }); } else { convertSettingAsList(jucerProject, "pluginAAXCategory", "PLUGIN_AAX_CATEGORY", [isSynthAudioPlugin](const juce::String&) { return juce::StringArray{ isSynthAudioPlugin ? "AAX_ePlugInCategory_SWGenerators" : "AAX_ePlugInCategory_None"}; }); } } else { convertSetting(jucerProject, "pluginRTASCategory", "PLUGIN_RTAS_CATEGORY", {}); convertSetting(jucerProject, "pluginAAXCategory", "PLUGIN_AAX_CATEGORY", {}); } if (vstIsLegacy) { convertSettingWithDefault( jucerProject, "pluginVSTCategory", "PLUGIN_VST_LEGACY_CATEGORY", isSynthAudioPlugin ? "kPlugCategSynth" : "kPlugCategEffect"); } if (jucerVersionAsTuple < Version{5, 3, 1}) { convertSetting(jucerProject, "aaxIdentifier", "PLUGIN_AAX_IDENTIFIER", {}); } wLn(")"); wLn(); } } // jucer_project_files() { const auto projectHasCompilerFlagSchemes = jucerProject.getStringAttribute("compilerFlagSchemes").isNotEmpty(); struct File { bool compile; bool xcodeResource; bool binaryResource; juce::String path; juce::String compilerFlagScheme; }; const auto writeFiles = [&projectHasCompilerFlagSchemes, &wLn](const juce::String& fullGroupName, const std::vector& files) { if (!files.empty()) { const auto longestPathLength = std::max_element(files.begin(), files.end(), [](const File& lhs, const File& rhs) { return lhs.path.length() < rhs.path.length(); }) ->path.length(); const auto nineSpaces = " "; wLn("jucer_project_files(\"", fullGroupName, "\""); if (projectHasCompilerFlagSchemes) { wLn("# Compile Xcode Binary File", juce::String::repeatedString(" ", longestPathLength) + "Compiler Flag"); wLn("# Resource Resource", juce::String::repeatedString(" ", longestPathLength + 6) + "Scheme"); } else { wLn("# Compile Xcode Binary File"); wLn("# Resource Resource"); } for (const auto& file : files) { const auto compilerFlagScheme = file.compilerFlagScheme.isEmpty() ? "" : juce::String::repeatedString(" ", longestPathLength - file.path.length() + 2) + "\"" + file.compilerFlagScheme + "\""; wLn(" ", (file.compile ? "x" : "."), nineSpaces, (file.xcodeResource ? "x" : "."), nineSpaces, (file.binaryResource ? "x" : "."), nineSpaces, "\"", file.path, "\"", compilerFlagScheme); } wLn(")"); wLn(); } }; juce::StringArray groupNames; std::function processGroup = [&groupNames, &processGroup, &writeFiles](const juce::XmlElement& group) { groupNames.add(group.getStringAttribute("name")); const auto fullGroupName = groupNames.joinIntoString("/"); std::vector files; for (auto pFileOrGroup = group.getFirstChildElement(); pFileOrGroup != nullptr; pFileOrGroup = pFileOrGroup->getNextElement()) { if (pFileOrGroup->isTextElement()) { continue; } if (pFileOrGroup->hasTagName("FILE")) { const auto& file = *pFileOrGroup; files.push_back({file.getStringAttribute("compile").getIntValue() == 1, file.getStringAttribute("xcodeResource").getIntValue() == 1, file.getStringAttribute("resource").getIntValue() == 1, file.getStringAttribute("file"), file.getStringAttribute("compilerFlagScheme")}); } else { writeFiles(fullGroupName, files); files.clear(); processGroup(*pFileOrGroup); } } writeFiles(fullGroupName, files); groupNames.strings.removeLast(); }; processGroup(safeGetChildByName(jucerProject, "MAINGROUP")); } // jucer_project_module() { const auto& modulePaths = [&jucerProject]() -> const juce::XmlElement& { const auto& exportFormats = safeGetChildByName(jucerProject, "EXPORTFORMATS"); for (auto pExporter = exportFormats.getFirstChildElement(); pExporter != nullptr; pExporter = pExporter->getNextElement()) { if (!pExporter->isTextElement()) { return safeGetChildByName(*pExporter, "MODULEPATHS"); } } return getFallbackXmlElement(); }(); const auto juceModules = getChildFileFromWorkingDirectory(juceModulesGlobalPath); const auto userModules = getChildFileFromWorkingDirectory(userModulesGlobalPath); const auto& modules = safeGetChildByName(jucerProject, "MODULES"); for (auto pModule = modules.getFirstChildElement(); pModule != nullptr; pModule = pModule->getNextElement()) { if (pModule->isTextElement()) { continue; } const auto& module = *pModule; const auto& moduleName = module.getStringAttribute("id"); const auto useGlobalPath = toBoolLikeVar(module.getStringAttribute("useGlobalPath")); const auto isJuceModule = moduleName.startsWith("juce_"); const auto modulePath = [&modulePaths, &moduleName]() -> juce::String { if (const auto pModulePath = modulePaths.getChildByAttribute("id", moduleName)) { return pModulePath->getStringAttribute("path"); } return {}; }(); wLn("jucer_project_module("); wLn(" ", moduleName); wLn(" PATH \"", useGlobalPath ? (isJuceModule ? "${JUCE_MODULES_GLOBAL_PATH}" : "${USER_MODULES_GLOBAL_PATH}") : modulePath.replace("\\", "/"), "\""); const auto moduleHeader = (useGlobalPath ? (isJuceModule ? juceModules : userModules) : jucerFile.getParentDirectory().getChildFile(modulePath)) .getChildFile(moduleName) .getChildFile(moduleName + ".h"); if (!moduleHeader.existsAsFile()) { std::cerr << "warning: Couldn't a find module header for " << moduleName << " module at \"" << moduleHeader.getFullPathName() << "\"." << std::endl; } juce::StringArray moduleHeaderLines; moduleHeader.readLines(moduleHeaderLines); const auto& modulesOptions = safeGetChildByName(jucerProject, "JUCEOPTIONS"); for (const auto& line : moduleHeaderLines) { if (line.startsWith("/** Config: ")) { const auto moduleOption = line.substring(12).trim(); const auto& optionValue = modulesOptions.getStringAttribute(moduleOption); if (optionValue == "1" || optionValue == "enabled") { writeUnquoted(moduleOption, "ON"); } else if (optionValue == "0" || optionValue == "disabled") { writeUnquoted(moduleOption, "OFF"); } else { writeUnquoted(moduleOption, ""); } } } wLn(")"); wLn(); } } // jucer_appconfig_header() { const auto appConfigFile = jucerFile.getSiblingFile("JuceLibraryCode").getChildFile("AppConfig.h"); juce::StringArray appConfigLines; appConfigLines.addLines(appConfigFile.loadFileAsString()); if (!appConfigLines.isEmpty()) { juce::StringArray userCodeSectionLines; for (auto i = 0; i < appConfigLines.size(); ++i) { if (appConfigLines[i].contains("[BEGIN_USER_CODE_SECTION]")) { for (auto j = i + 1; j < appConfigLines.size() && !appConfigLines[j].contains("[END_USER_CODE_SECTION]"); ++j) { userCodeSectionLines.add(appConfigLines[j]); } break; } } const auto kDefaultProjucerUserCodeSectionCommentLines = juce::StringArray{ "", "// (You can add your own code in this section, and the Projucer will not " "overwrite it)", ""}; if (userCodeSectionLines != kDefaultProjucerUserCodeSectionCommentLines) { wLn("jucer_appconfig_header("); wLn(" USER_CODE_SECTION"); wLn("\"", escape("\\\"", userCodeSectionLines.joinIntoString("\n")), "\""); wLn(")"); wLn(); } } } // jucer_export_target() and jucer_export_target_configuration() { const auto supportedExporters = juce::StringArray{"XCODE_MAC", "XCODE_IPHONE", "VS2022", "VS2019", "VS2017", "VS2015", "VS2013", "LINUX_MAKE", "CODEBLOCKS_WINDOWS", "CODEBLOCKS_LINUX"}; const auto exporterNames = std::map{ {"XCODE_MAC", jucerVersionAsTuple < Version{6, 0, 2} ? "Xcode (MacOSX)" : "Xcode (macOS)"}, {"XCODE_IPHONE", "Xcode (iOS)"}, {"VS2022", "Visual Studio 2022"}, {"VS2019", "Visual Studio 2019"}, {"VS2017", "Visual Studio 2017"}, {"VS2015", "Visual Studio 2015"}, {"VS2013", "Visual Studio 2013"}, {"LINUX_MAKE", "Linux Makefile"}, {"CODEBLOCKS_WINDOWS", "Code::Blocks (Windows)"}, {"CODEBLOCKS_LINUX", "Code::Blocks (Linux)"}, }; juce::StringPairArray configurationNamesMapping; const auto& exportFormats = safeGetChildByName(jucerProject, "EXPORTFORMATS"); for (auto pExporter = exportFormats.getFirstChildElement(); pExporter != nullptr; pExporter = pExporter->getNextElement()) { if (pExporter->isTextElement()) { continue; } const auto& exporter = *pExporter; const auto& exporterType = exporter.getTagName(); if (!supportedExporters.contains(exporterType)) { continue; } const auto exporterName = exporterNames.at(exporterType); const auto& configurations = safeGetChildByName(exporter, "CONFIGURATIONS"); wLn("jucer_export_target("); wLn(" \"", exporterName, "\""); const auto isXcodeExporter = exporterType == "XCODE_MAC" || exporterType == "XCODE_IPHONE"; const auto isVSExporter = exporterType == "VS2022" || exporterType == "VS2019" || exporterType == "VS2017" || exporterType == "VS2015" || exporterType == "VS2013"; juce::StringArray needTargetFolder; if (jucerProject.hasAttribute("headerPath")) { needTargetFolder.add("HEADER_SEARCH_PATHS"); } if (isXcodeExporter) { if (exporter.hasAttribute("frameworkSearchPaths")) { needTargetFolder.add("FRAMEWORK_SEARCH_PATHS"); } if (exporter.hasAttribute("prebuildCommand")) { needTargetFolder.add("PREBUILD_SHELL_SCRIPT"); } if (exporter.hasAttribute("postbuildCommand")) { needTargetFolder.add("POSTBUILD_SHELL_SCRIPT"); } } for (auto pConfiguration = configurations.getFirstChildElement(); pConfiguration != nullptr; pConfiguration = pConfiguration->getNextElement()) { if (pConfiguration->isTextElement()) { continue; } if (pConfiguration->hasAttribute("headerPath")) { needTargetFolder.add("HEADER_SEARCH_PATHS"); } if (pConfiguration->hasAttribute("libraryPath")) { needTargetFolder.add("EXTRA_LIBRARY_SEARCH_PATHS"); } if (isVSExporter) { if (pConfiguration->hasAttribute("prebuildCommand")) { needTargetFolder.add("PREBUILD_COMMAND"); } if (pConfiguration->hasAttribute("postbuildCommand")) { needTargetFolder.add("POSTBUILD_COMMAND"); } } } const auto kIgnoreCase = false; needTargetFolder.removeDuplicates(kIgnoreCase); if (!needTargetFolder.isEmpty()) { wLn(" TARGET_PROJECT_FOLDER \"", exporter.getStringAttribute("targetFolder"), "\" # used by ", needTargetFolder.joinIntoString(", ")); } const auto isAudioPlugin = projectType == "audioplug"; const auto pluginFormats = juce::StringArray::fromTokens( jucerProject.getStringAttribute("pluginFormats"), ",", {}); const auto hasJuceAudioProcessorsModule = safeGetChildByName(jucerProject, "MODULES") .getChildByAttribute("id", "juce_audio_processors") != nullptr; const auto hasVst2Interface = jucerVersionAsTuple > Version{4, 2, 3}; const auto isVstAudioPlugin = isAudioPlugin && (pluginFormats.contains("buildVST") || toBoolLikeVar(jucerProject.getStringAttribute("buildVST"))); const auto& pluginHostVstOption = safeGetChildByName(jucerProject, "JUCEOPTIONS") .getStringAttribute("JUCE_PLUGINHOST_VST"); const auto isVstPluginHost = hasJuceAudioProcessorsModule && (pluginHostVstOption == "enabled" || pluginHostVstOption == "1"); if (!hasVst2Interface && (isVstAudioPlugin || isVstPluginHost)) { convertSetting(exporter, "vstFolder", "VST_SDK_FOLDER", {}); } const auto vstIsLegacy = jucerVersionAsTuple > Version{5, 3, 2}; if (vstIsLegacy && (isVstAudioPlugin || isVstPluginHost)) { convertSetting(exporter, "vstLegacyFolder", "VST_LEGACY_SDK_FOLDER", {}); } const auto supportsVst3 = exporterType == "XCODE_MAC" || isVSExporter; const auto isVst3AudioPlugin = isAudioPlugin && (pluginFormats.contains("buildVST3") || toBoolLikeVar(jucerProject.getStringAttribute("buildVST3"))); const auto& pluginHostVst3Option = safeGetChildByName(jucerProject, "JUCEOPTIONS") .getStringAttribute("JUCE_PLUGINHOST_VST3"); const auto isVst3PluginHost = hasJuceAudioProcessorsModule && (pluginHostVst3Option == "enabled" || pluginHostVst3Option == "1"); if (supportsVst3 && (isVst3AudioPlugin || isVst3PluginHost)) { convertSetting(exporter, "vst3Folder", "VST3_SDK_FOLDER", {}); } const auto supportsAaxRtas = exporterType == "XCODE_MAC" || isVSExporter; if (supportsAaxRtas && isAudioPlugin) { if (pluginFormats.contains("buildAAX") || toBoolLikeVar(jucerProject.getStringAttribute("buildAAX"))) { convertSetting(exporter, "aaxFolder", "AAX_SDK_FOLDER", {}); } if (pluginFormats.contains("buildRTAS") || toBoolLikeVar(jucerProject.getStringAttribute("buildRTAS"))) { convertSetting(exporter, "rtasFolder", "RTAS_SDK_FOLDER", {}); } } convertSettingAsListIfDefined(exporter, "extraDefs", "EXTRA_PREPROCESSOR_DEFINITIONS", parsePreprocessorDefinitions); convertSettingAsListIfDefined(exporter, "extraCompilerFlags", "EXTRA_COMPILER_FLAGS", [](const juce::String& value) { return juce::StringArray::fromTokens(value, false); }); const auto compilerFlagSchemesArray = juce::StringArray::fromTokens( jucerProject.getStringAttribute("compilerFlagSchemes"), ",", {}); // Use a juce::HashMap like Projucer does, in order to get the same ordering. juce::HashMap> compilerFlagSchemesMap; for (const auto& scheme : compilerFlagSchemesArray) { compilerFlagSchemesMap.set(scheme, {}); } for (juce::HashMap>::Iterator i(compilerFlagSchemesMap); i.next();) { convertSettingIfDefined(exporter, i.getKey(), "COMPILER_FLAGS_FOR_" + i.getKey(), {}); } convertSettingAsListIfDefined(exporter, "extraLinkerFlags", "EXTRA_LINKER_FLAGS", [](const juce::String& value) { return juce::StringArray::fromTokens(value, false); }); convertSettingAsListIfDefined(exporter, "externalLibraries", "EXTERNAL_LIBRARIES_TO_LINK", {}); convertOnOffSettingIfDefined(exporter, "enableGNUExtensions", "GNU_COMPILER_EXTENSIONS", {}); const auto convertIcon = [&jucerProject](const juce::String& fileId) -> juce::String { if (fileId.isNotEmpty()) { if (const auto pFile = getChildByAttributeRecursively( safeGetChildByName(jucerProject, "MAINGROUP"), "id", fileId)) { return pFile->getStringAttribute("file"); } } return ""; }; convertSettingIfDefined(exporter, "smallIcon", "ICON_SMALL", convertIcon); convertSettingIfDefined(exporter, "bigIcon", "ICON_LARGE", convertIcon); if (exporterType == "XCODE_IPHONE") { convertSettingIfDefined(exporter, "customXcassetsFolder", "CUSTOM_XCASSETS_FOLDER", {}); convertSettingIfDefined(exporter, "customLaunchStoryboard", "CUSTOM_LAUNCH_STORYBOARD", {}); } if (isXcodeExporter) { convertSettingAsListIfDefined( exporter, "customXcodeResourceFolders", "CUSTOM_XCODE_RESOURCE_FOLDERS", [](const juce::String& value) { auto folders = juce::StringArray::fromLines(value); folders.trim(); return folders; }); if (isAudioPlugin) { convertOnOffSettingIfDefined(exporter, "duplicateAppExResourcesFolder", "ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION", {}); } } if (exporterType == "XCODE_IPHONE") { convertSettingIfDefined(exporter, "iosDeviceFamily", "DEVICE_FAMILY", [](const juce::String& value) -> juce::String { if (value == "1") return "iPhone"; if (value == "2") return "iPad"; if (value == "1,2") return "Universal"; return value; }); const auto screenOrientationFn = [](const juce::String& value) -> juce::String { if (value == "portraitlandscape") return "Portrait and Landscape"; if (value == "portrait") return "Portrait"; if (value == "landscape") return "Landscape"; return value; }; const auto screenOrientationsFn = [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"UIInterfaceOrientationPortrait", "Portrait"}, {"UIInterfaceOrientationPortraitUpsideDown", "Portrait Upside Down"}, {"UIInterfaceOrientationLandscapeLeft", "Landscape Left"}, {"UIInterfaceOrientationLandscapeRight", "Landscape Right"}}); }; if (exporter.hasAttribute("iosScreenOrientation")) { const auto value = exporter.getStringAttribute("iosScreenOrientation"); const auto screenOrientations = screenOrientationsFn(value); if (!screenOrientations.isEmpty()) { writeList("IPHONE_SCREEN_ORIENTATION", screenOrientations); } else { writeQuoted("IPHONE_SCREEN_ORIENTATION", screenOrientationFn(value)); } } if (exporter.hasAttribute("iPadScreenOrientation")) { const auto value = exporter.getStringAttribute("iPadScreenOrientation"); const auto screenOrientations = screenOrientationsFn(value); if (!screenOrientations.isEmpty()) { writeList("IPAD_SCREEN_ORIENTATION", screenOrientations); } else { writeQuoted("IPAD_SCREEN_ORIENTATION", screenOrientationFn(value)); } } convertOnOffSettingIfDefined(exporter, "UIFileSharingEnabled", "FILE_SHARING_ENABLED", {}); convertOnOffSettingIfDefined(exporter, "UISupportsDocumentBrowser", "SUPPORT_DOCUMENT_BROWSER", {}); convertOnOffSettingIfDefined(exporter, "UIStatusBarHidden", "STATUS_BAR_HIDDEN", {}); convertOnOffSettingIfDefined(exporter, "UIRequiresFullScreen", "REQUIRES_FULL_SCREEN", {}); } if (exporterType == "XCODE_MAC") { if (projectType == "guiapp") { convertSettingAsListIfDefined( exporter, "documentExtensions", "DOCUMENT_FILE_EXTENSIONS", [](const juce::String& value) { return juce::StringArray::fromTokens(value, ",", {}); }); } } convertOnOffSettingIfDefined(exporter, "useLegacyBuildSystem", "USE_LEGACY_BUILD_SYSTEM", {}); if (exporterType == "XCODE_MAC") { convertSettingAsListIfDefined(exporter, "xcodeValidArchs", "VALID_ARCHITECTURES", [](const juce::String& value) { return juce::StringArray::fromTokens(value, ",", {}); }); convertOnOffSettingIfDefined(exporter, "appSandbox", "USE_APP_SANDBOX", {}); convertOnOffSettingIfDefined(exporter, "appSandboxInheritance", "APP_SANDBOX_INHERITANCE", {}); convertSettingAsListIfDefined( exporter, "appSandboxOptions", "APP_SANDBOX_OPTIONS", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"com.apple.security.network.server", "Network: Incoming Connections (Server)"}, {"com.apple.security.network.client", "Network: Outgoing Connections (Client)"}, {"com.apple.security.device.camera", "Hardware: Camera"}, {"com.apple.security.device.microphone", "Hardware: Microphone"}, {"com.apple.security.device.usb", "Hardware: USB"}, {"com.apple.security.print", "Hardware: Printing"}, {"com.apple.security.device.bluetooth", "Hardware: Bluetooth"}, {"com.apple.security.personal-information.addressbook", "App Data: Contacts"}, {"com.apple.security.personal-information.location", "App Data: Location"}, {"com.apple.security.personal-information.calendars", "App Data: Calendar"}, {"com.apple.security.files.user-selected.read-only", "File Access: User Selected File (Read Only)"}, {"com.apple.security.files.user-selected.read-write", "File Access: User Selected File (Read/Write)"}, {"com.apple.security.files.downloads.read-only", "File Access: Downloads Folder (Read Only)"}, {"com.apple.security.files.downloads.read-write", "File Access: Downloads Folder (Read/Write)"}, {"com.apple.security.files.pictures.read-only", "File Access: Pictures Folder (Read Only)"}, {"com.apple.security.files.pictures.read-write", "File Access: Pictures Folder (Read/Write)"}, {"com.apple.security.assets.music.read-only", "File Access: Music Folder (Read Only)"}, {"com.apple.security.assets.music.read-write", "File Access: Music Folder (Read/Write)"}, {"com.apple.security.assets.movies.read-only", "File Access: Movies Folder (Read Only)"}, {"com.apple.security.assets.movies.read-write", "File Access: Movies Folder (Read/Write)"}, {"com.apple.security.temporary-exception.audio-unit-host", "Temporary Exception: Audio Unit Hosting"}, {"com.apple.security.temporary-exception.mach-lookup.global-name", "Temporary Exception: Global Mach Service"}, {"com.apple.security.temporary-exception.mach-register.global-name", "Temporary Exception: Global Mach Service Dynamic Registration"}, {"com.apple.security.temporary-exception.files.home-relative-path.read-" "only", "Temporary Exception: Home Directory File Access (Read Only)"}, {"com.apple.security.temporary-exception.files.home-relative-path.read-" "write", "Temporary Exception: Home Directory File Access (Read/Write)"}, {"com.apple.security.temporary-exception.files.absolute-path.read-only", "Temporary Exception: Absolute Path File Access (Read Only)"}, {"com.apple.security.temporary-exception.files.absolute-path.read-write", "Temporary Exception: Absolute Path File Access (Read/Write)"}, {"com.apple.security.temporary-exception.iokit-user-client-class", "Temporary Exception: IOKit User Client Class"}, {"com.apple.security.temporary-exception.shared-preference.read-only", "Temporary Exception: Shared Preference Domain (Read Only)"}, {"com.apple.security.temporary-exception.shared-preference.read-write", "Temporary Exception: Shared Preference Domain (Read/Write)"}}); }); convertOnOffSettingIfDefined(exporter, "hardenedRuntime", "USE_HARDENED_RUNTIME", {}); if (jucerVersionAsTuple >= Version{5, 4, 4}) { convertSettingAsListIfDefined( exporter, "hardenedRuntimeOptions", "HARDENED_RUNTIME_OPTIONS", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"com.apple.security.cs.allow-jit", "Runtime Exceptions: Allow Execution of JIT-compiled Code"}, {"com.apple.security.cs.allow-unsigned-executable-memory", "Runtime Exceptions: Allow Unsigned Executable Memory"}, {"com.apple.security.cs.allow-dyld-environment-variables", "Runtime Exceptions: Allow DYLD Environment Variables"}, {"com.apple.security.cs.disable-library-validation", "Runtime Exceptions: Disable Library Validation"}, {"com.apple.security.cs.disable-executable-page-protection", "Runtime Exceptions: Disable Executable Memory Protection"}, {"com.apple.security.cs.debugger", "Runtime Exceptions: Debugging Tool"}, {"com.apple.security.device.audio-input", "Resource Access: Audio Input"}, {"com.apple.security.device.camera", "Resource Access: Camera"}, {"com.apple.security.personal-information.location", "Resource Access: Location"}, {"com.apple.security.personal-information.addressbook", "Resource Access: Address Book"}, {"com.apple.security.personal-information.calendars", "Resource Access: Calendar"}, {"com.apple.security.personal-information.photos-library", "Resource Access: Photos Library"}, {"com.apple.security.automation.apple-events", "Resource Access: Apple Events"}}); }); } else { convertSettingAsListIfDefined( exporter, "hardenedRuntimeOptions", "HARDENED_RUNTIME_OPTIONS", [](const juce::String& value) { return convertIdsToStrings( juce::StringArray::fromTokens(value, ",", {}), {{"com.apple.security.cs.allow-jit", "Allow Execution of JIT-compiled Code"}, {"com.apple.security.cs.allow-unsigned-executable-memory", "Allow Unsigned Executable Memory"}, {"com.apple.security.cs.allow-dyld-environment-variables", "Allow DYLD Environment Variables"}, {"com.apple.security.cs.disable-library-validation", "Disable Library Validation"}, {"com.apple.security.cs.disable-executable-page-protection", "Disable Executable Memory Protection"}, {"com.apple.security.cs.debugger", "Debugging Tool"}, {"com.apple.security.device.audio-input", "Audio Input"}, {"com.apple.security.device.camera", "Camera"}, {"com.apple.security.personal-information.location", "Location"}, {"com.apple.security.personal-information.addressbook", "Address Book"}, {"com.apple.security.personal-information.calendars", "Calendar"}, {"com.apple.security.personal-information.photos-library", "Photos Library"}, {"com.apple.security.automation.apple-events", "Apple Events"}}); }); } } if (isXcodeExporter) { convertOnOffSettingIfDefined(exporter, "microphonePermissionNeeded", "MICROPHONE_ACCESS", {}); convertSettingIfDefined(exporter, "microphonePermissionsText", "MICROPHONE_ACCESS_TEXT", {}); convertOnOffSettingIfDefined(exporter, "cameraPermissionNeeded", "CAMERA_ACCESS", {}); convertSettingIfDefined(exporter, "cameraPermissionText", "CAMERA_ACCESS_TEXT", {}); convertOnOffSettingIfDefined(exporter, "iosBluetoothPermissionNeeded", "BLUETOOTH_ACCESS", {}); convertSettingIfDefined(exporter, "iosBluetoothPermissionText", "BLUETOOTH_ACCESS_TEXT", {}); } if (exporterType == "XCODE_MAC") { convertOnOffSettingIfDefined(exporter, "sendAppleEventsPermissionNeeded", "SEND_APPLE_EVENTS", {}); convertSettingIfDefined(exporter, "sendAppleEventsPermissionText", "SEND_APPLE_EVENTS_TEXT", {}); } if (isXcodeExporter) { convertOnOffSettingIfDefined(exporter, "iosInAppPurchasesValue", "IN_APP_PURCHASES_CAPABILITY", {}); } if (exporterType == "XCODE_IPHONE") { convertOnOffSettingIfDefined(exporter, "iosContentSharing", "CONTENT_SHARING", {}); convertOnOffSettingIfDefined(exporter, "iosBackgroundAudio", "AUDIO_BACKGROUND_CAPABILITY", {}); convertOnOffSettingIfDefined(exporter, "iosBackgroundBle", "BLUETOOTH_MIDI_BACKGROUND_CAPABILITY", {}); convertOnOffSettingIfDefined(exporter, "iosAppGroups", "APP_GROUPS_CAPABILITY", {}); convertOnOffSettingIfDefined(exporter, "iCloudPermissions", "ICLOUD_PERMISSIONS", {}); } if (isXcodeExporter) { convertOnOffSettingIfDefined(exporter, "iosPushNotifications", "PUSH_NOTIFICATIONS_CAPABILITY", {}); convertSettingIfDefined(exporter, "customPList", "CUSTOM_PLIST", {}); convertOnOffSettingIfDefined(exporter, "PListPreprocess", "PLIST_PREPROCESS", {}); convertOnOffSettingIfDefined(exporter, "pListPreprocess", "PLIST_PREPROCESS", {}); const auto convertPrefixHeader = [&jucerFile, &exporter](const juce::String& value) { if (value.isEmpty()) return juce::String{}; const auto jucerFileDir = jucerFile.getParentDirectory(); const auto targetProjectDir = jucerFileDir.getChildFile(exporter.getStringAttribute("targetFolder")); return targetProjectDir.getChildFile(value).getRelativePathFrom(jucerFileDir); }; convertSettingIfDefined(exporter, "PListPrefixHeader", "PLIST_PREFIX_HEADER", convertPrefixHeader); convertSettingIfDefined(exporter, "pListPrefixHeader", "PLIST_PREFIX_HEADER", convertPrefixHeader); convertOnOffSettingIfDefined(exporter, "suppressPlistResourceUsage", "SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY", {}); convertSettingAsListIfDefined( exporter, "extraFrameworks", jucerVersionAsTuple > Version{5, 3, 2} ? "EXTRA_SYSTEM_FRAMEWORKS" : "EXTRA_FRAMEWORKS", [](const juce::String& value) { auto frameworks = juce::StringArray::fromTokens(value, ",;", "\"'"); frameworks.trim(); return frameworks; }); convertSettingAsListIfDefined(exporter, "frameworkSearchPaths", "FRAMEWORK_SEARCH_PATHS", {}); convertSettingAsListIfDefined(exporter, "extraCustomFrameworks", "EXTRA_CUSTOM_FRAMEWORKS", {}); convertSettingAsListIfDefined(exporter, "embeddedFrameworks", "EMBEDDED_FRAMEWORKS", {}); convertSettingAsListIfDefined(exporter, "xcodeSubprojects", "XCODE_SUBPROJECTS", {}); convertRawStringSettingIfDefined(exporter, "prebuildCommand", "PREBUILD_SHELL_SCRIPT", {}); convertRawStringSettingIfDefined(exporter, "postbuildCommand", "POSTBUILD_SHELL_SCRIPT", {}); convertSettingIfDefined(exporter, "bundleIdentifier", "EXPORTER_BUNDLE_IDENTIFIER", {}); convertSettingIfDefined(exporter, "iosDevelopmentTeamID", "DEVELOPMENT_TEAM_ID", {}); } if (exporterType == "XCODE_IPHONE") { convertSettingAsListIfDefined( exporter, "iosAppGroupsId", "APP_GROUP_ID", [](const juce::String& value) { auto groups = juce::StringArray::fromTokens(value, ";", {}); groups.trim(); return groups; }); } if (isXcodeExporter) { convertOnOffSettingIfDefined(exporter, "keepCustomXcodeSchemes", "KEEP_CUSTOM_XCODE_SCHEMES", {}); convertOnOffSettingIfDefined(exporter, "useHeaderMap", "USE_HEADERMAP", {}); } if (isVSExporter) { convertSettingIfDefined(exporter, "msvcManifestFile", "MANIFEST_FILE", {}); if (exporter.hasAttribute("toolset")) { const auto& toolset = exporter.getStringAttribute("toolset"); if (toolset.isEmpty()) { wLn(" # PLATFORM_TOOLSET \"(default)\""); } else { wLn(" # PLATFORM_TOOLSET \"", toolset, "\""); } } convertSettingIfDefined( exporter, "IPPLibrary", "USE_IPP_LIBRARY", [&jucerVersionAsTuple](const juce::String& value) -> juce::String { if (value.isEmpty()) return "No"; if (value == "true") return jucerVersionAsTuple >= Version{5, 2, 1} ? "Yes (Default Mode)" : "Yes (Default Linking)"; if (value == "Parallel_Static") return "Multi-Threaded Static Library"; if (value == "Sequential") return "Single-Threaded Static Library"; if (value == "Parallel_Dynamic") return "Multi-Threaded DLL"; if (value == "Sequential_Dynamic") return "Single-Threaded DLL"; return {}; }); convertSettingIfDefined(exporter, "IPP1ALibrary", "USE_IPP_LIBRARY_ONE_API", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "No"; if (value == "true") return "Yes (Default Linking)"; if (value == "Static_Library") return "Static Library"; if (value == "Dynamic_Library") return "Dynamic Library"; return value; }); convertSettingIfDefined(exporter, "MKL1ALibrary", "USE_MKL_LIBRARY_ONE_API", [](const juce::String& value) -> juce::String { return value.isEmpty() ? "No" : value; }); convertSettingIfDefined(exporter, "windowsTargetPlatformVersion", "WINDOWS_TARGET_PLATFORM", {}); if (exporterType == "VS2017") { convertSettingIfDefined(exporter, "cppLanguageStandard", "CXX_STANDARD_TO_USE", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "(default)"; if (value == "stdcpp14") return "C++14"; if (value == "stdcpplatest") return "Latest C++ Standard"; return {}; }); } } if (exporterType == "LINUX_MAKE") { convertSettingIfDefined(exporter, "cppLanguageStandard", "CXX_STANDARD_TO_USE", [](const juce::String& value) -> juce::String { if (value == "-std=c++03") return "C++03"; if (value == "-std=c++11") return "C++11"; if (value == "-std=c++14") return "C++14"; return {}; }); convertSettingAsListIfDefined( exporter, "linuxExtraPkgConfig", "PKGCONFIG_LIBRARIES", [](const juce::String& value) { return juce::StringArray::fromTokens(value, " ", "\"'"); }); } if (exporterType == "CODEBLOCKS_WINDOWS") { const auto windowsTargets = std::map{ {"0x0400", "Windows NT 4.0"}, {"0x0500", "Windows 2000"}, {"0x0501", "Windows XP"}, {"0x0502", "Windows Server 2003"}, {"0x0600", "Windows Vista"}, {"0x0601", "Windows 7"}, {"0x0602", "Windows 8"}, {"0x0603", "Windows 8.1"}, {"0x0A00", "Windows 10"}, }; convertSettingIfDefined( exporter, "codeBlocksWindowsTarget", "TARGET_PLATFORM", [&windowsTargets](const juce::String& value) -> juce::String { auto search = windowsTargets.find(value); if (search != windowsTargets.end()) { return search->second; } return {}; }); } writeUserNotes(wLn, exporter); wLn(")"); wLn(); for (auto pConfiguration = configurations.getFirstChildElement(); pConfiguration != nullptr; pConfiguration = pConfiguration->getNextElement()) { if (pConfiguration->isTextElement()) { continue; } const auto& configuration = *pConfiguration; wLn("jucer_export_target_configuration("); wLn(" \"", exporterName, "\""); const auto originalName = configuration.getStringAttribute("name"); if (std::regex_match(originalName.toStdString(), std::regex{"^[A-Za-z0-9_]+$"})) { writeQuoted("NAME", originalName); } else { if (!configurationNamesMapping.containsKey(originalName)) { const auto validNameWithoutSuffix = makeValidConfigurationName(originalName); auto numberSuffix = 1; auto validName = validNameWithoutSuffix; while (configurationNamesMapping.getAllValues().contains(validName)) { validName = validNameWithoutSuffix + "_" + juce::String{numberSuffix++}; } configurationNamesMapping.set(originalName, validName); std::cerr << "warning: \"" << originalName << "\" is not a valid CMake build configuration name. It has been " "changed to \"" << validName << "\" in the generated CMakeLists.txt file." << std::endl; } wLn(" NAME \"", configurationNamesMapping[originalName], "\" # originally \"", originalName, "\" in ", jucerFileName); } const auto isDebug = toBoolLikeVar(configuration.getStringAttribute("isDebug")); writeUnquoted("DEBUG_MODE", (isDebug ? "ON" : "OFF")); convertSettingIfDefined(configuration, "targetName", "BINARY_NAME", {}); convertSettingIfDefined(configuration, "binaryPath", "BINARY_LOCATION", {}); convertSettingAsListIfDefined(configuration, "headerPath", "HEADER_SEARCH_PATHS", parseSearchPaths); convertSettingAsListIfDefined(configuration, "libraryPath", "EXTRA_LIBRARY_SEARCH_PATHS", parseSearchPaths); convertSettingAsListIfDefined(configuration, "defines", "PREPROCESSOR_DEFINITIONS", parsePreprocessorDefinitions); convertOnOffSettingIfDefined(configuration, "linkTimeOptimisation", "LINK_TIME_OPTIMISATION", {}); if (!configuration.hasAttribute("linkTimeOptimisation") && isVSExporter && !isDebug && jucerVersionAsTuple >= Version{5, 2, 0}) { convertOnOffSettingIfDefined(configuration, "wholeProgramOptimisation", "LINK_TIME_OPTIMISATION", [](const juce::String& value) { if (value.getIntValue() == 0) return "ON"; return "OFF"; }); } if (isXcodeExporter || isVSExporter) { convertOnOffSettingIfDefined(configuration, "usePrecompiledHeaderFile", "USE_PRECOMPILED_HEADER", {}); convertSettingIfDefined(configuration, "precompiledHeaderFile", "PRECOMPILED_HEADER_FILE", {}); } if (isXcodeExporter) { convertSettingIfDefined(configuration, "recommendedWarnings", "ADD_RECOMMENDED_COMPILER_WARNING_FLAGS", [](const juce::String& value) -> juce::String { if (value == "LLVM") return "Enabled"; if (value.isEmpty()) return "Disabled"; return {}; }); } else if (exporterType == "CODEBLOCKS_LINUX" || exporterType == "CODEBLOCKS_WINDOWS" || exporterType == "LINUX_MAKE") { convertSettingIfDefined(configuration, "recommendedWarnings", "ADD_RECOMMENDED_COMPILER_WARNING_FLAGS", [](const juce::String& value) -> juce::String { if (value == "GCC") return "GCC"; if (value == "GCC-7") return "GCC 7 and below"; if (value == "LLVM") return "LLVM"; if (value.isEmpty()) return "Disabled"; return {}; }); } convertSettingIfDefined( configuration, "optimisation", "OPTIMISATION", [&isVSExporter](const juce::String& value) -> juce::String { if (isVSExporter) { switch (value.getIntValue()) { case 1: return "No optimisation"; case 2: return "Minimise size"; case 3: return "Maximise speed"; } return {}; } switch (value.getIntValue()) { case 1: return "-O0 (no optimisation)"; case 2: return "-Os (minimise code size)"; case 3: return "-O3 (fastest with safe optimisations)"; case 4: return "-O1 (fast)"; case 5: return "-O2 (faster)"; case 6: return "-Ofast (uses aggressive optimisations)"; } return {}; }); if (isXcodeExporter) { convertOnOffSettingIfDefined(configuration, "enablePluginBinaryCopyStep", "ENABLE_PLUGIN_COPY_STEP", {}); if (!vstIsLegacy) { if (configuration.hasAttribute("xcodeVstBinaryLocation")) { convertSetting(configuration, "xcodeVstBinaryLocation", "VST_BINARY_LOCATION", {}); } else { convertSettingIfDefined(configuration, "vstBinaryLocation", "VST_BINARY_LOCATION", {}); } } const auto binaryLocationTuples = { std::make_tuple("xcodeVst3BinaryLocation", "vst3BinaryLocation", "VST3_BINARY_LOCATION"), std::make_tuple("xcodeAudioUnitBinaryLocation", "auBinaryLocation", "AU_BINARY_LOCATION"), std::make_tuple("xcodeRtasBinaryLocation", "rtasBinaryLocation", "RTAS_BINARY_LOCATION"), std::make_tuple("xcodeAaxBinaryLocation", "aaxBinaryLocation", "AAX_BINARY_LOCATION"), }; for (const auto& binaryLocationTuple : binaryLocationTuples) { const auto& oldProperty = std::get<0>(binaryLocationTuple); const auto& newProperty = std::get<1>(binaryLocationTuple); const auto& cmakeKeyword = std::get<2>(binaryLocationTuple); if (configuration.hasAttribute(oldProperty)) { convertSetting(configuration, oldProperty, cmakeKeyword, {}); } else { convertSettingIfDefined(configuration, newProperty, cmakeKeyword, {}); } } convertSettingIfDefined(configuration, "unityPluginBinaryLocation", "UNITY_BINARY_LOCATION", {}); if (vstIsLegacy) { convertSettingIfDefined(configuration, "vstBinaryLocation", "VST_LEGACY_BINARY_LOCATION", {}); } } if (exporterType == "XCODE_IPHONE") { convertSettingIfDefined(configuration, "iosBaseSDK", "IOS_BASE_SDK", {}); if (configuration.hasAttribute("iosDeploymentTarget")) { convertSetting(configuration, "iosDeploymentTarget", "IOS_DEPLOYMENT_TARGET", {}); } else { convertSettingIfDefined(configuration, "iosCompatibility", "IOS_DEPLOYMENT_TARGET", {}); } } if (exporterType == "XCODE_MAC") { const auto sdks = juce::StringArray{ "10.5 SDK", "10.6 SDK", "10.7 SDK", "10.8 SDK", "10.9 SDK", "10.10 SDK", "10.11 SDK", "10.12 SDK", "10.13 SDK", "10.14 SDK", "10.15 SDK", "10.16 SDK", "11.0 SDK", "11.1 SDK", }; if (configuration.hasAttribute("macOSBaseSDK")) { convertSetting(configuration, "macOSBaseSDK", "MACOS_BASE_SDK", {}); } else { convertSettingIfDefined( configuration, "osxSDK", jucerVersionAsTuple < Version{6, 0, 2} ? "OSX_BASE_SDK_VERSION" : "MACOS_BASE_SDK_VERSION", [&jucerVersionAsTuple, &sdks](const juce::String& value) -> juce::String { if (value == "default") return jucerVersionAsTuple < Version{5, 2, 1} ? "Use Default" : "Default"; if (sdks.contains(value)) return value; return {}; }); } if (configuration.hasAttribute("macOSDeploymentTarget")) { convertSetting(configuration, "macOSDeploymentTarget", "MACOS_DEPLOYMENT_TARGET", {}); } else { convertSettingIfDefined( configuration, "osxCompatibility", jucerVersionAsTuple < Version{6, 0, 2} ? "OSX_DEPLOYMENT_TARGET" : "MACOS_DEPLOYMENT_TARGET", [&jucerVersionAsTuple, &sdks](const juce::String& value) -> juce::String { if (value == "default") return jucerVersionAsTuple < Version{5, 2, 1} ? "Use Default" : "Default"; if (sdks.contains(value)) return value.substring(0, value.length() - 4); return {}; }); } if (jucerVersionAsTuple < Version{6, 0, 2}) { convertSettingIfDefined( configuration, "osxArchitecture", "OSX_ARCHITECTURE", [&jucerVersionAsTuple](const juce::String& value) -> juce::String { if (value == "default") return jucerVersionAsTuple < Version{5, 2, 1} ? "Use Default" : "Default"; if (value == "Native") return "Native architecture of build machine"; if (value == "32BitUniversal") return "Universal Binary (32-bit)"; if (value == "64BitUniversal") return "Universal Binary (32/64-bit)"; if (value == "64BitIntel") return "64-bit Intel"; return {}; }); } else { convertSettingIfDefined(configuration, "osxArchitecture", "MACOS_ARCHITECTURE", [](const juce::String& value) -> juce::String { if (value == "Native") return "Native architecture of build machine"; if (value == "32BitUniversal") return "Standard 32-bit"; if (value == "64BitUniversal") return "Standard 32/64-bit"; if (value == "64BitIntel") return "Standard 64-bit"; return {}; }); } } if (isXcodeExporter) { convertSettingAsListIfDefined( configuration, "customXcodeFlags", "CUSTOM_XCODE_FLAGS", [](const juce::String& value) { auto customFlags = juce::StringArray::fromTokens(value, ",", "\"'"); customFlags.removeEmptyStrings(); for (auto& flag : customFlags) { flag = flag.upToFirstOccurrenceOf("=", false, false).trim() + " = " + flag.fromFirstOccurrenceOf("=", false, false).trim(); } return customFlags; }); convertSettingAsListIfDefined(configuration, "plistPreprocessorDefinitions", "PLIST_PREPROCESSOR_DEFINITIONS", parsePreprocessorDefinitions); convertSettingIfDefined(configuration, "cppLanguageStandard", "CXX_LANGUAGE_STANDARD", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "Use Default"; if (value == "c++98") return "C++98"; if (value == "gnu++98") return "GNU++98"; if (value == "c++11") return "C++11"; if (value == "gnu++11") return "GNU++11"; if (value == "c++14") return "C++14"; if (value == "gnu++14") return "GNU++14"; return {}; }); convertSettingIfDefined( configuration, "cppLibType", "CXX_LIBRARY", [&jucerVersionAsTuple](const juce::String& value) -> juce::String { if (value.isEmpty()) return jucerVersionAsTuple < Version{5, 2, 1} ? "Use Default" : "Default"; if (value == "libc++") return "LLVM libc++"; if (value == "libstdc++") return "GNU libstdc++"; return {}; }); convertSettingIfDefined(configuration, "codeSigningIdentity", "CODE_SIGNING_IDENTITY", {}); convertOnOffSettingIfDefined(configuration, "fastMath", "RELAX_IEEE_COMPLIANCE", {}); convertOnOffSettingIfDefined(configuration, "stripLocalSymbols", "STRIP_LOCAL_SYMBOLS", {}); } if (isVSExporter) { convertOnOffSettingIfDefined(configuration, "enablePluginBinaryCopyStep", "ENABLE_PLUGIN_COPY_STEP", {}); if (!vstIsLegacy) { convertSettingIfDefined(configuration, "vstBinaryLocation", "VST_BINARY_LOCATION", {}); } convertSettingIfDefined(configuration, "vst3BinaryLocation", "VST3_BINARY_LOCATION", {}); convertSettingIfDefined(configuration, "rtasBinaryLocation", "RTAS_BINARY_LOCATION", {}); convertSettingIfDefined(configuration, "aaxBinaryLocation", "AAX_BINARY_LOCATION", {}); convertSettingIfDefined(configuration, "unityPluginBinaryLocation", "UNITY_BINARY_LOCATION", {}); if (vstIsLegacy) { convertSettingIfDefined(configuration, "vstBinaryLocation", "VST_LEGACY_BINARY_LOCATION", {}); } convertSettingIfDefined(configuration, "winWarningLevel", "WARNING_LEVEL", [](const juce::String& value) -> juce::String { switch (value.getIntValue()) { case 2: return "Low"; case 3: return "Medium"; case 4: return "High"; } return "High"; }); convertOnOffSettingIfDefined(configuration, "warningsAreErrors", "TREAT_WARNINGS_AS_ERRORS", {}); convertSettingIfDefined( configuration, "useRuntimeLibDLL", "RUNTIME_LIBRARY", [&jucerVersionAsTuple](const juce::String& value) -> juce::String { if (value.isEmpty()) return jucerVersionAsTuple < Version{5, 2, 1} ? "(Default)" : "Default"; if (value == "0") return "Use static runtime"; if (value == "1") return "Use DLL runtime"; return {}; }); if (jucerVersionAsTuple < Version{5, 2, 0}) { convertSettingIfDefined(configuration, "wholeProgramOptimisation", "WHOLE_PROGRAM_OPTIMISATION", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "Enable when possible"; if (value.getIntValue() > 0) return "Always disable"; return {}; }); } convertOnOffSettingIfDefined(configuration, "multiProcessorCompilation", "MULTI_PROCESSOR_COMPILATION", {}); convertOnOffSettingIfDefined(configuration, "enableIncrementalLinking", "INCREMENTAL_LINKING", {}); if (!isDebug) { convertOnOffSettingIfDefined(configuration, "alwaysGenerateDebugSymbols", "FORCE_GENERATION_OF_DEBUG_SYMBOLS", {}); } convertSettingIfDefined(configuration, "prebuildCommand", "PREBUILD_COMMAND", {}); convertSettingIfDefined(configuration, "postbuildCommand", "POSTBUILD_COMMAND", {}); convertOnOffSettingIfDefined(configuration, "generateManifest", "GENERATE_MANIFEST", {}); convertSettingIfDefined(configuration, "characterSet", "CHARACTER_SET", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return "Default"; return value; }); if (configuration.hasAttribute("winArchitecture")) { const auto& winArchitecture = configuration.getStringAttribute("winArchitecture"); if (winArchitecture.isEmpty()) { wLn(" # ARCHITECTURE"); } else { wLn(" # ARCHITECTURE \"", winArchitecture, "\""); } } convertSettingIfDefined( configuration, "debugInformationFormat", "DEBUG_INFORMATION_FORMAT", [](const juce::String& value) -> juce::String { if (value == "None") return "None"; if (value == "OldStyle") return "C7 Compatible (/Z7)"; if (value == "ProgramDatabase") return "Program Database (/Zi)"; if (value == "EditAndContinue") return "Program Database for Edit And Continue (/ZI)"; return {}; }); convertOnOffSettingIfDefined(configuration, "fastMath", "RELAX_IEEE_COMPLIANCE", {}); } if (exporterType == "LINUX_MAKE") { convertSettingIfDefined(configuration, "linuxArchitecture", "ARCHITECTURE", [](const juce::String& value) -> juce::String { if (value.isEmpty()) return ""; if (value == "-march=native") return "Native"; if (value == "-m32") return "32-bit (-m32)"; if (value == "-m64") return "64-bit (-m64)"; if (value == "-march=armv6") return "ARM v6"; if (value == "-march=armv7") return "ARM v7"; return {}; }); convertOnOffSettingIfDefined(configuration, "enablePluginBinaryCopyStep", "ENABLE_PLUGIN_COPY_STEP", {}); convertSettingIfDefined(configuration, "vst3BinaryLocation", "VST3_BINARY_LOCATION", {}); convertSettingIfDefined(configuration, "unityPluginBinaryLocation", "UNITY_BINARY_LOCATION", {}); convertSettingIfDefined(configuration, "vstBinaryLocation", "VST_LEGACY_BINARY_LOCATION", {}); } const auto codeBlocksArchitecture = [](const juce::String& value) -> juce::String { if (value == "-m32") return "32-bit (-m32)"; if (value == "-m64" || value.isEmpty()) return "64-bit (-m64)"; if (value == "-march=armv6") return "ARM v6"; if (value == "-march=armv7") return "ARM v7"; return {}; }; if (exporterType == "CODEBLOCKS_WINDOWS") { if (configuration.hasAttribute("windowsCodeBlocksArchitecture") || (jucerVersionAsTuple >= Version{5, 0, 0} && jucerVersionAsTuple < Version{5, 2, 1})) { convertSetting(configuration, "windowsCodeBlocksArchitecture", "ARCHITECTURE", codeBlocksArchitecture); } } if (exporterType == "CODEBLOCKS_LINUX") { if (configuration.hasAttribute("linuxCodeBlocksArchitecture") || (jucerVersionAsTuple >= Version{5, 0, 0} && jucerVersionAsTuple < Version{5, 2, 1})) { convertSetting(configuration, "linuxCodeBlocksArchitecture", "ARCHITECTURE", codeBlocksArchitecture); } } writeUserNotes(wLn, configuration); wLn(")"); wLn(); } } } wLn("jucer_project_end()"); } } // namespace Jucer2CMake ================================================ FILE: Jucer2CMake/src/utils.hpp ================================================ // Copyright (C) 2021-2022 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #include "juce_core.hpp" #include #include namespace Jucer2CMake { struct Arguments { juce::String mode; juce::String jucerFilePath; juce::String reprojucerFilePath; juce::String jucerVersion; juce::String juceModulesPath; juce::String userModulesPath; juce::File outputDir; bool relocatable; }; struct ExitException { public: ExitException(const int returnValue) : mReturnValue{returnValue} { } int returnValue() const { return mReturnValue; } private: const int mReturnValue; }; #if !defined(WRITE_CRLF_LINE_ENDINGS) #error WRITE_CRLF_LINE_ENDINGS must be defined #endif #if WRITE_CRLF_LINE_ENDINGS static const auto kNewLine = "\r\n"; #else static const auto kNewLine = '\n'; #endif struct LineWriter { explicit LineWriter(juce::MemoryOutputStream& stream) : mStream(stream) { } LineWriter(const LineWriter&) = delete; LineWriter& operator=(const LineWriter&) = delete; template void operator()(Args&&... args) { if (needsEmptyLine) { writeToStream(mStream, kNewLine); needsEmptyLine = false; } writeToStream(mStream, std::forward(args)..., kNewLine); } bool needsEmptyLine = false; private: template void writeToStream(juce::MemoryOutputStream& stream, Head&& head) { stream << std::forward(head); } template void writeToStream(juce::MemoryOutputStream& stream, Head&& head, Tail&&... tail) { stream << std::forward(head); writeToStream(stream, std::forward(tail)...); } juce::MemoryOutputStream& mStream; }; inline juce::StringArray convertIdsToStrings( const juce::StringArray& ids, const std::vector>& idsToStrings) { juce::StringArray strings; for (const auto& idToString : idsToStrings) { if (ids.contains(idToString.first)) { strings.add(idToString.second); } } return strings; } inline juce::String getAUMainTypeConstantFromQuotedFourChars( const juce::String& quotedFourChars) { // clang-format off if (quotedFourChars == "'aufx'") return "kAudioUnitType_Effect"; if (quotedFourChars == "'aufc'") return "kAudioUnitType_FormatConverter"; if (quotedFourChars == "'augn'") return "kAudioUnitType_Generator"; if (quotedFourChars == "'aumi'") return "kAudioUnitType_MIDIProcessor"; if (quotedFourChars == "'aumx'") return "kAudioUnitType_Mixer"; if (quotedFourChars == "'aumu'") return "kAudioUnitType_MusicDevice"; if (quotedFourChars == "'aumf'") return "kAudioUnitType_MusicEffect"; if (quotedFourChars == "'auol'") return "kAudioUnitType_OfflineEffect"; if (quotedFourChars == "'auou'") return "kAudioUnitType_Output"; if (quotedFourChars == "'aupn'") return "kAudioUnitType_Panner"; // clang-format on return quotedFourChars; } inline juce::File getChildFileFromWorkingDirectory( const juce::StringRef relativeOrAbsolutePath) { return juce::File::getCurrentWorkingDirectory().getChildFile(relativeOrAbsolutePath); } inline void printError(const juce::String& error) { std::cerr << "error: " << error << std::endl; } // Matches juce::var::VariantType_String::toBool. This means that `toBoolLikeVar(s)` and // `bool{juce::var{s}}` are equivalent. inline bool toBoolLikeVar(const juce::String& s) { return s.getIntValue() != 0 || s.trim().equalsIgnoreCase("true") || s.trim().equalsIgnoreCase("yes"); } } // namespace Jucer2CMake ================================================ FILE: Jucer2CMake/tests/.gitignore ================================================ /*/Builds/ /*/JuceLibraryCode/ ================================================ FILE: Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake ================================================ # Copyright (C) 2021 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . if(NOT DEFINED Jucer2CMake_EXE) message(FATAL_ERROR "Jucer2CMake_EXE must be defined") endif() if(NOT EXISTS ${Jucer2CMake_EXE}) message(FATAL_ERROR "No such file: ${Jucer2CMake_EXE}") endif() get_filename_component(Jucer2CMake_EXE "${Jucer2CMake_EXE}" ABSOLUTE) file(GLOB_RECURSE jucer_files "${CMAKE_CURRENT_LIST_DIR}/*.jucer") foreach(jucer_file IN LISTS jucer_files) set(command "${Jucer2CMake_EXE}" "juce6" "${jucer_file}") execute_process(COMMAND ${command} RESULT_VARIABLE result) if(NOT result EQUAL 0) string(REPLACE ";" " " command_string "${command}") message(FATAL_ERROR "Failed to run `${command_string}`") endif() endforeach() ================================================ FILE: Jucer2CMake/tests/audioplug6/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "audioplug6.jucer" cmake_minimum_required(VERSION 3.15) project("audioplug6") find_package(JUCE CONFIG REQUIRED) juce_add_plugin(audioplug6 VERSION "1.0.0" FORMATS "VST3" "Standalone" PLUGIN_NAME "PluginName" DESCRIPTION "The description" PLUGIN_MANUFACTURER_CODE "Manu" PLUGIN_CODE "Code" IS_SYNTH TRUE NEEDS_MIDI_INPUT TRUE NEEDS_MIDI_OUTPUT TRUE IS_MIDI_EFFECT TRUE EDITOR_WANTS_KEYBOARD_FOCUS TRUE DISABLE_AAX_BYPASS TRUE DISABLE_AAX_MULTI_MONO TRUE AAX_IDENTIFIER "org.myorg.myAAXplugin" AU_EXPORT_PREFIX "prefixAU" AU_MAIN_TYPE "kAudioUnitType_MIDIProcessor" AU_SANDBOX_SAFE FALSE VST_NUM_MIDI_INS "9" VST_NUM_MIDI_OUTS "8" VST3_CATEGORIES "Drum" "Mastering" VST2_CATEGORY "kPlugCategUnknown" ) juce_generate_juce_header(audioplug6) target_compile_definitions(audioplug6 PUBLIC JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=0 JUCE_VST3_CAN_REPLACE_VST2=0 JUCE_WEB_BROWSER=0 ) target_sources(audioplug6 PRIVATE "Source/PluginEditor.cpp" "Source/PluginProcessor.cpp" ) target_link_libraries(audioplug6 PRIVATE juce::juce_audio_basics juce::juce_audio_devices juce::juce_audio_formats juce::juce_audio_plugin_client juce::juce_audio_processors juce::juce_audio_utils juce::juce_core juce::juce_data_structures juce::juce_events juce::juce_graphics juce::juce_gui_basics juce::juce_gui_extra PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/audioplug6/Source/PluginEditor.cpp ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin editor. ============================================================================== */ #include "PluginProcessor.h" #include "PluginEditor.h" //============================================================================== Audioplug6AudioProcessorEditor::Audioplug6AudioProcessorEditor (Audioplug6AudioProcessor& p) : AudioProcessorEditor (&p), audioProcessor (p) { // 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); } Audioplug6AudioProcessorEditor::~Audioplug6AudioProcessorEditor() { } //============================================================================== void Audioplug6AudioProcessorEditor::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 Audioplug6AudioProcessorEditor::resized() { // This is generally where you'll want to lay out the positions of any // subcomponents in your editor.. } ================================================ FILE: Jucer2CMake/tests/audioplug6/Source/PluginEditor.h ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin editor. ============================================================================== */ #pragma once #include #include "PluginProcessor.h" //============================================================================== /** */ class Audioplug6AudioProcessorEditor : public juce::AudioProcessorEditor { public: Audioplug6AudioProcessorEditor (Audioplug6AudioProcessor&); ~Audioplug6AudioProcessorEditor() 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. Audioplug6AudioProcessor& audioProcessor; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Audioplug6AudioProcessorEditor) }; ================================================ FILE: Jucer2CMake/tests/audioplug6/Source/PluginProcessor.cpp ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin processor. ============================================================================== */ #include "PluginProcessor.h" #include "PluginEditor.h" //============================================================================== Audioplug6AudioProcessor::Audioplug6AudioProcessor() #ifndef JucePlugin_PreferredChannelConfigurations : AudioProcessor (BusesProperties() #if ! JucePlugin_IsMidiEffect #if ! JucePlugin_IsSynth .withInput ("Input", juce::AudioChannelSet::stereo(), true) #endif .withOutput ("Output", juce::AudioChannelSet::stereo(), true) #endif ) #endif { } Audioplug6AudioProcessor::~Audioplug6AudioProcessor() { } //============================================================================== const juce::String Audioplug6AudioProcessor::getName() const { return JucePlugin_Name; } bool Audioplug6AudioProcessor::acceptsMidi() const { #if JucePlugin_WantsMidiInput return true; #else return false; #endif } bool Audioplug6AudioProcessor::producesMidi() const { #if JucePlugin_ProducesMidiOutput return true; #else return false; #endif } bool Audioplug6AudioProcessor::isMidiEffect() const { #if JucePlugin_IsMidiEffect return true; #else return false; #endif } double Audioplug6AudioProcessor::getTailLengthSeconds() const { return 0.0; } int Audioplug6AudioProcessor::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 Audioplug6AudioProcessor::getCurrentProgram() { return 0; } void Audioplug6AudioProcessor::setCurrentProgram (int index) { } const juce::String Audioplug6AudioProcessor::getProgramName (int index) { return {}; } void Audioplug6AudioProcessor::changeProgramName (int index, const juce::String& newName) { } //============================================================================== void Audioplug6AudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) { // Use this method as the place to do any pre-playback // initialisation that you need.. } void Audioplug6AudioProcessor::releaseResources() { // When playback stops, you can use this as an opportunity to free up any // spare memory, etc. } #ifndef JucePlugin_PreferredChannelConfigurations bool Audioplug6AudioProcessor::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 } #endif void Audioplug6AudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& 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); // ..do something to the data... } } //============================================================================== bool Audioplug6AudioProcessor::hasEditor() const { return true; // (change this to false if you choose to not supply an editor) } juce::AudioProcessorEditor* Audioplug6AudioProcessor::createEditor() { return new Audioplug6AudioProcessorEditor (*this); } //============================================================================== void Audioplug6AudioProcessor::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. } void Audioplug6AudioProcessor::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. } //============================================================================== // This creates new instances of the plugin.. juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new Audioplug6AudioProcessor(); } ================================================ FILE: Jucer2CMake/tests/audioplug6/Source/PluginProcessor.h ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin processor. ============================================================================== */ #pragma once #include //============================================================================== /** */ class Audioplug6AudioProcessor : public juce::AudioProcessor { public: //============================================================================== Audioplug6AudioProcessor(); ~Audioplug6AudioProcessor() override; //============================================================================== void prepareToPlay (double sampleRate, int samplesPerBlock) override; void releaseResources() override; #ifndef JucePlugin_PreferredChannelConfigurations bool isBusesLayoutSupported (const BusesLayout& layouts) const override; #endif 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 (Audioplug6AudioProcessor) }; ================================================ FILE: Jucer2CMake/tests/audioplug6/audioplug6.jucer ================================================ ================================================ FILE: Jucer2CMake/tests/audioplug6-default/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "audioplug6.jucer" cmake_minimum_required(VERSION 3.15) project("audioplug6") find_package(JUCE CONFIG REQUIRED) juce_add_plugin(audioplug6 VERSION "1.0.0" FORMATS "VST3" "AU" "Standalone" ) juce_generate_juce_header(audioplug6) target_compile_definitions(audioplug6 PUBLIC JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=0 JUCE_VST3_CAN_REPLACE_VST2=0 JUCE_WEB_BROWSER=0 ) target_sources(audioplug6 PRIVATE "Source/PluginEditor.cpp" "Source/PluginProcessor.cpp" ) target_link_libraries(audioplug6 PRIVATE juce::juce_audio_basics juce::juce_audio_devices juce::juce_audio_formats juce::juce_audio_plugin_client juce::juce_audio_processors juce::juce_audio_utils juce::juce_core juce::juce_data_structures juce::juce_events juce::juce_graphics juce::juce_gui_basics juce::juce_gui_extra PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/audioplug6-default/Source/PluginEditor.cpp ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin editor. ============================================================================== */ #include "PluginProcessor.h" #include "PluginEditor.h" //============================================================================== Audioplug6AudioProcessorEditor::Audioplug6AudioProcessorEditor (Audioplug6AudioProcessor& p) : AudioProcessorEditor (&p), audioProcessor (p) { // 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); } Audioplug6AudioProcessorEditor::~Audioplug6AudioProcessorEditor() { } //============================================================================== void Audioplug6AudioProcessorEditor::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 Audioplug6AudioProcessorEditor::resized() { // This is generally where you'll want to lay out the positions of any // subcomponents in your editor.. } ================================================ FILE: Jucer2CMake/tests/audioplug6-default/Source/PluginEditor.h ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin editor. ============================================================================== */ #pragma once #include #include "PluginProcessor.h" //============================================================================== /** */ class Audioplug6AudioProcessorEditor : public juce::AudioProcessorEditor { public: Audioplug6AudioProcessorEditor (Audioplug6AudioProcessor&); ~Audioplug6AudioProcessorEditor() 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. Audioplug6AudioProcessor& audioProcessor; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Audioplug6AudioProcessorEditor) }; ================================================ FILE: Jucer2CMake/tests/audioplug6-default/Source/PluginProcessor.cpp ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin processor. ============================================================================== */ #include "PluginProcessor.h" #include "PluginEditor.h" //============================================================================== Audioplug6AudioProcessor::Audioplug6AudioProcessor() #ifndef JucePlugin_PreferredChannelConfigurations : AudioProcessor (BusesProperties() #if ! JucePlugin_IsMidiEffect #if ! JucePlugin_IsSynth .withInput ("Input", juce::AudioChannelSet::stereo(), true) #endif .withOutput ("Output", juce::AudioChannelSet::stereo(), true) #endif ) #endif { } Audioplug6AudioProcessor::~Audioplug6AudioProcessor() { } //============================================================================== const juce::String Audioplug6AudioProcessor::getName() const { return JucePlugin_Name; } bool Audioplug6AudioProcessor::acceptsMidi() const { #if JucePlugin_WantsMidiInput return true; #else return false; #endif } bool Audioplug6AudioProcessor::producesMidi() const { #if JucePlugin_ProducesMidiOutput return true; #else return false; #endif } bool Audioplug6AudioProcessor::isMidiEffect() const { #if JucePlugin_IsMidiEffect return true; #else return false; #endif } double Audioplug6AudioProcessor::getTailLengthSeconds() const { return 0.0; } int Audioplug6AudioProcessor::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 Audioplug6AudioProcessor::getCurrentProgram() { return 0; } void Audioplug6AudioProcessor::setCurrentProgram (int index) { } const juce::String Audioplug6AudioProcessor::getProgramName (int index) { return {}; } void Audioplug6AudioProcessor::changeProgramName (int index, const juce::String& newName) { } //============================================================================== void Audioplug6AudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) { // Use this method as the place to do any pre-playback // initialisation that you need.. } void Audioplug6AudioProcessor::releaseResources() { // When playback stops, you can use this as an opportunity to free up any // spare memory, etc. } #ifndef JucePlugin_PreferredChannelConfigurations bool Audioplug6AudioProcessor::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 } #endif void Audioplug6AudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& 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); // ..do something to the data... } } //============================================================================== bool Audioplug6AudioProcessor::hasEditor() const { return true; // (change this to false if you choose to not supply an editor) } juce::AudioProcessorEditor* Audioplug6AudioProcessor::createEditor() { return new Audioplug6AudioProcessorEditor (*this); } //============================================================================== void Audioplug6AudioProcessor::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. } void Audioplug6AudioProcessor::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. } //============================================================================== // This creates new instances of the plugin.. juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new Audioplug6AudioProcessor(); } ================================================ FILE: Jucer2CMake/tests/audioplug6-default/Source/PluginProcessor.h ================================================ /* ============================================================================== This file contains the basic framework code for a JUCE plugin processor. ============================================================================== */ #pragma once #include //============================================================================== /** */ class Audioplug6AudioProcessor : public juce::AudioProcessor { public: //============================================================================== Audioplug6AudioProcessor(); ~Audioplug6AudioProcessor() override; //============================================================================== void prepareToPlay (double sampleRate, int samplesPerBlock) override; void releaseResources() override; #ifndef JucePlugin_PreferredChannelConfigurations bool isBusesLayoutSupported (const BusesLayout& layouts) const override; #endif 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 (Audioplug6AudioProcessor) }; ================================================ FILE: Jucer2CMake/tests/audioplug6-default/audioplug6.jucer ================================================ ================================================ FILE: Jucer2CMake/tests/consoleapp6/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "consoleapp6.jucer" cmake_minimum_required(VERSION 3.12) project("consoleapp6") find_package(JUCE CONFIG REQUIRED) juce_add_console_app(consoleapp6 VERSION "0.1" COMPANY_NAME "The Name of the Company" COMPANY_COPYRIGHT "The Copyright of the Company" COMPANY_WEBSITE "The Website of the Company" COMPANY_EMAIL "The E-mail of the Company" NEEDS_CURL TRUE ) juce_generate_juce_header(consoleapp6) target_compile_definitions(consoleapp6 PRIVATE JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=1 ) target_sources(consoleapp6 PRIVATE "Source/Main.cpp" ) target_link_libraries(consoleapp6 PRIVATE juce::juce_core juce::juce_data_structures juce::juce_events PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/consoleapp6/Source/Main.cpp ================================================ /* ============================================================================== This file contains the basic startup code for a JUCE application. ============================================================================== */ #include //============================================================================== int main (int argc, char* argv[]) { // ..your code goes here! return 0; } ================================================ FILE: Jucer2CMake/tests/consoleapp6/consoleapp6.jucer ================================================ ================================================ FILE: Jucer2CMake/tests/consoleapp6-default/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "consoleapp6.jucer" cmake_minimum_required(VERSION 3.12) project("consoleapp6") find_package(JUCE CONFIG REQUIRED) juce_add_console_app(consoleapp6 VERSION "1.0.0" ) juce_generate_juce_header(consoleapp6) target_compile_definitions(consoleapp6 PRIVATE JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=0 ) target_sources(consoleapp6 PRIVATE "Source/Main.cpp" ) target_link_libraries(consoleapp6 PRIVATE juce::juce_core juce::juce_data_structures juce::juce_events PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/consoleapp6-default/Source/Main.cpp ================================================ /* ============================================================================== This file contains the basic startup code for a JUCE application. ============================================================================== */ #include //============================================================================== int main (int argc, char* argv[]) { // ..your code goes here! return 0; } ================================================ FILE: Jucer2CMake/tests/consoleapp6-default/consoleapp6.jucer ================================================ ================================================ FILE: Jucer2CMake/tests/guiapp6/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "guiapp6.jucer" cmake_minimum_required(VERSION 3.12) project("guiapp6") find_package(JUCE CONFIG REQUIRED) juce_add_gui_app(guiapp6 VERSION "1.0.0" BUNDLE_ID "org.myorg.myapp" NEEDS_WEB_BROWSER TRUE PLUGINHOST_AU TRUE ) juce_generate_juce_header(guiapp6) target_compile_definitions(guiapp6 PRIVATE JUCE_PLUGINHOST_AU=1 JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=0 JUCE_WEB_BROWSER=1 ) target_sources(guiapp6 PRIVATE "Source/Main.cpp" "Source/MainComponent.cpp" ) juce_add_binary_data(guiapp6_BinaryData NAMESPACE "BinaryNamespace" SOURCES "Source/icons/16x16.png" "Source/icons/32x32.png" ) target_link_libraries(guiapp6 PRIVATE guiapp6_BinaryData juce::juce_audio_basics juce::juce_audio_processors juce::juce_core juce::juce_data_structures juce::juce_events juce::juce_graphics juce::juce_gui_basics juce::juce_gui_extra PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/guiapp6/Source/Main.cpp ================================================ /* ============================================================================== This file contains the basic startup code for a JUCE application. ============================================================================== */ #include #include "MainComponent.h" //============================================================================== class guiapp6Application : public juce::JUCEApplication { public: //============================================================================== guiapp6Application() {} const juce::String getApplicationName() override { return ProjectInfo::projectName; } const juce::String getApplicationVersion() override { return ProjectInfo::versionString; } bool moreThanOneInstanceAllowed() override { return true; } //============================================================================== void initialise (const juce::String& commandLine) override { // This method is where you should put your application's initialisation code.. 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. } //============================================================================== /* This class implements the desktop window that contains an instance of our MainComponent class. */ class MainWindow : public juce::DocumentWindow { public: MainWindow (juce::String name) : DocumentWindow (name, juce::Desktop::getInstance().getDefaultLookAndFeel() .findColour (juce::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 (guiapp6Application) ================================================ FILE: Jucer2CMake/tests/guiapp6/Source/MainComponent.cpp ================================================ #include "MainComponent.h" //============================================================================== MainComponent::MainComponent() { setSize (600, 400); } MainComponent::~MainComponent() { } //============================================================================== 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. } ================================================ FILE: Jucer2CMake/tests/guiapp6/Source/MainComponent.h ================================================ #pragma once #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(); ~MainComponent() override; //============================================================================== void paint (juce::Graphics&) override; void resized() override; private: //============================================================================== // Your private member variables go here... JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent) }; ================================================ FILE: Jucer2CMake/tests/guiapp6/guiapp6.jucer ================================================ ================================================ FILE: Jucer2CMake/tests/guiapp6-default/CMakeLists.txt ================================================ # This file was generated by FRUT's Jucer2CMake from "guiapp6.jucer" cmake_minimum_required(VERSION 3.12) project("guiapp6") find_package(JUCE CONFIG REQUIRED) juce_add_gui_app(guiapp6 VERSION "1.0.0" ) juce_generate_juce_header(guiapp6) target_compile_definitions(guiapp6 PRIVATE JUCE_STRICT_REFCOUNTEDPOINTER=1 JUCE_USE_CURL=0 ) target_sources(guiapp6 PRIVATE "Source/Main.cpp" "Source/MainComponent.cpp" ) target_link_libraries(guiapp6 PRIVATE juce::juce_core juce::juce_data_structures juce::juce_events juce::juce_graphics juce::juce_gui_basics PUBLIC juce::juce_recommended_config_flags juce::juce_recommended_lto_flags juce::juce_recommended_warning_flags ) ================================================ FILE: Jucer2CMake/tests/guiapp6-default/Source/Main.cpp ================================================ /* ============================================================================== This file contains the basic startup code for a JUCE application. ============================================================================== */ #include #include "MainComponent.h" //============================================================================== class guiapp6Application : public juce::JUCEApplication { public: //============================================================================== guiapp6Application() {} const juce::String getApplicationName() override { return ProjectInfo::projectName; } const juce::String getApplicationVersion() override { return ProjectInfo::versionString; } bool moreThanOneInstanceAllowed() override { return true; } //============================================================================== void initialise (const juce::String& commandLine) override { // This method is where you should put your application's initialisation code.. 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. } //============================================================================== /* This class implements the desktop window that contains an instance of our MainComponent class. */ class MainWindow : public juce::DocumentWindow { public: MainWindow (juce::String name) : DocumentWindow (name, juce::Desktop::getInstance().getDefaultLookAndFeel() .findColour (juce::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 (guiapp6Application) ================================================ FILE: Jucer2CMake/tests/guiapp6-default/Source/MainComponent.cpp ================================================ #include "MainComponent.h" //============================================================================== MainComponent::MainComponent() { setSize (600, 400); } MainComponent::~MainComponent() { } //============================================================================== 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. } ================================================ FILE: Jucer2CMake/tests/guiapp6-default/Source/MainComponent.h ================================================ #pragma once #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(); ~MainComponent() override; //============================================================================== void paint (juce::Graphics&) override; void resized() override; private: //============================================================================== // Your private member variables go here... JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent) }; ================================================ FILE: Jucer2CMake/tests/guiapp6-default/guiapp6.jucer ================================================ ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.rst ================================================ |Code_of_Conduct| |AppVeyor| |Azure_Pipelines| |Read_the_Docs| .. image:: FRUT.svg :target: https://github.com/McMartin/FRUT :alt: FRUT FRUT makes it easy to build `JUCE`_ projects using `CMake`_ instead of `Projucer`_. It enables more flexibility in project architecture, simplified CI setup, and easier integration with other JUCE and non-JUCE projects. Converting an existing JUCE project to FRUT is easy, and you don't need to be a CMake expert to use it! **In short** - *Requirements* - CMake (3.4 minimum, or `higher depending on the target platform <#supported-projucer-exporters>`__) - JUCE (4.2.0 minimum) - *Supported platforms* - iOS - Linux - macOS - Windows (MSVC and MinGW) - *Documentation* - https://frut.readthedocs.io - *Contributing* - Contributions are welcome! See `CONTRIBUTING.md`_ for more details. - `All contributors are recognized <#contributors>`__ **Table of Contents** .. contents:: :local: :backlinks: none Background ---------- `JUCE`_ comes with its own project generation tool, `Projucer`_, which is very useful when starting a JUCE project. However, Projucer doesn't scale well when you want to make some aspects of your project configurable, when you want to add external libraries, when you want to use Continuous Integration, or when you want to manage several projects at once. FRUT was created to overcome these limitations, while making it very easy to migrate an existing JUCE project that uses Projucer. Since FRUT is based on `CMake`_, you also get access to many great features of CMake, including `testing `__ and `packaging `__ utilities. Contents -------- FRUT currently contains: - ``Jucer2CMake``, a console application that converts ``.jucer`` project files into ready-to-use ``CMakeLists.txt`` files, - ``Reprojucer.cmake``, a CMake module that provides high-level functions to reproduce how a JUCE project is defined in Projucer, - several ``CMakeLists.txt`` files generated from existing ``.jucer`` project files, including: - ``examples`` and ``extras`` projects from `JUCE 4.2.0`_ (in `generated/JUCE-4.2.0`_) - ``examples`` and ``extras`` projects from `JUCE 4.3.1`_ (in `generated/JUCE-4.3.1`_) - ``examples`` and ``extras`` projects from `JUCE 5.0.0`_ (in `generated/JUCE-5.0.0`_) - ``examples`` and ``extras`` projects from `JUCE 5.2.1`_ (in `generated/JUCE-5.2.1`_) - ``examples`` and ``extras`` projects from `JUCE 5.3.1`_ (in `generated/JUCE-5.3.1`_) - ``examples`` and ``extras`` projects from `JUCE 5.4.3`_ (in `generated/JUCE-5.4.3`_) - ``examples`` and ``extras`` projects from `JUCE 5.4.7`_ (in `generated/JUCE-5.4.7`_) - ``examples`` and ``extras`` projects from `JUCE 6.0.5`_ (in `generated/JUCE-6.0.5`_) - ``examples`` and ``extras`` projects from `JUCE 6.1.6`_ (in `generated/JUCE-6.1.6`_) - ``examples`` and ``extras`` projects from `JUCE 7.0.7`_ (in `generated/JUCE-7.0.7`_) Requirements ------------ - CMake, version 3.4 minimum - JUCE, version 4.2.0 minimum Supported Projucer exporters ---------------------------- ``Jucer2CMake`` and ``Reprojucer.cmake`` support the following Projucer exporters (also known as "export targets"): .. raw:: html SupportedExporterCMake requirements and optionsMissing features ✔️Xcode (macOS) 4 unsupported Xcode exporter settings ✔️Xcode (iOS)version 3.14 minimum-G Xcode -DCMAKE_SYSTEM_NAME=iOS ✔️Visual Studio 2022version 3.21 minimum 3 unsupported Visual Studio exporter settings ✔️Visual Studio 2019version 3.14 minimum ✔️Visual Studio 2017version 3.7 minimum(3.13.3 when VS 2019 is installed) ✔️Visual Studio 2015 ✔️Visual Studio 2013 ✔️Linux Makefile ❌Android ✔️Code::Blocks (Windows) ✔️Code::Blocks (Linux) Documentation ------------- You can read the documentation of FRUT on Read the Docs: https://frut.readthedocs.io Getting started --------------- Let's consider that you have a copy of `JUCE`_, a copy of `FRUT`_ and a JUCE project called ``MyGreatProject`` following this folder structure: :: ├── FRUT/ ├── JUCE/ └── MyGreatProject/ ├── Source/ └── MyGreatProject.jucer We first build and install FRUT with CMake: :: $ cd /FRUT/ $ mkdir build && cd build/ $ cmake .. -DCMAKE_INSTALL_PREFIX="../prefix" -DJUCE_ROOT="../../JUCE" ... -- Configuring done -- Generating done -- Build files have been written to: /FRUT/build $ cmake --build . --target install # or $ cmake --build . --target install --parallel # with CMake 3.12 or later ... If it fails to build and install, please report the problem by creating a new issue on GitHub: https://github.com/McMartin/FRUT/issues/new. Then we convert ``MyGreatProject.jucer`` to a new ``CMakeLists.txt`` file: :: $ cd /MyGreatProject/ $ ../FRUT/prefix/FRUT/bin/Jucer2CMake reprojucer MyGreatProject.jucer ../FRUT/prefix/FRUT/cmake/Reprojucer.cmake /MyGreatProject/CMakeLists.txt has been successfully generated. Now we can build ``MyGreatProject`` using CMake: :: $ cd /MyGreatProject/ $ mkdir build && cd build/ $ cmake .. -G ... -- Configuring done -- Generating done -- Build files have been written to: /MyGreatProject/build $ cmake --build . # or $ cmake --build . -- -parallelizeTargets # when is Xcode # or $ cmake --build . --parallel # with CMake 3.12 or later ... ```` can be one of many `CMake Generators`_ supported by your platform, including Ninja, NMake Makefiles (on Windows), Unix Makefiles (on Linux and macOS), Visual Studio 2013, 2015, 2017, 2019 and 2022 (on Windows), and Xcode (on macOS). Contributing ------------ Contributions to FRUT are very welcomed and you can contribute even if you don't know anything about CMake. See the `CONTRIBUTING.md`_ file for more details. Contributors ------------ FRUT follows the `all-contributors`_ specification and is brought to you by these awesome contributors: .. raw:: html Alain Martin 💻 👀 📖 Matthieu Talbot 👀 💻 🐛 Florian Goltz 💻 Fabien Roussel 🐛 👀 Xavier Jouvenot 🐛 👀 Nikolai Wuttke 👀 Dominik Grzelak 🐛 Dennis Scheffer 🐛 💻 Scott Wheeler 💻 🐛 Iqra Shahzad 🐛 Romain Clement 🐛 Stijn Frishert 🐛 Jerry Chan 🐛 👀 Frank Lange 🐛 Johannes Elliesen 🐛 💻 David Holland 💻 Dimitri Sudell 🐛 👀 Dan Raviv 🐛 👀 Rory Walsh 🐛 Eyal Amir 🐛 Michael Hetrick 🐛 Alex 💻 👀 Alexey Romanoff 🐛 Benedikt Adams 🐛 Steve Baker 🐛 David Crome 🐛 JF Castel-Branco 🐛 Butch Warns 🐛 Suganthan BC 🐛 Thiébaud Fuchs 🐛 💻 Hayden Setlik 🐛 Adrian Ostrowski 💻 Naïl Perreau 🐛 License ------- |GPLv3| FRUT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FRUT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the `LICENSE`_ file for more details. .. |Code_of_Conduct| image:: https://img.shields.io/badge/code%20of%20conduct-Contributor%20Covenant-blue.svg?style=flat :target: CODE_OF_CONDUCT.md :alt: Contributor Covenant Code of Conduct .. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/github/McMartin/frut?branch=main&svg=true :target: https://ci.appveyor.com/project/McMartin/frut :alt: AppVeyor build status .. |Azure_Pipelines| image:: https://dev.azure.com/McMartin/FRUT/_apis/build/status/McMartin.FRUT?branchName=main :target: https://dev.azure.com/McMartin/FRUT/_build?definitionId=2 :alt: Azure Pipelines build status .. |Read_the_Docs| image:: https://readthedocs.org/projects/frut/badge/?version=latest :target: https://frut.readthedocs.io :alt: Documentation status .. |GPLv3| image:: https://www.gnu.org/graphics/gplv3-127x51.png :target: https://www.gnu.org/licenses/gpl.html :alt: GNU General Public License .. _CONTRIBUTING.md: CONTRIBUTING.md .. _LICENSE: LICENSE .. _generated/JUCE-4.2.0: generated/JUCE-4.2.0 .. _generated/JUCE-4.3.1: generated/JUCE-4.3.1 .. _generated/JUCE-5.0.0: generated/JUCE-5.0.0 .. _generated/JUCE-5.2.1: generated/JUCE-5.2.1 .. _generated/JUCE-5.3.1: generated/JUCE-5.3.1 .. _generated/JUCE-5.4.3: generated/JUCE-5.4.3 .. _generated/JUCE-5.4.7: generated/JUCE-5.4.7 .. _generated/JUCE-6.0.5: generated/JUCE-6.0.5 .. _generated/JUCE-6.1.6: generated/JUCE-6.1.6 .. _generated/JUCE-7.0.7: generated/JUCE-7.0.7 .. _CMake Generators: https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html .. _CMake: https://cmake.org .. _FRUT: https://github.com/McMartin/FRUT .. _JUCE 4.2.0: https://github.com/juce-framework/JUCE/tree/4.2.0 .. _JUCE 4.3.1: https://github.com/juce-framework/JUCE/tree/4.3.1 .. _JUCE 5.0.0: https://github.com/juce-framework/JUCE/tree/5.0.0 .. _JUCE 5.2.1: https://github.com/juce-framework/JUCE/tree/5.2.1 .. _JUCE 5.3.1: https://github.com/juce-framework/JUCE/tree/5.3.1 .. _JUCE 5.4.3: https://github.com/juce-framework/JUCE/tree/5.4.3 .. _JUCE 5.4.7: https://github.com/juce-framework/JUCE/tree/5.4.7 .. _JUCE 6.0.5: https://github.com/juce-framework/JUCE/tree/6.0.5 .. _JUCE 6.1.6: https://github.com/juce-framework/JUCE/tree/6.1.6 .. _JUCE 7.0.7: https://github.com/juce-framework/JUCE/tree/7.0.7 .. _JUCE: https://github.com/juce-framework/JUCE .. _Projucer: https://juce.com/discover/projucer .. _all-contributors: https://github.com/all-contributors/all-contributors ================================================ FILE: ci/AllJuceProjects/CMakeLists.txt ================================================ # Copyright (C) 2017-2018 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . cmake_minimum_required(VERSION 3.4) if(NOT DEFINED JUCE_VERSION) message(FATAL_ERROR "JUCE_VERSION must be defined") endif() set(JUCE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../tmp/JUCE-${JUCE_VERSION}") if(NOT IS_DIRECTORY "${JUCE_ROOT}") message(FATAL_ERROR "No such directory: ${JUCE_ROOT}") endif() project(AllJuceProjects) add_subdirectory( "${CMAKE_CURRENT_LIST_DIR}/../../generated/JUCE-${JUCE_VERSION}" "JUCE-${JUCE_VERSION}" ) ================================================ FILE: ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake ================================================ # Copyright (C) 2017-2020, 2022 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . if(NOT DEFINED JUCE_VERSION) message(FATAL_ERROR "JUCE_VERSION must be defined") endif() set(JUCE_ROOT "${CMAKE_CURRENT_LIST_DIR}/tmp/JUCE-${JUCE_VERSION}") if(NOT IS_DIRECTORY "${JUCE_ROOT}") message(FATAL_ERROR "No such directory: ${JUCE_ROOT}") endif() set(generated_JUCE_ROOT "${CMAKE_CURRENT_LIST_DIR}/../generated/JUCE-${JUCE_VERSION}") if(NOT IS_DIRECTORY "${generated_JUCE_ROOT}") message(FATAL_ERROR "No such directory: ${generated_JUCE_ROOT}") endif() if(NOT DEFINED Jucer2CMake_EXE) message(FATAL_ERROR "Jucer2CMake_EXE must be defined") endif() if(NOT EXISTS ${Jucer2CMake_EXE}) message(FATAL_ERROR "No such file: ${Jucer2CMake_EXE}") endif() get_filename_component(Jucer2CMake_EXE "${Jucer2CMake_EXE}" ABSOLUTE) file(GLOB_RECURSE jucer_files RELATIVE "${JUCE_ROOT}" "${JUCE_ROOT}/*.jucer") foreach(jucer_file IN LISTS jucer_files) set(command "${Jucer2CMake_EXE}" "reprojucer" "${JUCE_ROOT}/${jucer_file}" "${CMAKE_CURRENT_LIST_DIR}/../cmake/Reprojucer.cmake" "--jucer-version" "${JUCE_VERSION}" "--relocatable" ) get_filename_component(working_dir "${generated_JUCE_ROOT}/${jucer_file}" DIRECTORY) if(NOT IS_DIRECTORY "${working_dir}") message(FATAL_ERROR "Cannot change working directory to ${working_dir}") endif() execute_process(COMMAND ${command} WORKING_DIRECTORY "${working_dir}" RESULT_VARIABLE result ) if(NOT result EQUAL 0) string(REPLACE ";" " " command_string "${command}") message(FATAL_ERROR "Failed to run `${command_string}`") endif() endforeach() ================================================ FILE: ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake ================================================ # Copyright (C) 2018-2020 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . set(tests_DIR "${CMAKE_CURRENT_LIST_DIR}/../tests") if(NOT IS_DIRECTORY "${tests_DIR}") message(FATAL_ERROR "No such directory: ${tests_DIR}") endif() if(NOT DEFINED Jucer2CMake_EXE) message(FATAL_ERROR "Jucer2CMake_EXE must be defined") endif() if(NOT EXISTS ${Jucer2CMake_EXE}) message(FATAL_ERROR "No such file: ${Jucer2CMake_EXE}") endif() get_filename_component(Jucer2CMake_EXE "${Jucer2CMake_EXE}" ABSOLUTE) file(GLOB_RECURSE jucer_files "${tests_DIR}/*.jucer") foreach(jucer_file IN LISTS jucer_files) set(command "${Jucer2CMake_EXE}" "reprojucer" "${jucer_file}" "${CMAKE_CURRENT_LIST_DIR}/../cmake/Reprojucer.cmake" ) get_filename_component(working_dir "${jucer_file}" DIRECTORY) execute_process(COMMAND ${command} WORKING_DIRECTORY "${working_dir}" RESULT_VARIABLE result ) if(NOT result EQUAL 0) string(REPLACE ";" " " command_string "${command}") message(FATAL_ERROR "Failed to run `${command_string}`") endif() endforeach() ================================================ FILE: ci/azure-pipelines/steps-Makefiles.yml ================================================ parameters: - name: juceVersions type: object steps: - script: cmake --version displayName: CMake version - ${{ each juceVersion in parameters.juceVersions }}: - script: > git clone --branch=${{ juceVersion }} --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-${{ juceVersion }} displayName: Clone JUCE ${{ juceVersion }} - script: mkdir Debug_build displayName: mkdir Debug_build - script: mkdir Release_build displayName: mkdir Release_build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G "$(cmakeGenerator)" -DCMAKE_BUILD_TYPE=Debug -DJUCE_ROOT="$(Build.SourcesDirectory)/ci/tmp/JUCE-${{ juceVersion }}" workingDirectory: Debug_build displayName: Configure FRUT with JUCE ${{ juceVersion }} (Debug) - script: cmake --build . --parallel workingDirectory: Debug_build displayName: Build FRUT with JUCE ${{ juceVersion }} (Debug) - script: > cmake .. -G "$(cmakeGenerator)" -DCMAKE_BUILD_TYPE=Release -DJUCE_ROOT="$(Build.SourcesDirectory)/ci/tmp/JUCE-${{ juceVersion }}" workingDirectory: Release_build displayName: Configure FRUT with JUCE ${{ juceVersion }} (Release) - script: > cmake .. -G "$(cmakeGenerator)" -DCMAKE_INSTALL_PREFIX="$(Build.SourcesDirectory)/prefix" workingDirectory: Release_build displayName: Configure FRUT for installation in ./prefix - script: cmake --build . --target install --parallel workingDirectory: Release_build displayName: Build and install FRUT in ./prefix - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for Jucer2CMake test projects - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for test projects - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake -DJUCE_VERSION="${{ juceVersion }}" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake displayName: Re-generate CMakeLists.txt files for JUCE ${{ juceVersion }} - script: git diff --exit-code displayName: Check that generated CMakeLists.txt files are up-to-date - script: mkdir ci/AllJuceProjects/Debug_build displayName: mkdir ci/AllJuceProjects/Debug_build - script: mkdir ci/AllJuceProjects/Release_build displayName: mkdir ci/AllJuceProjects/Release_build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G "$(cmakeGenerator)" -DCMAKE_BUILD_TYPE=Debug -DJUCE_VERSION="${{ juceVersion }}" -DJUCER_AAX_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST3" -DJUCER_VST_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST" workingDirectory: ci/AllJuceProjects/Debug_build displayName: Configure all JUCE ${{ juceVersion }} projects (Debug) - script: > cmake .. -G "$(cmakeGenerator)" -DCMAKE_BUILD_TYPE=Release -DJUCE_VERSION="${{ juceVersion }}" -DJUCER_AAX_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST3" -DJUCER_VST_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST" workingDirectory: ci/AllJuceProjects/Release_build displayName: Configure all JUCE ${{ juceVersion }} projects (Release) ================================================ FILE: ci/azure-pipelines/steps-VS.yml ================================================ parameters: - name: juceVersions type: object steps: - script: cmake --version displayName: CMake version - ${{ each juceVersion in parameters.juceVersions }}: - script: > git clone --branch=${{ juceVersion }} --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-${{ juceVersion }} displayName: Clone JUCE ${{ juceVersion }} - script: mkdir build displayName: mkdir build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G "$(cmakeGenerator)" -DJUCE_ROOT="$(Build.SourcesDirectory)/ci/tmp/JUCE-${{ juceVersion }}" -DJucer2CMake_WRITE_CRLF_LINE_ENDINGS=ON workingDirectory: build displayName: Configure FRUT with JUCE ${{ juceVersion }} - script: cmake --build . --config Debug --parallel workingDirectory: build displayName: Build FRUT with JUCE ${{ juceVersion }} - script: cmake .. -DCMAKE_INSTALL_PREFIX="$(Build.SourcesDirectory)/prefix" workingDirectory: build displayName: Configure FRUT for installation in ./prefix - script: cmake --build . --config Release --target install --parallel workingDirectory: build displayName: Build and install FRUT in ./prefix - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for Jucer2CMake test projects - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for test projects - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake -DJUCE_VERSION="${{ juceVersion }}" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake.exe" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake displayName: Re-generate CMakeLists.txt files for JUCE ${{ juceVersion }} - script: git diff --exit-code displayName: Check that generated CMakeLists.txt files are up-to-date - script: mkdir ci\AllJuceProjects\build displayName: mkdir ci/AllJuceProjects/build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G "$(cmakeGenerator)" -DJUCE_VERSION="${{ juceVersion }}" -DJUCER_AAX_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST3" -DJUCER_VST_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST" workingDirectory: ci/AllJuceProjects/build displayName: Configure all JUCE ${{ juceVersion }} projects ================================================ FILE: ci/azure-pipelines/steps-Xcode.yml ================================================ parameters: - name: juceVersions type: object steps: - script: cmake --version displayName: CMake version - ${{ each juceVersion in parameters.juceVersions }}: - script: > git clone --branch=${{ juceVersion }} --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-${{ juceVersion }} displayName: Clone JUCE ${{ juceVersion }} - script: mkdir build displayName: mkdir build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G Xcode -DJUCE_ROOT="$(Build.SourcesDirectory)/ci/tmp/JUCE-${{ juceVersion }}" workingDirectory: build displayName: Configure FRUT with JUCE ${{ juceVersion }} - script: cmake --build . --config Debug -- -parallelizeTargets workingDirectory: build displayName: Build FRUT with JUCE ${{ juceVersion }} - script: cmake .. -G Xcode -DCMAKE_INSTALL_PREFIX="$(Build.SourcesDirectory)/prefix" workingDirectory: build displayName: Configure FRUT for installation in ./prefix - script: cmake --build . --config Release --target install -- -parallelizeTargets workingDirectory: build displayName: Build and install FRUT in ./prefix - script: cmake .. -G Xcode workingDirectory: tests/test-projects/entitlements-generation/guiapp-MacOSX/binary_dir displayName: Re-generate .entitlements files for GUI Application projects - script: cmake .. -G Xcode workingDirectory: tests/test-projects/entitlements-generation/plugin-MacOSX/binary_dir displayName: Re-generate .entitlements files for Audio Plug-In projects - script: git diff --exit-code displayName: Check that .entitlements files haven't changed - script: cmake .. -G Xcode workingDirectory: tests/test-projects/plist-generation/guiapp-MacOSX/binary_dir displayName: Re-generate .plist files for GUI Application projects - script: cmake .. -G Xcode workingDirectory: tests/test-projects/plist-generation/plugin-MacOSX/binary_dir displayName: Re-generate .plist files for Audio Plug-In projects - script: git diff --exit-code displayName: Check that .plist files haven't changed - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P Jucer2CMake/tests/apply-Jucer2CMake-juce6-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for Jucer2CMake test projects - script: > cmake -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P ci/apply-Jucer2CMake-reprojucer-to-test-jucers.cmake displayName: Re-generate CMakeLists.txt files for test projects - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake -DJUCE_VERSION="${{ juceVersion }}" -DJucer2CMake_EXE="prefix/FRUT/bin/Jucer2CMake" -P ci/apply-Jucer2CMake-reprojucer-to-JUCE-jucers.cmake displayName: Re-generate CMakeLists.txt files for JUCE ${{ juceVersion }} - script: git diff --exit-code displayName: Check that generated CMakeLists.txt files are up-to-date - script: mkdir ci/AllJuceProjects/build displayName: mkdir ci/AllJuceProjects/build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G Xcode -DJUCE_VERSION="${{ juceVersion }}" -DJUCER_AAX_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/AAX" -DJUCER_VST3_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST3" -DJUCER_VST_SDK_FOLDER="$(Build.SourcesDirectory)/ci/fake-SDKs/VST" workingDirectory: ci/AllJuceProjects/build displayName: Configure all JUCE ${{ juceVersion }} projects ================================================ FILE: ci/azure-pipelines/steps-iOS.yml ================================================ parameters: - name: juceVersions type: object steps: - script: cmake --version displayName: CMake version - ${{ each juceVersion in parameters.juceVersions }}: - script: > git clone --branch=${{ juceVersion }} --depth=1 --single-branch -- https://github.com/juce-framework/JUCE.git ci/tmp/JUCE-${{ juceVersion }} displayName: Clone JUCE ${{ juceVersion }} - script: cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS workingDirectory: tests/test-projects/entitlements-generation/guiapp-iOS/binary_dir displayName: Re-generate .entitlements files for GUI Application projects - script: cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS workingDirectory: tests/test-projects/entitlements-generation/plugin-iOS/binary_dir displayName: Re-generate .entitlements files for Audio Plug-In projects - script: git diff --exit-code displayName: Check that .entitlements files haven't changed - script: cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS workingDirectory: tests/test-projects/plist-generation/guiapp-iOS/binary_dir displayName: Re-generate .plist files for GUI Application projects - script: cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS workingDirectory: tests/test-projects/plist-generation/plugin-iOS/binary_dir displayName: Re-generate .plist files for Audio Plug-In projects - script: git diff --exit-code displayName: Check that .plist files haven't changed - script: mkdir ci/AllJuceProjects/build displayName: mkdir ci/AllJuceProjects/build - ${{ each juceVersion in parameters.juceVersions }}: - script: > cmake .. -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DJUCE_VERSION="${{ juceVersion }}" workingDirectory: ci/AllJuceProjects/build displayName: Configure all JUCE ${{ juceVersion }} projects ================================================ FILE: ci/fake-SDKs/AAX/Interfaces/AAX_Exports.cpp ================================================ ================================================ FILE: ci/fake-SDKs/VST/pluginterfaces/vst2.x/aeffect.h ================================================ ================================================ FILE: ci/fake-SDKs/VST/public.sdk/source/vst2.x/audioeffectx.h ================================================ ================================================ FILE: ci/fake-SDKs/VST3/base/source/baseiids.cpp ================================================ ================================================ FILE: cmake/Reprojucer.cmake ================================================ # Copyright (C) 2016-2024 Alain Martin # Copyright (C) 2017 Matthieu Talbot # Copyright (C) 2018-2019 Scott Wheeler # Copyright (C) 2022 Thiébaud Fuchs # # This file is part of FRUT. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. if(CMAKE_VERSION VERSION_LESS 3.4) message(FATAL_ERROR "Reprojucer.cmake requires at least CMake version 3.4") endif() if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND CMAKE_VERSION VERSION_LESS 3.14) message(FATAL_ERROR "Reprojucer.cmake requires at least CMake version 3.14 for iOS support" ) endif() if(IOS AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(FATAL_ERROR "Reprojucer.cmake only supports iOS when using the Xcode generator." " You must call `cmake -G Xcode`." ) endif() set(Reprojucer.cmake_DIR "${CMAKE_CURRENT_LIST_DIR}") set(Reprojucer_data_DIR "${Reprojucer.cmake_DIR}/data") set(Reprojucer_supported_exporters "Xcode (macOS)" "Xcode (iOS)" "Visual Studio 2022" "Visual Studio 2019" "Visual Studio 2017" "Visual Studio 2015" "Visual Studio 2013" "Linux Makefile" "Code::Blocks (Windows)" "Code::Blocks (Linux)" ) set(Reprojucer_supported_exporters_conditions "APPLE\;AND\;NOT\;IOS" "IOS" "MSVC_VERSION\;GREATER\;1929\;AND\;MSVC_VERSION\;LESS\;1950" "MSVC_VERSION\;GREATER\;1919\;AND\;MSVC_VERSION\;LESS\;1930" "MSVC_VERSION\;GREATER\;1909\;AND\;MSVC_VERSION\;LESS\;1920" "MSVC_VERSION\;EQUAL\;1900" "MSVC_VERSION\;EQUAL\;1800" "CMAKE_HOST_SYSTEM_NAME\;STREQUAL\;Linux\;AND\;NOT\;CMAKE_EXTRA_GENERATOR\;STREQUAL\;CodeBlocks" "WIN32\;AND\;NOT\;MSVC" "CMAKE_HOST_SYSTEM_NAME\;STREQUAL\;Linux\;AND\;CMAKE_EXTRA_GENERATOR\;STREQUAL\;CodeBlocks" ) function(jucer_project_begin) set(single_value_keywords "JUCER_FORMAT_VERSION" "JUCER_VERSION" "PROJECT_FILE" "PROJECT_ID" ) _FRUT_parse_arguments("${single_value_keywords}" "" "${ARGN}") if(DEFINED _JUCER_FORMAT_VERSION) set(JUCER_FORMAT_VERSION "${_JUCER_FORMAT_VERSION}" PARENT_SCOPE) endif() if(DEFINED _JUCER_VERSION) set(JUCER_VERSION "${_JUCER_VERSION}" PARENT_SCOPE) endif() if(DEFINED _PROJECT_FILE) get_filename_component(abs_project_file "${_PROJECT_FILE}" ABSOLUTE) if(NOT EXISTS "${abs_project_file}") message(FATAL_ERROR "No such JUCE project file: \"${_PROJECT_FILE}\" (\"${abs_project_file}\")" ) endif() get_filename_component(project_dir "${abs_project_file}" DIRECTORY) set(JUCER_PROJECT_DIR "${project_dir}" PARENT_SCOPE) else() set(JUCER_PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE) endif() if(DEFINED _PROJECT_ID) set(JUCER_PROJECT_ID "${_PROJECT_ID}" PARENT_SCOPE) endif() endfunction() function(jucer_project_settings) set(single_value_keywords "PROJECT_NAME" "PROJECT_VERSION" "COMPANY_NAME" "COMPANY_COPYRIGHT" "COMPANY_WEBSITE" "COMPANY_EMAIL" "USE_GLOBAL_APPCONFIG_HEADER" "ADD_USING_NAMESPACE_JUCE_TO_JUCE_HEADER" "REPORT_JUCE_APP_USAGE" "DISPLAY_THE_JUCE_SPLASH_SCREEN" "SPLASH_SCREEN_COLOUR" "PROJECT_TYPE" "BUNDLE_IDENTIFIER" "BINARYDATACPP_SIZE_LIMIT" "INCLUDE_BINARYDATA" "BINARYDATA_NAMESPACE" "CXX_LANGUAGE_STANDARD" "POST_EXPORT_SHELL_COMMAND_MACOS_LINUX" "POST_EXPORT_SHELL_COMMAND_WINDOWS" ) set(multi_value_keywords "PREPROCESSOR_DEFINITIONS" "HEADER_SEARCH_PATHS") _FRUT_parse_arguments("${single_value_keywords}" "${multi_value_keywords}" "${ARGN}") if(NOT DEFINED _PROJECT_NAME) message(FATAL_ERROR "Missing PROJECT_NAME argument") endif() if(DEFINED _PROJECT_VERSION) string(REGEX MATCH ".+\\..+\\..+(\\..+)?" version_match "${_PROJECT_VERSION}") if(NOT _PROJECT_VERSION STREQUAL version_match) message(WARNING "The PROJECT_VERSION doesn't seem to be in the format" " major.minor.point[.point]" ) endif() _FRUT_version_to_hex("${_PROJECT_VERSION}" hex_value) set(JUCER_PROJECT_VERSION_AS_HEX "${hex_value}" PARENT_SCOPE) endif() if(NOT DEFINED _PROJECT_TYPE) message(FATAL_ERROR "Missing PROJECT_TYPE argument") endif() set(project_types "GUI Application" "Console Application" "Static Library" "Dynamic Library" "Audio Plug-in" ) if(NOT _PROJECT_TYPE IN_LIST project_types) message(FATAL_ERROR "Unsupported project type: \"${_PROJECT_TYPE}\"\n" "Supported project types: ${project_types}" ) endif() if(DEFINED _BINARYDATACPP_SIZE_LIMIT) set(size_limit_descs "Default" "20.0 MB" "10.0 MB" "6.0 MB" "2.0 MB" "1.0 MB" "512.0 KB" "256.0 KB" "128.0 KB" "64.0 KB" ) set(size_limits 10240 20480 10240 6144 2048 1024 512 256 128 64) list(FIND size_limit_descs "${_BINARYDATACPP_SIZE_LIMIT}" size_limit_index) if(size_limit_index EQUAL -1) message(FATAL_ERROR "Unsupported value for BINARYDATACPP_SIZE_LIMIT:" " \"${_BINARYDATACPP_SIZE_LIMIT}\"\nSupported values: ${size_limit_descs}" ) endif() list(GET size_limits ${size_limit_index} _BINARYDATACPP_SIZE_LIMIT) endif() if(DEFINED _CXX_LANGUAGE_STANDARD) set(cxx_lang_standard_descs "C++11" "C++14" "C++17" "C++20" "Use Latest") set(cxx_lang_standards "11" "14" "17" "20" "latest") list(FIND cxx_lang_standard_descs "${_CXX_LANGUAGE_STANDARD}" cxx_lang_standard_index) if(cxx_lang_standard_index EQUAL -1) message(FATAL_ERROR "Unsupported value for CXX_LANGUAGE_STANDARD:" " \"${_CXX_LANGUAGE_STANDARD}\"\nSupported values: ${cxx_lang_standard_descs}" ) endif() list(GET cxx_lang_standards ${cxx_lang_standard_index} _CXX_LANGUAGE_STANDARD) endif() if(DEFINED _POST_EXPORT_SHELL_COMMAND_MACOS_LINUX OR DEFINED _POST_EXPORT_SHELL_COMMAND_WINDOWS) option(JUCER_RUN_POST_EXPORT_SHELL_COMMANDS "If ON, run Post-Export Shell Commands of JUCE projects" ) endif() foreach(keyword IN LISTS single_value_keywords multi_value_keywords) if(DEFINED _${keyword}) set(JUCER_${keyword} "${_${keyword}}" PARENT_SCOPE) endif() endforeach() endfunction() function(jucer_audio_plugin_settings) set(plugin_formats_keywords "BUILD_VST" "BUILD_VST3" "BUILD_AUDIOUNIT" "BUILD_AUDIOUNIT_V3" "BUILD_RTAS" "BUILD_AAX" "BUILD_STANDALONE_PLUGIN" "BUILD_UNITY_PLUGIN" "ENABLE_INTER_APP_AUDIO" ) set(plugin_characteristics_keywords "PLUGIN_IS_A_SYNTH" "PLUGIN_MIDI_INPUT" "PLUGIN_MIDI_OUTPUT" "MIDI_EFFECT_PLUGIN" "KEY_FOCUS" ) set(single_value_keywords ${plugin_formats_keywords} "PLUGIN_NAME" "PLUGIN_DESCRIPTION" "PLUGIN_MANUFACTURER" "PLUGIN_MANUFACTURER_CODE" "PLUGIN_CODE" "PLUGIN_CHANNEL_CONFIGURATIONS" ${plugin_characteristics_keywords} "PLUGIN_AAX_IDENTIFIER" "PLUGIN_AU_EXPORT_PREFIX" "PLUGIN_AU_MAIN_TYPE" "PLUGIN_AU_IS_SANDBOX_SAFE" "PLUGIN_VST_NUM_MIDI_INPUTS" "PLUGIN_VST_NUM_MIDI_OUTPUTS" "PLUGIN_VST_LEGACY_CATEGORY" "PLUGIN_VST_CATEGORY" "VST_CATEGORY" ) set(multi_value_keywords "PLUGIN_FORMATS" "PLUGIN_CHARACTERISTICS" "PLUGIN_VST3_CATEGORY" "PLUGIN_RTAS_CATEGORY" "PLUGIN_AAX_CATEGORY" ) _FRUT_parse_arguments("${single_value_keywords}" "${multi_value_keywords}" "${ARGN}") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) if(DEFINED _BUILD_STANDALONE_PLUGIN) message(WARNING "BUILD_STANDALONE_PLUGIN is a JUCE 5 feature only") endif() if(DEFINED _ENABLE_INTER_APP_AUDIO) message(WARNING "ENABLE_INTER_APP_AUDIO is a JUCE 5 feature only") endif() endif() if(DEFINED _PLUGIN_FORMATS) set(plugin_formats_vars ${plugin_formats_keywords} "BUILD_VST") set(plugin_formats_values "VST" "VST3" "AU" "AUv3" "RTAS" "AAX" "Standalone" "Unity" "Enable IAA" "VST (Legacy)" ) foreach(index RANGE 9) list(GET plugin_formats_vars ${index} format_var) if(NOT DEFINED _${format_var}) list(GET plugin_formats_values ${index} format_value) if(format_value IN_LIST _PLUGIN_FORMATS) set(_${format_var} ON) endif() endif() endforeach() endif() if(DEFINED _PLUGIN_CHARACTERISTICS) set(extra_rtas_aax_keywords "PLUGIN_RTAS_DISABLE_BYPASS" "PLUGIN_AAX_DISABLE_BYPASS" "PLUGIN_RTAS_DISABLE_MULTI_MONO" "PLUGIN_AAX_DISABLE_MULTI_MONO" ) list(APPEND single_value_keywords ${extra_rtas_aax_keywords}) set(plugin_characteristics_vars ${plugin_characteristics_keywords} ${extra_rtas_aax_keywords} ) set(plugin_characteristics_values "Plugin is a Synth" "Plugin MIDI Input" "Plugin MIDI Output" "MIDI Effect Plugin" "Plugin Editor Requires Keyboard Focus" "Disable RTAS Bypass" "Disable AAX Bypass" "Disable RTAS Multi-Mono" "Disable AAX Multi-Mono" ) foreach(index RANGE 8) list(GET plugin_characteristics_vars ${index} characteristic_var) if(NOT DEFINED _${characteristic_var}) list(GET plugin_characteristics_values ${index} characteristic_value) if(characteristic_value IN_LIST _PLUGIN_CHARACTERISTICS) set(_${characteristic_var} ON) endif() endif() endforeach() endif() if(DEFINED _VST_CATEGORY) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1)) message(WARNING "VST_CATEGORY is deprecated. Use PLUGIN_VST_CATEGORY instead.") endif() endif() foreach(keyword IN LISTS single_value_keywords multi_value_keywords) if(DEFINED _${keyword}) set(JUCER_${keyword} "${_${keyword}}" PARENT_SCOPE) endif() endforeach() endfunction() function(jucer_project_files source_group_name) function(_FRUT_jucer_project_files_assert_x_or_dot input row_number property) if(NOT input STREQUAL "x" AND NOT input STREQUAL ".") message(FATAL_ERROR "Expected \"x\" or \".\" token for \"${property}\", got" " \"${input}\" instead (row ${row_number})" ) endif() endfunction() set(files "") set(compiler_flag_schemes "") unset(compile) unset(xcode_resource) unset(binary_resource) unset(path) set(row 1) foreach(argument IN LISTS ARGN) if(NOT DEFINED compile) _FRUT_jucer_project_files_assert_x_or_dot("${argument}" ${row} "Compile") set(compile "${argument}") elseif(NOT DEFINED xcode_resource) _FRUT_jucer_project_files_assert_x_or_dot("${argument}" ${row} "Xcode Resource") set(xcode_resource "${argument}") elseif(NOT DEFINED binary_resource) _FRUT_jucer_project_files_assert_x_or_dot("${argument}" ${row} "Binary Resource") set(binary_resource "${argument}") elseif(NOT DEFINED path) if(argument STREQUAL "x" OR argument STREQUAL ".") message(FATAL_ERROR "Expected path for \"File\", got \"${argument}\" instead (row ${row})" ) endif() set(path "${argument}") _FRUT_abs_path_based_on_jucer_project_dir(path "${path}") if(compile STREQUAL "x" OR xcode_resource STREQUAL ".") list(APPEND files "${path}") elseif(xcode_resource STREQUAL "x") list(APPEND JUCER_PROJECT_XCODE_RESOURCES "${path}") endif() if(binary_resource STREQUAL "x") list(APPEND JUCER_PROJECT_RESOURCES "${path}") endif() get_filename_component(file_extension "${path}" EXT) if((NOT file_extension STREQUAL ".h" AND compile STREQUAL ".") OR (file_extension STREQUAL ".mm" AND NOT APPLE)) set_source_files_properties("${path}" PROPERTIES HEADER_FILE_ONLY TRUE) endif() else() if(argument STREQUAL "x" OR argument STREQUAL ".") set(compile "${argument}") else() set(scheme "${argument}") list(APPEND compiler_flag_schemes "${scheme}") list(APPEND JUCER_COMPILER_FLAG_SCHEME_${scheme}_FILES "${path}") unset(compile) endif() unset(xcode_resource) unset(binary_resource) unset(path) math(EXPR row "${row} + 1") endif() endforeach() string(REPLACE "/" "\\" source_group_name ${source_group_name}) source_group(${source_group_name} FILES ${files}) list(APPEND JUCER_PROJECT_FILES ${files}) set(JUCER_PROJECT_FILES "${JUCER_PROJECT_FILES}" PARENT_SCOPE) set(JUCER_PROJECT_RESOURCES "${JUCER_PROJECT_RESOURCES}" PARENT_SCOPE) set(JUCER_PROJECT_XCODE_RESOURCES "${JUCER_PROJECT_XCODE_RESOURCES}" PARENT_SCOPE) list(APPEND JUCER_COMPILER_FLAG_SCHEMES "${compiler_flag_schemes}") list(REMOVE_DUPLICATES JUCER_COMPILER_FLAG_SCHEMES) set(JUCER_COMPILER_FLAG_SCHEMES "${JUCER_COMPILER_FLAG_SCHEMES}" PARENT_SCOPE) foreach(scheme IN LISTS compiler_flag_schemes) set(JUCER_COMPILER_FLAG_SCHEME_${scheme}_FILES "${JUCER_COMPILER_FLAG_SCHEME_${scheme}_FILES}" PARENT_SCOPE ) endforeach() endfunction() function(jucer_project_module module_name PATH_KEYWORD modules_folder) if(NOT PATH_KEYWORD STREQUAL "PATH") message(FATAL_ERROR "Invalid second argument. Expected \"PATH\" keyword, but got" " \"${PATH_KEYWORD}\" instead." ) endif() _FRUT_abs_path_based_on_jucer_project_dir(modules_folder "${modules_folder}") if(NOT IS_DIRECTORY "${modules_folder}") message(FATAL_ERROR "No such directory: \"${modules_folder}\"") endif() set(module_dir "${modules_folder}/${module_name}") foreach(extension IN ITEMS ".h" ".hpp" ".hxx") set(module_header_file "${module_dir}/${module_name}${extension}") if(EXISTS "${module_header_file}") break() endif() endforeach() if(NOT EXISTS "${module_header_file}") message(FATAL_ERROR "\"${module_dir}/\" is not a valid JUCE module") endif() set(make_juce_code_browsable ON) set(extra_keywords "") unset(keyword) foreach(argument IN LISTS ARGN) if(NOT DEFINED keyword) set(keyword "${argument}") if(NOT keyword STREQUAL "ADD_SOURCE_TO_PROJECT") list(APPEND extra_keywords "${keyword}") endif() else() set(value "${argument}") if(keyword STREQUAL "ADD_SOURCE_TO_PROJECT") set(make_juce_code_browsable "${value}") else() set(extra_values_${keyword} "${value}") endif() unset(keyword) endif() endforeach() foreach(keyword IN LISTS extra_keywords) if(NOT DEFINED extra_values_${keyword}) message(WARNING "Keyword \"${keyword}\" doesn't have any associated value") endif() endforeach() list(APPEND JUCER_PROJECT_MODULES ${module_name}) set(JUCER_PROJECT_MODULES "${JUCER_PROJECT_MODULES}" PARENT_SCOPE) list(APPEND JUCER_PROJECT_MODULES_FOLDERS "${modules_folder}") set(JUCER_PROJECT_MODULES_FOLDERS "${JUCER_PROJECT_MODULES_FOLDERS}" PARENT_SCOPE) set(JUCER_PROJECT_MODULE_${module_name}_PATH "${modules_folder}" PARENT_SCOPE) file(GLOB module_src_files LIST_DIRECTORIES FALSE "${module_dir}/${module_name}*.cpp" "${module_dir}/${module_name}*.mm" "${module_dir}/${module_name}*.r" ) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) set(proxy_prefix "") else() set(proxy_prefix "include_") endif() if(DEFINED JUCER_USE_GLOBAL_APPCONFIG_HEADER AND NOT JUCER_USE_GLOBAL_APPCONFIG_HEADER) set(appconfig_include "") else() set(appconfig_include "#include \"AppConfig.h\"\n") endif() set(can_build_vst3 FALSE) if((APPLE AND NOT IOS) OR MSVC) set(can_build_vst3 TRUE) elseif( NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" ) set(can_build_vst3 TRUE) endif() set(module_sources "") foreach(src_file IN LISTS module_src_files) unset(to_compile) if( (src_file MATCHES "_AU[._]" AND NOT (JUCER_BUILD_AUDIOUNIT AND (APPLE AND NOT IOS))) OR (src_file MATCHES "_AUv3[._]" AND NOT (JUCER_BUILD_AUDIOUNIT_V3 AND APPLE)) OR (src_file MATCHES "_AAX[._]" AND NOT (JUCER_BUILD_AAX AND ((APPLE AND NOT IOS) OR MSVC))) OR (src_file MATCHES "_RTAS[._]" AND NOT (JUCER_BUILD_RTAS AND ((APPLE AND NOT IOS) OR MSVC))) OR (src_file MATCHES "_VST2[._]" AND NOT (JUCER_BUILD_VST AND NOT IOS)) OR (src_file MATCHES "_VST3[._]" AND NOT (JUCER_BUILD_VST3 AND can_build_vst3)) ) set(to_compile FALSE) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) if(src_file MATCHES "_Standalone[._]" AND NOT (JUCER_BUILD_AUDIOUNIT_V3 AND APPLE)) set(to_compile FALSE) endif() else() if(src_file MATCHES "_Standalone[._]" AND NOT JUCER_BUILD_STANDALONE_PLUGIN) set(to_compile FALSE) endif() endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2)) if(src_file MATCHES "_Unity[._]" AND NOT JUCER_BUILD_UNITY_PLUGIN) set(to_compile FALSE) endif() endif() if(NOT DEFINED to_compile) get_filename_component(src_file_extension "${src_file}" EXT) if(src_file_extension STREQUAL ".mm") if(APPLE) set(to_compile TRUE) endif() elseif(APPLE) string(REGEX REPLACE "${src_file_extension}$" ".mm" objcxx_src_file "${src_file}") if(NOT objcxx_src_file IN_LIST module_src_files) set(to_compile TRUE) endif() else() set(to_compile TRUE) endif() endif() if(to_compile) get_filename_component(src_file_basename "${src_file}" NAME) if(src_file_extension STREQUAL ".r") set(proxied_src_file "${src_file_basename}") else() set(proxied_src_file "${module_name}/${src_file_basename}") endif() configure_file("${Reprojucer_data_DIR}/JuceLibraryCode-Wrapper.cpp.in" "JuceLibraryCode/${proxy_prefix}${src_file_basename}" @ONLY ) list(APPEND module_sources "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/${proxy_prefix}${src_file_basename}" ) endif() endforeach() set(JUCER_PROJECT_MODULE_${module_name}_SOURCES "${module_sources}" PARENT_SCOPE) file(STRINGS "${module_header_file}" config_flags_lines REGEX "/\\*\\* Config: ") string(REPLACE "/** Config: " "" module_config_flags "${config_flags_lines}") set(JUCER_${module_name}_CONFIG_FLAGS "${module_config_flags}" PARENT_SCOPE) foreach(config_flag IN LISTS extra_keywords) if(NOT config_flag IN_LIST module_config_flags) message(WARNING "Unknown config flag ${config_flag} in module ${module_name}") endif() set(JUCER_FLAG_${config_flag} "${extra_values_${config_flag}}" PARENT_SCOPE) endforeach() unset(module_info_version) set(module_info_searchpaths "") set(module_info_OSXFrameworks "") set(module_info_WeakOSXFrameworks "") set(module_info_iOSFrameworks "") set(module_info_WeakiOSFrameworks "") set(module_info_linuxPackages "") set(module_info_linuxLibs "") set(module_info_mingwLibs "") set(module_info_OSXLibs "") set(module_info_iOSLibs "") set(module_info_windowsLibs "") unset(module_info_minimumCppStandard) file(STRINGS "${module_header_file}" all_lines) set(in_module_declaration FALSE) foreach(line IN LISTS all_lines) string(STRIP "${line}" stripped_line) if(stripped_line MATCHES "^BEGIN_JUCE_MODULE_DECLARATION") set(in_module_declaration TRUE) continue() elseif(stripped_line MATCHES "^END_JUCE_MODULE_DECLARATION") break() endif() if(in_module_declaration) string(FIND "${line}" ":" colon_pos) if(NOT colon_pos EQUAL -1) string(SUBSTRING "${line}" 0 ${colon_pos} key) string(STRIP "${key}" key) math(EXPR colon_pos_plus_one "${colon_pos} + 1") string(SUBSTRING "${line}" ${colon_pos_plus_one} -1 value) string(STRIP "${value}" value) set(module_info_${key} "${value}") endif() endif() endforeach() set(JUCER_PROJECT_MODULE_${module_name}_VERSION "${module_info_version}" PARENT_SCOPE) string(REGEX REPLACE "[ ,]+" ";" search_paths "${module_info_searchpaths}") foreach(search_path IN LISTS search_paths) list(APPEND JUCER_PROJECT_MODULES_INTERNAL_SEARCH_PATHS "${module_dir}/${search_path}" ) endforeach() set(JUCER_PROJECT_MODULES_INTERNAL_SEARCH_PATHS "${JUCER_PROJECT_MODULES_INTERNAL_SEARCH_PATHS}" PARENT_SCOPE ) if(IOS) string(REGEX REPLACE "[ ,]+" ";" xcode_frameworks "${module_info_iOSFrameworks}") string(REGEX REPLACE "[ ,]+" ";" xcode_weak_frameworks "${module_info_WeakiOSFrameworks}") else() string(REGEX REPLACE "[ ,]+" ";" xcode_frameworks "${module_info_OSXFrameworks}") string(REGEX REPLACE "[ ,]+" ";" xcode_weak_frameworks "${module_info_WeakOSXFrameworks}") endif() list(APPEND JUCER_PROJECT_XCODE_FRAMEWORKS ${xcode_frameworks}) set(JUCER_PROJECT_XCODE_FRAMEWORKS "${JUCER_PROJECT_XCODE_FRAMEWORKS}" PARENT_SCOPE) list(APPEND JUCER_PROJECT_XCODE_WEAK_FRAMEWORKS ${xcode_weak_frameworks}) set(JUCER_PROJECT_XCODE_WEAK_FRAMEWORKS "${JUCER_PROJECT_XCODE_WEAK_FRAMEWORKS}" PARENT_SCOPE) string(REGEX REPLACE "[ ,]+" ";" linux_packages "${module_info_linuxPackages}") list(APPEND JUCER_PROJECT_LINUX_PACKAGES ${linux_packages}) set(JUCER_PROJECT_LINUX_PACKAGES "${JUCER_PROJECT_LINUX_PACKAGES}" PARENT_SCOPE) string(REGEX REPLACE "[ ,]+" ";" linux_libs "${module_info_linuxLibs}") list(APPEND JUCER_PROJECT_LINUX_LIBS ${linux_libs}) set(JUCER_PROJECT_LINUX_LIBS "${JUCER_PROJECT_LINUX_LIBS}" PARENT_SCOPE) string(REGEX REPLACE "[ ,]+" ";" mingw_libs "${module_info_mingwLibs}") list(APPEND JUCER_PROJECT_MINGW_LIBS ${mingw_libs}) set(JUCER_PROJECT_MINGW_LIBS "${JUCER_PROJECT_MINGW_LIBS}" PARENT_SCOPE) if(IOS) string(REGEX REPLACE "[ ,]+" ";" xcode_libs "${module_info_iOSLibs}") else() string(REGEX REPLACE "[ ,]+" ";" xcode_libs "${module_info_OSXLibs}") endif() list(APPEND JUCER_PROJECT_XCODE_LIBS ${xcode_libs}) set(JUCER_PROJECT_XCODE_LIBS "${JUCER_PROJECT_XCODE_LIBS}" PARENT_SCOPE) string(REGEX REPLACE "[ ,]+" ";" windows_libs "${module_info_windowsLibs}") list(APPEND JUCER_PROJECT_WINDOWS_LIBS ${windows_libs}) set(JUCER_PROJECT_WINDOWS_LIBS "${JUCER_PROJECT_WINDOWS_LIBS}" PARENT_SCOPE) if(DEFINED module_info_minimumCppStandard) unset(project_cxx_standard) if(DEFINED JUCER_CXX_LANGUAGE_STANDARD) set(project_cxx_standard "${JUCER_CXX_LANGUAGE_STANDARD}") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.1.0) # "C++ Language Standard" didn't exist before JUCE version 5.1.0 elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.1) set(project_cxx_standard 11) else() set(project_cxx_standard 14) endif() if(DEFINED project_cxx_standard AND NOT (project_cxx_standard STREQUAL "latest") AND (module_info_minimumCppStandard STREQUAL "latest" OR module_info_minimumCppStandard GREATER project_cxx_standard)) message(WARNING "${module_name} has a higher C++ language standard requirement" " (${module_info_minimumCppStandard}) than your project" " (${project_cxx_standard}). To use this module you need to increase the C++" " language standard of the project." ) endif() endif() if(make_juce_code_browsable) file(GLOB_RECURSE browsable_files "${module_dir}/*") foreach(file_path IN LISTS browsable_files) get_filename_component(file_dir "${file_path}" DIRECTORY) string(REPLACE "${modules_folder}" "" rel_file_dir "${file_dir}") string(REPLACE "/" "\\" sub_group_name "${rel_file_dir}") source_group("JUCE Modules${sub_group_name}" FILES "${file_path}") endforeach() list(APPEND JUCER_PROJECT_MODULES_BROWSABLE_FILES ${browsable_files}) set(JUCER_PROJECT_MODULES_BROWSABLE_FILES "${JUCER_PROJECT_MODULES_BROWSABLE_FILES}" PARENT_SCOPE ) endif() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") set(module_lib_dir "${module_dir}/libs/Linux") elseif(WIN32 AND NOT MSVC) set(module_lib_dir "${module_dir}/libs/MinGW") elseif(IOS) set(module_lib_dir "${module_dir}/libs/iOS") elseif(APPLE) set(module_lib_dir "${module_dir}/libs/MacOSX") elseif(MSVC) if(MSVC_VERSION GREATER 1929 AND MSVC_VERSION LESS 1940) set(module_lib_dir "${module_dir}/libs/VisualStudio2022") elseif(MSVC_VERSION GREATER 1919 AND MSVC_VERSION LESS 1930) set(module_lib_dir "${module_dir}/libs/VisualStudio2019") elseif(MSVC_VERSION GREATER 1909 AND MSVC_VERSION LESS 1920) set(module_lib_dir "${module_dir}/libs/VisualStudio2017") elseif(MSVC_VERSION EQUAL 1900) set(module_lib_dir "${module_dir}/libs/VisualStudio2015") elseif(MSVC_VERSION EQUAL 1800) set(module_lib_dir "${module_dir}/libs/VisualStudio2013") endif() endif() if(IS_DIRECTORY "${module_lib_dir}") list(APPEND JUCER_PROJECT_MODULES_LIBRARY_SEARCH_PATHS "${module_lib_dir}") set(JUCER_PROJECT_MODULES_LIBRARY_SEARCH_PATHS "${JUCER_PROJECT_MODULES_LIBRARY_SEARCH_PATHS}" PARENT_SCOPE ) endif() endfunction() function(jucer_appconfig_header USER_CODE_SECTION_KEYWORD user_code_section) if(NOT USER_CODE_SECTION_KEYWORD STREQUAL "USER_CODE_SECTION") message(FATAL_ERROR "Invalid second argument. Expected \"USER_CODE_SECTION\" keyword," " but got \"${USER_CODE_SECTION_KEYWORD}\" instead." ) endif() set(JUCER_APPCONFIG_USER_CODE_SECTION "${user_code_section}" PARENT_SCOPE) endfunction() function(jucer_export_target exporter) if(exporter STREQUAL "Xcode (MacOSX)") set(exporter "Xcode (macOS)") endif() if(NOT exporter IN_LIST Reprojucer_supported_exporters) message(FATAL_ERROR "Unsupported exporter: ${exporter}\n" "Supported exporters: ${Reprojucer_supported_exporters}" ) endif() list(APPEND JUCER_PROJECT_EXPORT_TARGETS "${exporter}") set(JUCER_PROJECT_EXPORT_TARGETS "${JUCER_PROJECT_EXPORT_TARGETS}" PARENT_SCOPE) list(FIND Reprojucer_supported_exporters "${exporter}" exporter_index) list(GET Reprojucer_supported_exporters_conditions ${exporter_index} condition) if(NOT (${condition})) return() endif() set(single_value_keywords "TARGET_PROJECT_FOLDER" "ICON_SMALL" "ICON_LARGE") set(multi_value_keywords "EXTRA_PREPROCESSOR_DEFINITIONS" "EXTRA_COMPILER_FLAGS" "EXTRA_LINKER_FLAGS" "EXTERNAL_LIBRARIES_TO_LINK" ) if(exporter STREQUAL "Xcode (macOS)" OR exporter STREQUAL "Xcode (iOS)") list(APPEND single_value_keywords "USE_LEGACY_BUILD_SYSTEM" "MICROPHONE_ACCESS" "MICROPHONE_ACCESS_TEXT" "CAMERA_ACCESS" "CAMERA_ACCESS_TEXT" "BLUETOOTH_ACCESS" "BLUETOOTH_ACCESS_TEXT" "IN_APP_PURCHASES_CAPABILITY" "PUSH_NOTIFICATIONS_CAPABILITY" "CUSTOM_PLIST" "PLIST_PREPROCESS" "PLIST_PREFIX_HEADER" "SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY" "PREBUILD_SHELL_SCRIPT" "POSTBUILD_SHELL_SCRIPT" "EXPORTER_BUNDLE_IDENTIFIER" "DEVELOPMENT_TEAM_ID" "KEEP_CUSTOM_XCODE_SCHEMES" "USE_HEADERMAP" ) list(APPEND multi_value_keywords "CUSTOM_XCODE_RESOURCE_FOLDERS" "EXTRA_SYSTEM_FRAMEWORKS" "EXTRA_FRAMEWORKS" "FRAMEWORK_SEARCH_PATHS" "EXTRA_CUSTOM_FRAMEWORKS" "EMBEDDED_FRAMEWORKS" "XCODE_SUBPROJECTS" ) if(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") list(APPEND single_value_keywords "ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION") endif() endif() if(exporter STREQUAL "Xcode (macOS)") list(APPEND single_value_keywords "VST3_SDK_FOLDER" "AAX_SDK_FOLDER" "RTAS_SDK_FOLDER" "USE_APP_SANDBOX" "APP_SANDBOX_INHERITANCE" "USE_HARDENED_RUNTIME" "SEND_APPLE_EVENTS" "SEND_APPLE_EVENTS_TEXT" ) list(APPEND multi_value_keywords "VALID_ARCHITECTURES" "APP_SANDBOX_OPTIONS" "HARDENED_RUNTIME_OPTIONS" ) if(JUCER_PROJECT_TYPE STREQUAL "GUI Application") list(APPEND multi_value_keywords "DOCUMENT_FILE_EXTENSIONS") endif() endif() if(exporter STREQUAL "Xcode (iOS)") list(APPEND single_value_keywords "CUSTOM_XCASSETS_FOLDER" "CUSTOM_LAUNCH_STORYBOARD" "DEVICE_FAMILY" "FILE_SHARING_ENABLED" "SUPPORT_DOCUMENT_BROWSER" "STATUS_BAR_HIDDEN" "REQUIRES_FULL_SCREEN" "CONTENT_SHARING" "AUDIO_BACKGROUND_CAPABILITY" "BLUETOOTH_MIDI_BACKGROUND_CAPABILITY" "APP_GROUPS_CAPABILITY" "ICLOUD_PERMISSIONS" ) list(APPEND multi_value_keywords "IPHONE_SCREEN_ORIENTATION" "IPAD_SCREEN_ORIENTATION" "APP_GROUP_ID" ) else() list(APPEND single_value_keywords "VST_LEGACY_SDK_FOLDER" "VST_SDK_FOLDER") endif() if(exporter MATCHES "^Visual Studio 20(22|1[9753])$") list(APPEND single_value_keywords "VST3_SDK_FOLDER" "AAX_SDK_FOLDER" "RTAS_SDK_FOLDER" "MANIFEST_FILE" "PLATFORM_TOOLSET" "USE_IPP_LIBRARY" "USE_IPP_LIBRARY_ONE_API" "USE_MKL_LIBRARY_ONE_API" "WINDOWS_TARGET_PLATFORM" ) if(exporter STREQUAL "Visual Studio 2017") list(APPEND single_value_keywords "CXX_STANDARD_TO_USE") endif() else() list(APPEND single_value_keywords "GNU_COMPILER_EXTENSIONS") endif() if(exporter STREQUAL "Linux Makefile") list(APPEND single_value_keywords "CXX_STANDARD_TO_USE") list(APPEND multi_value_keywords "PKGCONFIG_LIBRARIES") endif() if(exporter STREQUAL "Code::Blocks (Windows)") list(APPEND single_value_keywords "TARGET_PLATFORM") endif() set(compiler_flags_for__prefixed_keywords "") foreach(argument IN LISTS ARGN) if(argument MATCHES "^COMPILER_FLAGS_FOR_([A-Za-z0-9_]+)$") list(APPEND compiler_flags_for__prefixed_keywords "${argument}") list(APPEND single_value_keywords "${argument}") endif() endforeach() _FRUT_parse_arguments("${single_value_keywords}" "${multi_value_keywords}" "${ARGN}") if(DEFINED _TARGET_PROJECT_FOLDER) file(TO_CMAKE_PATH "${_TARGET_PROJECT_FOLDER}" project_folder) _FRUT_abs_path_based_on_jucer_project_dir(project_folder "${project_folder}") set(JUCER_TARGET_PROJECT_FOLDER "${project_folder}" PARENT_SCOPE) endif() if(DEFINED _VST_LEGACY_SDK_FOLDER) file(TO_CMAKE_PATH "${_VST_LEGACY_SDK_FOLDER}" sdk_folder) _FRUT_abs_path_based_on_jucer_project_dir(sdk_folder "${sdk_folder}") set(JUCER_VST_LEGACY_SDK_FOLDER "${sdk_folder}" PARENT_SCOPE) endif() if(DEFINED _VST_SDK_FOLDER) file(TO_CMAKE_PATH "${_VST_SDK_FOLDER}" sdk_folder) _FRUT_abs_path_based_on_jucer_project_dir(sdk_folder "${sdk_folder}") set(JUCER_VST_SDK_FOLDER "${sdk_folder}" PARENT_SCOPE) endif() if(DEFINED _VST3_SDK_FOLDER) file(TO_CMAKE_PATH "${_VST3_SDK_FOLDER}" sdk_folder) _FRUT_abs_path_based_on_jucer_project_dir(sdk_folder "${sdk_folder}") set(JUCER_VST3_SDK_FOLDER "${sdk_folder}" PARENT_SCOPE) endif() if(DEFINED _AAX_SDK_FOLDER) file(TO_CMAKE_PATH "${_AAX_SDK_FOLDER}" sdk_folder) _FRUT_abs_path_based_on_jucer_project_dir(sdk_folder "${sdk_folder}") set(JUCER_AAX_SDK_FOLDER "${sdk_folder}" PARENT_SCOPE) endif() if(DEFINED _RTAS_SDK_FOLDER) file(TO_CMAKE_PATH "${_RTAS_SDK_FOLDER}" sdk_folder) _FRUT_abs_path_based_on_jucer_project_dir(sdk_folder "${sdk_folder}") set(JUCER_RTAS_SDK_FOLDER "${sdk_folder}" PARENT_SCOPE) endif() if(DEFINED _EXTRA_PREPROCESSOR_DEFINITIONS) set(JUCER_EXTRA_PREPROCESSOR_DEFINITIONS "${_EXTRA_PREPROCESSOR_DEFINITIONS}" PARENT_SCOPE ) endif() if(DEFINED _EXTRA_COMPILER_FLAGS) set(JUCER_EXTRA_COMPILER_FLAGS "${_EXTRA_COMPILER_FLAGS}" PARENT_SCOPE) endif() foreach(keyword IN LISTS compiler_flags_for__prefixed_keywords) if(DEFINED _${keyword}) set(JUCER_${keyword} "${_${keyword}}" PARENT_SCOPE) endif() endforeach() if(DEFINED _EXTRA_LINKER_FLAGS) set(JUCER_EXTRA_LINKER_FLAGS "${_EXTRA_LINKER_FLAGS}" PARENT_SCOPE) endif() if(DEFINED _EXTERNAL_LIBRARIES_TO_LINK) set(JUCER_EXTERNAL_LIBRARIES_TO_LINK "${_EXTERNAL_LIBRARIES_TO_LINK}" PARENT_SCOPE) endif() if(DEFINED _GNU_COMPILER_EXTENSIONS) set(JUCER_GNU_COMPILER_EXTENSIONS "${_GNU_COMPILER_EXTENSIONS}" PARENT_SCOPE) endif() if(DEFINED _ICON_SMALL) if(NOT _ICON_SMALL STREQUAL "") _FRUT_abs_path_based_on_jucer_project_dir(small_icon "${_ICON_SMALL}") if(NOT EXISTS "${small_icon}") message(FATAL_ERROR "No such file (ICON_SMALL): \"${_ICON_SMALL}\" (\"${small_icon}\")" ) endif() set(JUCER_SMALL_ICON "${small_icon}" PARENT_SCOPE) endif() endif() if(DEFINED _ICON_LARGE) if(NOT _ICON_LARGE STREQUAL "") _FRUT_abs_path_based_on_jucer_project_dir(large_icon "${_ICON_LARGE}") if(NOT EXISTS "${large_icon}") message(FATAL_ERROR "No such file (ICON_LARGE): \"${_ICON_LARGE}\" (\"${large_icon}\")" ) endif() set(JUCER_LARGE_ICON "${large_icon}" PARENT_SCOPE) endif() endif() if(DEFINED _CUSTOM_XCASSETS_FOLDER) set(JUCER_CUSTOM_XCASSETS_FOLDER "${_CUSTOM_XCASSETS_FOLDER}" PARENT_SCOPE) endif() if(DEFINED _CUSTOM_LAUNCH_STORYBOARD) _FRUT_abs_path_based_on_jucer_project_dir(storyboard "${_CUSTOM_LAUNCH_STORYBOARD}") if(NOT EXISTS "${storyboard}") message(FATAL_ERROR "No such file (CUSTOM_LAUNCH_STORYBOARD):" " \"${_CUSTOM_LAUNCH_STORYBOARD}\" (\"${storyboard}\")" ) endif() set(JUCER_CUSTOM_LAUNCH_STORYBOARD "${storyboard}" PARENT_SCOPE) endif() if(DEFINED _CUSTOM_XCODE_RESOURCE_FOLDERS) set(resource_folders "") foreach(folder IN LISTS _CUSTOM_XCODE_RESOURCE_FOLDERS) _FRUT_abs_path_based_on_jucer_project_dir(abs_folder "${folder}") if(NOT IS_DIRECTORY "${abs_folder}") message(FATAL_ERROR "No such folder (CUSTOM_XCODE_RESOURCE_FOLDERS):" " \"${folder}\" (\"${abs_folder}\")" ) endif() list(APPEND resource_folders "${abs_folder}") endforeach() set(JUCER_CUSTOM_XCODE_RESOURCE_FOLDERS "${resource_folders}" PARENT_SCOPE) endif() if(DEFINED _ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION) set(JUCER_ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION "${_ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION}" PARENT_SCOPE ) endif() if(DEFINED _DEVICE_FAMILY) if(_DEVICE_FAMILY STREQUAL "iPhone") set(JUCER_DEVICE_FAMILY "1" PARENT_SCOPE) elseif(_DEVICE_FAMILY STREQUAL "iPad") set(JUCER_DEVICE_FAMILY "2" PARENT_SCOPE) elseif(_DEVICE_FAMILY STREQUAL "Universal") set(JUCER_DEVICE_FAMILY "1,2" PARENT_SCOPE) else() message(FATAL_ERROR "Unsupported value for DEVICE_FAMILY: \"${_DEVICE_FAMILY}\"") endif() endif() if(DEFINED _IPHONE_SCREEN_ORIENTATION) set(screen_orientation "${_IPHONE_SCREEN_ORIENTATION}") if(screen_orientation STREQUAL "Portrait and Landscape") set(JUCER_IPHONE_SCREEN_ORIENTATIONS "UIInterfaceOrientationPortrait" "UIInterfaceOrientationLandscapeLeft" "UIInterfaceOrientationLandscapeRight" PARENT_SCOPE ) elseif(screen_orientation STREQUAL "Portrait") set(JUCER_IPHONE_SCREEN_ORIENTATIONS "UIInterfaceOrientationPortrait" PARENT_SCOPE) elseif(screen_orientation STREQUAL "Landscape") set(JUCER_IPHONE_SCREEN_ORIENTATIONS "UIInterfaceOrientationLandscapeLeft" "UIInterfaceOrientationLandscapeRight" PARENT_SCOPE ) else() set(screen_orientations "") foreach(item IN LISTS screen_orientation) if(item STREQUAL "Portrait") list(APPEND screen_orientations "UIInterfaceOrientationPortrait") elseif(item STREQUAL "Portrait Upside Down") list(APPEND screen_orientations "UIInterfaceOrientationPortraitUpsideDown") elseif(item STREQUAL "Landscape Left") list(APPEND screen_orientations "UIInterfaceOrientationLandscapeLeft") elseif(item STREQUAL "Landscape Right") list(APPEND screen_orientations "UIInterfaceOrientationLandscapeRight") else() message(FATAL_ERROR "Unsupported value for IPHONE_SCREEN_ORIENTATION: \"${item}\"" ) endif() endforeach() set(JUCER_IPHONE_SCREEN_ORIENTATIONS "${screen_orientations}" PARENT_SCOPE) endif() endif() if(DEFINED _IPAD_SCREEN_ORIENTATION) set(screen_orientation "${_IPAD_SCREEN_ORIENTATION}") if(screen_orientation STREQUAL "Portrait and Landscape") set(JUCER_IPAD_SCREEN_ORIENTATIONS "UIInterfaceOrientationPortrait" "UIInterfaceOrientationLandscapeLeft" "UIInterfaceOrientationLandscapeRight" PARENT_SCOPE ) elseif(screen_orientation STREQUAL "Portrait") set(JUCER_IPAD_SCREEN_ORIENTATIONS "UIInterfaceOrientationPortrait" PARENT_SCOPE) elseif(screen_orientation STREQUAL "Landscape") set(JUCER_IPAD_SCREEN_ORIENTATIONS "UIInterfaceOrientationLandscapeLeft" "UIInterfaceOrientationLandscapeRight" PARENT_SCOPE ) else() set(screen_orientations "") foreach(item IN LISTS screen_orientation) if(item STREQUAL "Portrait") list(APPEND screen_orientations "UIInterfaceOrientationPortrait") elseif(item STREQUAL "Portrait Upside Down") list(APPEND screen_orientations "UIInterfaceOrientationPortraitUpsideDown") elseif(item STREQUAL "Landscape Left") list(APPEND screen_orientations "UIInterfaceOrientationLandscapeLeft") elseif(item STREQUAL "Landscape Right") list(APPEND screen_orientations "UIInterfaceOrientationLandscapeRight") else() message(FATAL_ERROR "Unsupported value for IPAD_SCREEN_ORIENTATION: \"${item}\"" ) endif() endforeach() set(JUCER_IPAD_SCREEN_ORIENTATIONS "${screen_orientations}" PARENT_SCOPE) endif() endif() if(DEFINED _FILE_SHARING_ENABLED) set(JUCER_FILE_SHARING_ENABLED "${_FILE_SHARING_ENABLED}" PARENT_SCOPE) endif() if(DEFINED _SUPPORT_DOCUMENT_BROWSER) set(JUCER_SUPPORT_DOCUMENT_BROWSER "${_SUPPORT_DOCUMENT_BROWSER}" PARENT_SCOPE) endif() if(DEFINED _STATUS_BAR_HIDDEN) set(JUCER_STATUS_BAR_HIDDEN "${_STATUS_BAR_HIDDEN}" PARENT_SCOPE) endif() if(DEFINED _REQUIRES_FULL_SCREEN) set(JUCER_REQUIRES_FULL_SCREEN "${_REQUIRES_FULL_SCREEN}" PARENT_SCOPE) endif() if(DEFINED _DOCUMENT_FILE_EXTENSIONS) set(JUCER_DOCUMENT_FILE_EXTENSIONS "${_DOCUMENT_FILE_EXTENSIONS}" PARENT_SCOPE) endif() if(DEFINED _USE_LEGACY_BUILD_SYSTEM) if(CMAKE_GENERATOR STREQUAL "Xcode") _FRUT_warn_about_unsupported_setting( "USE_LEGACY_BUILD_SYSTEM" "Use Legacy Build System" 738 ) endif() endif() if(DEFINED _VALID_ARCHITECTURES) if(NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "VALID_ARCHITECTURES is only supported when using the Xcode" " generator. You can call `cmake -G Xcode` to do so." ) endif() set(JUCER_VALID_ARCHITECTURES "${_VALID_ARCHITECTURES}" PARENT_SCOPE) endif() if(DEFINED _USE_APP_SANDBOX) if(_USE_APP_SANDBOX AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "USE_APP_SANDBOX is only supported when using the Xcode generator." " You should call `cmake -G Xcode`." ) endif() set(JUCER_USE_APP_SANDBOX "${_USE_APP_SANDBOX}" PARENT_SCOPE) endif() if(DEFINED _APP_SANDBOX_INHERITANCE) if(_APP_SANDBOX_INHERITANCE AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "APP_SANDBOX_INHERITANCE is only supported when using the Xcode" " generator. You should call `cmake -G Xcode`." ) endif() set(JUCER_APP_SANDBOX_INHERITANCE "${_APP_SANDBOX_INHERITANCE}" PARENT_SCOPE) endif() if(DEFINED _APP_SANDBOX_OPTIONS) set(projucer_strings "Network: Incoming Connections (Server)" "Network: Outgoing Connections (Client)" "Hardware: Camera" "Hardware: Microphone" "Hardware: USB" "Hardware: Printing" "Hardware: Bluetooth" "App Data: Contacts" "App Data: Location" "App Data: Calendar" "File Access: User Selected File (Read Only)" "File Access: User Selected File (Read/Write)" "File Access: Downloads Folder (Read Only)" "File Access: Downloads Folder (Read/Write)" "File Access: Pictures Folder (Read Only)" "File Access: Pictures Folder (Read/Write)" "File Access: Music Folder (Read Only)" "File Access: Music Folder (Read/Write)" "File Access: Movies Folder (Read Only)" "File Access: Movies Folder (Read/Write)" "Temporary Exception: Audio Unit Hosting" "Temporary Exception: Global Mach Service" "Temporary Exception: Global Mach Service Dynamic Registration" "Temporary Exception: Home Directory File Access (Read Only)" "Temporary Exception: Home Directory File Access (Read/Write)" "Temporary Exception: Absolute Path File Access (Read Only)" "Temporary Exception: Absolute Path File Access (Read/Write)" "Temporary Exception: IOKit User Client Class" "Temporary Exception: Shared Preference Domain (Read Only)" "Temporary Exception: Shared Preference Domain (Read/Write)" ) set(entitlement_keys "com.apple.security.network.server" "com.apple.security.network.client" "com.apple.security.device.camera" "com.apple.security.device.microphone" "com.apple.security.device.usb" "com.apple.security.print" "com.apple.security.device.bluetooth" "com.apple.security.personal-information.addressbook" "com.apple.security.personal-information.location" "com.apple.security.personal-information.calendars" "com.apple.security.files.user-selected.read-only" "com.apple.security.files.user-selected.read-write" "com.apple.security.files.downloads.read-only" "com.apple.security.files.downloads.read-write" "com.apple.security.files.pictures.read-only" "com.apple.security.files.pictures.read-write" "com.apple.security.assets.music.read-only" "com.apple.security.assets.music.read-write" "com.apple.security.assets.movies.read-only" "com.apple.security.assets.movies.read-write" "com.apple.security.temporary-exception.audio-unit-host" "com.apple.security.temporary-exception.mach-lookup.global-name" "com.apple.security.temporary-exception.mach-register.global-name" "com.apple.security.temporary-exception.files.home-relative-path.read-only" "com.apple.security.temporary-exception.files.home-relative-path.read-write" "com.apple.security.temporary-exception.files.absolute-path.read-only" "com.apple.security.temporary-exception.files.absolute-path.read-write" "com.apple.security.temporary-exception.iokit-user-client-class" "com.apple.security.temporary-exception.shared-preference.read-only" "com.apple.security.temporary-exception.shared-preference.read-write" ) set(app_sandbox_options "") foreach(option_string IN LISTS _APP_SANDBOX_OPTIONS) list(FIND projucer_strings "${option_string}" option_index) if(option_index EQUAL -1) message(FATAL_ERROR "Unsupported value for APP_SANDBOX_OPTIONS: \"${option_string}\"" ) endif() list(GET entitlement_keys ${option_index} entitlement_key) list(APPEND app_sandbox_options "${entitlement_key}") endforeach() list(SORT app_sandbox_options) set(JUCER_APP_SANDBOX_OPTIONS "${app_sandbox_options}" PARENT_SCOPE) endif() if(DEFINED _USE_HARDENED_RUNTIME) if(_USE_HARDENED_RUNTIME AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "USE_HARDENED_RUNTIME is only supported when using the Xcode" " generator. You should call `cmake -G Xcode`." ) endif() set(JUCER_USE_HARDENED_RUNTIME "${_USE_HARDENED_RUNTIME}" PARENT_SCOPE) endif() if(DEFINED _HARDENED_RUNTIME_OPTIONS) set(projucer_strings "Runtime Exceptions: Allow Execution of JIT-compiled Code" "Runtime Exceptions: Allow Unsigned Executable Memory" "Runtime Exceptions: Allow DYLD Environment Variables" "Runtime Exceptions: Disable Library Validation" "Runtime Exceptions: Disable Executable Memory Protection" "Runtime Exceptions: Debugging Tool" "Resource Access: Audio Input" "Resource Access: Camera" "Resource Access: Location" "Resource Access: Address Book" "Resource Access: Calendar" "Resource Access: Photos Library" "Resource Access: Apple Events" ) set(projucer_5_4_3_strings "Allow Execution of JIT-compiled Code" "Allow Unsigned Executable Memory" "Allow DYLD Environment Variables" "Disable Library Validation" "Disable Executable Memory Protection" "Debugging Tool" "Audio Input" "Camera" "Location" "Address Book" "Calendar" "Photos Library" "Apple Events" ) set(entitlement_keys "com.apple.security.cs.allow-jit" "com.apple.security.cs.allow-unsigned-executable-memory" "com.apple.security.cs.allow-dyld-environment-variables" "com.apple.security.cs.disable-library-validation" "com.apple.security.cs.disable-executable-page-protection" "com.apple.security.cs.debugger" "com.apple.security.device.audio-input" "com.apple.security.device.camera" "com.apple.security.personal-information.location" "com.apple.security.personal-information.addressbook" "com.apple.security.personal-information.calendars" "com.apple.security.personal-information.photos-library" "com.apple.security.automation.apple-events" ) set(hardened_runtime_options "") foreach(option_string IN LISTS _HARDENED_RUNTIME_OPTIONS) list(FIND projucer_strings "${option_string}" option_index) if(option_index EQUAL -1) list(FIND projucer_5_4_3_strings "${option_string}" option_index) if(option_index EQUAL -1) message(FATAL_ERROR "Unsupported value for HARDENED_RUNTIME_OPTIONS: \"${option_string}\"" ) endif() endif() list(GET entitlement_keys ${option_index} entitlement_key) list(APPEND hardened_runtime_options "${entitlement_key}") endforeach() list(SORT hardened_runtime_options) set(JUCER_HARDENED_RUNTIME_OPTIONS "${hardened_runtime_options}" PARENT_SCOPE) endif() if(DEFINED _MICROPHONE_ACCESS) set(JUCER_MICROPHONE_ACCESS "${_MICROPHONE_ACCESS}" PARENT_SCOPE) endif() if(DEFINED _MICROPHONE_ACCESS_TEXT) set(JUCER_MICROPHONE_ACCESS_TEXT "${_MICROPHONE_ACCESS_TEXT}" PARENT_SCOPE) endif() if(DEFINED _CAMERA_ACCESS) set(JUCER_CAMERA_ACCESS "${_CAMERA_ACCESS}" PARENT_SCOPE) endif() if(DEFINED _CAMERA_ACCESS_TEXT) set(JUCER_CAMERA_ACCESS_TEXT "${_CAMERA_ACCESS_TEXT}" PARENT_SCOPE) endif() if(DEFINED _BLUETOOTH_ACCESS) set(JUCER_BLUETOOTH_ACCESS "${_BLUETOOTH_ACCESS}" PARENT_SCOPE) endif() if(DEFINED _BLUETOOTH_ACCESS_TEXT) set(JUCER_BLUETOOTH_ACCESS_TEXT "${_BLUETOOTH_ACCESS_TEXT}" PARENT_SCOPE) endif() if(DEFINED _SEND_APPLE_EVENTS) set(JUCER_SEND_APPLE_EVENTS "${_SEND_APPLE_EVENTS}" PARENT_SCOPE) endif() if(DEFINED _SEND_APPLE_EVENTS_TEXT) set(JUCER_SEND_APPLE_EVENTS_TEXT "${_SEND_APPLE_EVENTS_TEXT}" PARENT_SCOPE) endif() if(DEFINED _IN_APP_PURCHASES_CAPABILITY AND _IN_APP_PURCHASES_CAPABILITY) set(JUCER_IN_APP_PURCHASES_CAPABILITY "${_IN_APP_PURCHASES_CAPABILITY}" PARENT_SCOPE) endif() if(DEFINED _PUSH_NOTIFICATIONS_CAPABILITY) if(_PUSH_NOTIFICATIONS_CAPABILITY AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "PUSH_NOTIFICATIONS_CAPABILITY is only supported when using the" " Xcode generator. You should call `cmake -G Xcode`." ) endif() set(JUCER_PUSH_NOTIFICATIONS_CAPABILITY "${_PUSH_NOTIFICATIONS_CAPABILITY}" PARENT_SCOPE ) endif() if(DEFINED _CONTENT_SHARING) set(JUCER_CONTENT_SHARING "${_CONTENT_SHARING}" PARENT_SCOPE) endif() if(DEFINED _AUDIO_BACKGROUND_CAPABILITY) set(JUCER_AUDIO_BACKGROUND_CAPABILITY "${_AUDIO_BACKGROUND_CAPABILITY}" PARENT_SCOPE) endif() if(DEFINED _BLUETOOTH_MIDI_BACKGROUND_CAPABILITY) set(JUCER_BLUETOOTH_MIDI_BACKGROUND_CAPABILITY "${_BLUETOOTH_MIDI_BACKGROUND_CAPABILITY}" PARENT_SCOPE ) endif() if(DEFINED _APP_GROUPS_CAPABILITY) set(JUCER_APP_GROUPS_CAPABILITY "${_APP_GROUPS_CAPABILITY}" PARENT_SCOPE) endif() if(DEFINED _ICLOUD_PERMISSIONS) set(JUCER_ICLOUD_PERMISSIONS "${_ICLOUD_PERMISSIONS}" PARENT_SCOPE) endif() if(DEFINED _CUSTOM_PLIST) set(JUCER_CUSTOM_PLIST "${_CUSTOM_PLIST}" PARENT_SCOPE) endif() if(DEFINED _PLIST_PREPROCESS AND _PLIST_PREPROCESS) if(_PLIST_PREPROCESS AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "PLIST_PREPROCESS is only supported when using the Xcode generator." " You should call `cmake -G Xcode`." ) endif() set(JUCER_PLIST_PREPROCESS "${_PLIST_PREPROCESS}" PARENT_SCOPE) endif() if(DEFINED _PLIST_PREFIX_HEADER) _FRUT_abs_path_based_on_jucer_project_dir(prefix_header "${_PLIST_PREFIX_HEADER}") if(NOT EXISTS "${prefix_header}") message(FATAL_ERROR "No such file (PLIST_PREFIX_HEADER):" " \"${_PLIST_PREFIX_HEADER}\" (\"${prefix_header}\")" ) endif() set(JUCER_PLIST_PREFIX_HEADER "${prefix_header}" PARENT_SCOPE) endif() if(DEFINED _SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY) set(JUCER_SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY "${_SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY}" PARENT_SCOPE ) endif() if(DEFINED _EXTRA_SYSTEM_FRAMEWORKS) set(JUCER_EXTRA_SYSTEM_FRAMEWORKS "${_EXTRA_SYSTEM_FRAMEWORKS}" PARENT_SCOPE) endif() if(DEFINED _EXTRA_FRAMEWORKS) set(JUCER_EXTRA_FRAMEWORKS "${_EXTRA_FRAMEWORKS}" PARENT_SCOPE) endif() if(DEFINED _FRAMEWORK_SEARCH_PATHS) set(JUCER_FRAMEWORK_SEARCH_PATHS "${_FRAMEWORK_SEARCH_PATHS}" PARENT_SCOPE) endif() if(DEFINED _EXTRA_CUSTOM_FRAMEWORKS) set(JUCER_EXTRA_CUSTOM_FRAMEWORKS "${_EXTRA_CUSTOM_FRAMEWORKS}" PARENT_SCOPE) endif() if(DEFINED _EMBEDDED_FRAMEWORKS) _FRUT_warn_about_unsupported_setting("EMBEDDED_FRAMEWORKS" "Embedded Frameworks" 443) endif() if(DEFINED _XCODE_SUBPROJECTS) _FRUT_warn_about_unsupported_setting("XCODE_SUBPROJECTS" "Xcode Subprojects" 445) endif() if(DEFINED _PREBUILD_SHELL_SCRIPT) set(script_content "${_PREBUILD_SHELL_SCRIPT}") configure_file("${Reprojucer_data_DIR}/script.in" "prebuild.sh" @ONLY) set(JUCER_PREBUILD_SHELL_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/prebuild.sh" PARENT_SCOPE ) endif() if(DEFINED _POSTBUILD_SHELL_SCRIPT) set(script_content "${_POSTBUILD_SHELL_SCRIPT}") configure_file("${Reprojucer_data_DIR}/script.in" "postbuild.sh" @ONLY) set(JUCER_POSTBUILD_SHELL_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/postbuild.sh" PARENT_SCOPE ) endif() if(DEFINED _EXPORTER_BUNDLE_IDENTIFIER) set(JUCER_EXPORTER_BUNDLE_IDENTIFIER "${_EXPORTER_BUNDLE_IDENTIFIER}" PARENT_SCOPE) endif() if(DEFINED _DEVELOPMENT_TEAM_ID) set(JUCER_DEVELOPMENT_TEAM_ID "${_DEVELOPMENT_TEAM_ID}" PARENT_SCOPE) endif() if(DEFINED _APP_GROUP_ID) set(JUCER_APP_GROUP_ID "${_APP_GROUP_ID}" PARENT_SCOPE) endif() if(DEFINED _KEEP_CUSTOM_XCODE_SCHEMES) message(WARNING "KEEP_CUSTOM_XCODE_SCHEMES is ignored. Reprojucer.cmake won't create" " any Xcode schemes, so it won't delete any either." ) endif() if(DEFINED _USE_HEADERMAP) if(_USE_HEADERMAP AND NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "USE_HEADERMAP is only supported when using the Xcode generator." " You should call `cmake -G Xcode`." ) endif() set(JUCER_USE_HEADERMAP "${_USE_HEADERMAP}" PARENT_SCOPE) endif() if(DEFINED _MANIFEST_FILE) _FRUT_abs_path_based_on_jucer_project_dir(manifest_file "${_MANIFEST_FILE}") if(NOT EXISTS "${manifest_file}") message(FATAL_ERROR "No such file (MANIFEST_FILE):" " \"${_MANIFEST_FILE}\" (\"${manifest_file}\")" ) endif() set(JUCER_MANIFEST_FILE "${manifest_file}" PARENT_SCOPE) endif() if(DEFINED _PLATFORM_TOOLSET) set(toolset "${_PLATFORM_TOOLSET}") if((exporter STREQUAL "Visual Studio 2022" AND toolset MATCHES "^(v140(_xp)?|v141(_xp)?|v142|v143)$") OR (exporter STREQUAL "Visual Studio 2019" AND toolset MATCHES "^(v140(_xp)?|v141(_xp)?|v142)$") OR (exporter STREQUAL "Visual Studio 2017" AND toolset MATCHES "^(v140(_xp)?|v141(_xp)?)$") OR (exporter STREQUAL "Visual Studio 2015" AND toolset MATCHES "^(v140(_xp)?|CTP_Nov2013)$") OR (exporter STREQUAL "Visual Studio 2013" AND toolset MATCHES "^(v120(_xp)?|Windows7|CTP_Nov2013)$")) if(NOT toolset STREQUAL "${CMAKE_VS_PLATFORM_TOOLSET}") message(FATAL_ERROR "You must call `cmake -T ${toolset}` in order to build with" " the toolset \"${toolset}\"." ) endif() elseif(NOT toolset STREQUAL "(default)") message(FATAL_ERROR "Unsupported value for PLATFORM_TOOLSET: \"${toolset}\"") endif() endif() if(DEFINED _USE_IPP_LIBRARY) set(ipp_library "${_USE_IPP_LIBRARY}") set(ipp_library_values "Yes (Default Mode)" "Yes (Default Linking)" "Multi-Threaded Static Library" "Single-Threaded Static Library" "Multi-Threaded DLL" "Single-Threaded DLL" ) if(ipp_library IN_LIST ipp_library_values) set(JUCER_USE_IPP_LIBRARY "${ipp_library}" PARENT_SCOPE) elseif(NOT ipp_library STREQUAL "No") message(FATAL_ERROR "Unsupported value for USE_IPP_LIBRARY: \"${ipp_library}\"") endif() endif() if(DEFINED _USE_IPP_LIBRARY_ONE_API) _FRUT_warn_about_unsupported_setting( "USE_IPP_LIBRARY_ONE_API" "Use IPP Library (oneAPI)" 739 ) endif() if(DEFINED _USE_MKL_LIBRARY_ONE_API) _FRUT_warn_about_unsupported_setting( "USE_MKL_LIBRARY_ONE_API" "Use MKL Library (oneAPI)" 740 ) endif() if(DEFINED _WINDOWS_TARGET_PLATFORM) set(platform "${_WINDOWS_TARGET_PLATFORM}") if(NOT platform STREQUAL CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION" " (${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}) doesn't match" " WINDOWS_TARGET_PLATFORM (${platform})." ) endif() endif() if(DEFINED _CXX_STANDARD_TO_USE AND exporter STREQUAL "Visual Studio 2017") set(standard "${_CXX_STANDARD_TO_USE}") if(standard STREQUAL "C++14") set(JUCER_CXX_STANDARD_TO_USE "14" PARENT_SCOPE) elseif(standard STREQUAL "Latest C++ Standard") set(JUCER_CXX_STANDARD_TO_USE "latest" PARENT_SCOPE) elseif(NOT standard STREQUAL "(default)") message(FATAL_ERROR "Unsupported value for CXX_STANDARD_TO_USE: \"${standard}\"") endif() endif() if(DEFINED _CXX_STANDARD_TO_USE AND exporter STREQUAL "Linux Makefile") set(standard "${_CXX_STANDARD_TO_USE}") if(standard MATCHES "^C\\+\\+(03|11|14)$") set(JUCER_CXX_STANDARD_TO_USE "${standard}" PARENT_SCOPE) else() message(FATAL_ERROR "Unsupported value for CXX_STANDARD_TO_USE: \"${standard}\"") endif() endif() if(DEFINED _PKGCONFIG_LIBRARIES) set(JUCER_PKGCONFIG_LIBRARIES "${_PKGCONFIG_LIBRARIES}" PARENT_SCOPE) endif() if(DEFINED _TARGET_PLATFORM) set(target_platform "${_TARGET_PLATFORM}") set(target_platform_values "Default" "Windows NT 4.0" "Windows 2000" "Windows XP" "Windows Server 2003" "Windows Vista" "Windows Server 2008" "Windows 7" "Windows 8" "Windows 8.1" "Windows 10" ) if(NOT target_platform IN_LIST target_platform_values) message(FATAL_ERROR "Unsupported value for TARGET_PLATFORM: \"${target_platform}\"") endif() set(JUCER_TARGET_PLATFORM "${target_platform}" PARENT_SCOPE) endif() endfunction() function(jucer_export_target_configuration exporter NAME_KEYWORD config DEBUG_MODE_KEYWORD is_debug ) if(exporter STREQUAL "Xcode (MacOSX)") set(exporter "Xcode (macOS)") endif() if(NOT exporter IN_LIST Reprojucer_supported_exporters) message(FATAL_ERROR "Unsupported exporter: ${exporter}\n" "Supported exporters: ${Reprojucer_supported_exporters}" ) endif() if(NOT exporter IN_LIST JUCER_PROJECT_EXPORT_TARGETS) message(FATAL_ERROR "You must call jucer_export_target(\"${exporter}\") before" " calling jucer_export_target_configuration(\"${exporter}\")." ) endif() if(NOT NAME_KEYWORD STREQUAL "NAME") message(FATAL_ERROR "Invalid second argument. Expected \"NAME\" keyword, but got" " \"${NAME_KEYWORD}\" instead." ) endif() if(NOT config MATCHES "^[A-Za-z0-9_]+$") _FRUT_make_valid_configuration_name("${config}" valid_config) message(FATAL_ERROR "\"${config}\" is not a valid CMake build configuration name." " Configuration names must match \"^[A-Za-z0-9_]+$\". You can use" " \"${valid_config}\" instead." ) endif() if(NOT DEBUG_MODE_KEYWORD STREQUAL "DEBUG_MODE") message(FATAL_ERROR "Invalid fourth argument. Expected \"DEBUG_MODE\" keyword, but" " got \"${DEBUG_MODE_KEYWORD}\" instead." ) endif() list(FIND Reprojucer_supported_exporters "${exporter}" exporter_index) list(GET Reprojucer_supported_exporters_conditions ${exporter_index} condition) if(NOT (${condition})) return() endif() if(NOT "${config}" IN_LIST JUCER_PROJECT_CONFIGURATIONS) list(APPEND JUCER_PROJECT_CONFIGURATIONS "${config}") set(JUCER_PROJECT_CONFIGURATIONS "${JUCER_PROJECT_CONFIGURATIONS}" PARENT_SCOPE) endif() set(JUCER_CONFIGURATION_IS_DEBUG_${config} "${is_debug}" PARENT_SCOPE) set(single_value_keywords "BINARY_NAME" "BINARY_LOCATION" "OPTIMISATION") set(multi_value_keywords "HEADER_SEARCH_PATHS" "EXTRA_LIBRARY_SEARCH_PATHS" "PREPROCESSOR_DEFINITIONS" "LINK_TIME_OPTIMISATION" ) if(exporter STREQUAL "Xcode (macOS)" OR exporter STREQUAL "Xcode (iOS)") list(APPEND single_value_keywords "USE_PRECOMPILED_HEADER" "PRECOMPILED_HEADER_FILE" "ENABLE_PLUGIN_COPY_STEP" "VST_BINARY_LOCATION" "VST3_BINARY_LOCATION" "AU_BINARY_LOCATION" "RTAS_BINARY_LOCATION" "AAX_BINARY_LOCATION" "UNITY_BINARY_LOCATION" "VST_LEGACY_BINARY_LOCATION" "CXX_LANGUAGE_STANDARD" "CXX_LIBRARY" "CODE_SIGNING_IDENTITY" "RELAX_IEEE_COMPLIANCE" "STRIP_LOCAL_SYMBOLS" ) list(APPEND multi_value_keywords "CUSTOM_XCODE_FLAGS" "PLIST_PREPROCESSOR_DEFINITIONS" ) endif() if(exporter STREQUAL "Xcode (macOS)") list(APPEND single_value_keywords "MACOS_BASE_SDK" "MACOS_BASE_SDK_VERSION" "OSX_BASE_SDK_VERSION" "MACOS_DEPLOYMENT_TARGET" "OSX_DEPLOYMENT_TARGET" "MACOS_ARCHITECTURE" "OSX_ARCHITECTURE" ) endif() if(exporter STREQUAL "Xcode (iOS)") list(APPEND single_value_keywords "IOS_BASE_SDK" "IOS_DEPLOYMENT_TARGET") endif() if(exporter MATCHES "^Visual Studio 20(22|1[9753])$") list(APPEND single_value_keywords "USE_PRECOMPILED_HEADER" "PRECOMPILED_HEADER_FILE" "ENABLE_PLUGIN_COPY_STEP" "VST_BINARY_LOCATION" "VST3_BINARY_LOCATION" "RTAS_BINARY_LOCATION" "AAX_BINARY_LOCATION" "UNITY_BINARY_LOCATION" "VST_LEGACY_BINARY_LOCATION" "DEBUG_INFORMATION_FORMAT" "WARNING_LEVEL" "TREAT_WARNINGS_AS_ERRORS" "RUNTIME_LIBRARY" "WHOLE_PROGRAM_OPTIMISATION" "MULTI_PROCESSOR_COMPILATION" "INCREMENTAL_LINKING" "PREBUILD_COMMAND" "POSTBUILD_COMMAND" "GENERATE_MANIFEST" "CHARACTER_SET" "ARCHITECTURE" "RELAX_IEEE_COMPLIANCE" ) if(NOT is_debug) list(APPEND single_value_keywords "FORCE_GENERATION_OF_DEBUG_SYMBOLS") endif() else() list(APPEND single_value_keywords "ADD_RECOMMENDED_COMPILER_WARNING_FLAGS") endif() if(exporter STREQUAL "Linux Makefile") list(APPEND single_value_keywords "ARCHITECTURE" "ENABLE_PLUGIN_COPY_STEP" "VST3_BINARY_LOCATION" "UNITY_BINARY_LOCATION" "VST_LEGACY_BINARY_LOCATION" ) endif() if(exporter MATCHES "^Code::Blocks \\((Windows|Linux)\\)$") list(APPEND single_value_keywords "ARCHITECTURE") endif() _FRUT_parse_arguments("${single_value_keywords}" "${multi_value_keywords}" "${ARGN}") if(DEFINED _BINARY_NAME) set(JUCER_BINARY_NAME_${config} "${_BINARY_NAME}" PARENT_SCOPE) endif() if(DEFINED _BINARY_LOCATION) get_filename_component(abs_path "${_BINARY_LOCATION}" ABSOLUTE) set(JUCER_BINARY_LOCATION_${config} "${abs_path}" PARENT_SCOPE) endif() if(DEFINED _HEADER_SEARCH_PATHS) set(JUCER_HEADER_SEARCH_PATHS_${config} "${_HEADER_SEARCH_PATHS}" PARENT_SCOPE) endif() if(DEFINED _EXTRA_LIBRARY_SEARCH_PATHS) set(JUCER_EXTRA_LIBRARY_SEARCH_PATHS_${config} "${_EXTRA_LIBRARY_SEARCH_PATHS}" PARENT_SCOPE ) endif() if(DEFINED _PREPROCESSOR_DEFINITIONS) set(JUCER_PREPROCESSOR_DEFINITIONS_${config} "${_PREPROCESSOR_DEFINITIONS}" PARENT_SCOPE ) endif() if(DEFINED _LINK_TIME_OPTIMISATION) set(JUCER_LINK_TIME_OPTIMISATION_${config} "${_LINK_TIME_OPTIMISATION}" PARENT_SCOPE) endif() if(DEFINED _ADD_RECOMMENDED_COMPILER_WARNING_FLAGS) set(kind_text "${_ADD_RECOMMENDED_COMPILER_WARNING_FLAGS}") unset(kind) if(exporter STREQUAL "Xcode (macOS)" OR exporter STREQUAL "Xcode (iOS)") if(kind_text STREQUAL "Enabled") set(kind "LLVM") elseif(kind_text STREQUAL "Disabled") set(kind "") endif() elseif(exporter STREQUAL "Linux Makefile" OR exporter MATCHES "^Code::Blocks \\((Windows|Linux)\\)$") if(kind_text STREQUAL "GCC") set(kind "GCC") elseif(kind_text STREQUAL "GCC 7 and below") set(kind "GCC-7") elseif(kind_text STREQUAL "LLVM") set(kind "LLVM") elseif(kind_text STREQUAL "Disabled") set(kind "") endif() endif() if(NOT DEFINED kind) message(FATAL_ERROR "Unsupported value for ADD_RECOMMENDED_COMPILER_WARNING_FLAGS: \"${kind_text}\"" ) endif() set(JUCER_ADD_RECOMMENDED_COMPILER_WARNING_FLAGS "${kind}" PARENT_SCOPE) endif() if(DEFINED _OPTIMISATION) set(optimisation "${_OPTIMISATION}") if(exporter MATCHES "^Visual Studio 20(22|1[9753])$") if(optimisation STREQUAL "No optimisation") set(optimisation_flag "/Od") elseif(optimisation STREQUAL "Minimise size") set(optimisation_flag "/O1") elseif(optimisation STREQUAL "Maximise speed") set(optimisation_flag "/Ox") else() message(FATAL_ERROR "Unsupported value for OPTIMISATION: \"${optimisation}\"") endif() else() if(optimisation STREQUAL "-O0 (no optimisation)") set(optimisation_flag "-O0") elseif(optimisation STREQUAL "-Os (minimise code size)") set(optimisation_flag "-Os") elseif(optimisation STREQUAL "-O1 (fast)") set(optimisation_flag "-O1") elseif(optimisation STREQUAL "-O2 (faster)") set(optimisation_flag "-O2") elseif(optimisation STREQUAL "-O3 (fastest with safe optimisations)") set(optimisation_flag "-O3") elseif(optimisation STREQUAL "-Ofast (uses aggressive optimisations)") set(optimisation_flag "-Ofast") else() message(FATAL_ERROR "Unsupported value for OPTIMISATION: \"${optimisation}\"") endif() endif() set(JUCER_OPTIMISATION_FLAG_${config} "${optimisation_flag}" PARENT_SCOPE) endif() if(DEFINED _USE_PRECOMPILED_HEADER) _FRUT_warn_about_unsupported_setting( "USE_PRECOMPILED_HEADER" "Use Precompiled Header" 737 ) endif() if(DEFINED _PRECOMPILED_HEADER_FILE) # TODO with USE_PRECOMPILED_HEADER endif() if(DEFINED _ENABLE_PLUGIN_COPY_STEP) set(JUCER_ENABLE_PLUGIN_COPY_STEP_${config} "${_ENABLE_PLUGIN_COPY_STEP}" PARENT_SCOPE ) endif() if(DEFINED _VST_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_VST_BINARY_LOCATION}") set(JUCER_VST_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _VST3_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_VST3_BINARY_LOCATION}") set(JUCER_VST3_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _AU_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_AU_BINARY_LOCATION}") set(JUCER_AU_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _RTAS_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_RTAS_BINARY_LOCATION}") set(JUCER_RTAS_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _AAX_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_AAX_BINARY_LOCATION}") set(JUCER_AAX_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _UNITY_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_UNITY_BINARY_LOCATION}") set(JUCER_UNITY_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _VST_LEGACY_BINARY_LOCATION) _FRUT_sanitize_path_in_user_folder(binary_location "${_VST_LEGACY_BINARY_LOCATION}") set(JUCER_VST_BINARY_LOCATION_${config} "${binary_location}" PARENT_SCOPE) endif() if(DEFINED _MACOS_BASE_SDK) set(JUCER_MACOS_BASE_SDK_${config} "${_MACOS_BASE_SDK}" PARENT_SCOPE) endif() if(DEFINED _MACOS_BASE_SDK_VERSION) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.0)) message(WARNING "MACOS_BASE_SDK_VERSION is deprecated, use MACOS_BASE_SDK instead.") endif() set(version "${_MACOS_BASE_SDK_VERSION}") if(version MATCHES "^10\\.(1[1-6]) SDK$") set(JUCER_MACOS_BASE_SDK_VERSION_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(version MATCHES "^11\\.([0-1]) SDK$") set(JUCER_MACOS_BASE_SDK_VERSION_${config} "11.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(NOT version STREQUAL "Default") message(FATAL_ERROR "Unsupported value for MACOS_BASE_SDK_VERSION: \"${version}\"") endif() endif() if(DEFINED _OSX_BASE_SDK_VERSION) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.0)) message(WARNING "OSX_BASE_SDK_VERSION is deprecated, use MACOS_BASE_SDK instead.") elseif(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.2)) message(WARNING "OSX_BASE_SDK_VERSION is deprecated, use MACOS_BASE_SDK_VERSION" " instead." ) endif() set(version "${_OSX_BASE_SDK_VERSION}") if(version MATCHES "^10\\.([5-6]) SDK$" AND DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2) set(JUCER_OSX_BASE_SDK_VERSION_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(version MATCHES "^10\\.([7-9]|10) SDK$" AND DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.4.4) set(JUCER_OSX_BASE_SDK_VERSION_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(version MATCHES "^10\\.(1[1-6]) SDK$") set(JUCER_OSX_BASE_SDK_VERSION_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(version STREQUAL "11.0 SDK") set(JUCER_OSX_BASE_SDK_VERSION_${config} "11.0" PARENT_SCOPE) elseif(NOT version MATCHES "^(Use )?Default$") message(FATAL_ERROR "Unsupported value for OSX_BASE_SDK_VERSION: \"${version}\"") endif() endif() if(DEFINED _MACOS_DEPLOYMENT_TARGET) set(target "${_MACOS_DEPLOYMENT_TARGET}") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.0) if(target MATCHES "^10\\.([7-9]|1[0-6])$") set(JUCER_MACOS_DEPLOYMENT_TARGET_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(target MATCHES "^11\\.([0-1])$") set(JUCER_MACOS_DEPLOYMENT_TARGET_${config} "11.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(NOT target STREQUAL "Default") message(FATAL_ERROR "Unsupported value for MACOS_DEPLOYMENT_TARGET: \"${target}\"" ) endif() endif() set(JUCER_MACOS_DEPLOYMENT_TARGET_${config} "${target}" PARENT_SCOPE) endif() if(DEFINED _OSX_DEPLOYMENT_TARGET) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.2)) message(WARNING "OSX_DEPLOYMENT_TARGET is deprecated, use MACOS_DEPLOYMENT_TARGET" " instead." ) endif() set(target "${_OSX_DEPLOYMENT_TARGET}") if(target MATCHES "^10\\.([5-6])$" AND DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2) set(JUCER_OSX_DEPLOYMENT_TARGET_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(target MATCHES "^10\\.([7-9]|1[0-6])$") set(JUCER_OSX_DEPLOYMENT_TARGET_${config} "10.${CMAKE_MATCH_1}" PARENT_SCOPE) elseif(target STREQUAL "11.0") set(JUCER_OSX_DEPLOYMENT_TARGET_${config} "11.0" PARENT_SCOPE) elseif(NOT target MATCHES "^(Use )?Default$") message(FATAL_ERROR "Unsupported value for OSX_DEPLOYMENT_TARGET: \"${target}\"") endif() endif() if(DEFINED _MACOS_ARCHITECTURE) set(architecture "${_MACOS_ARCHITECTURE}") unset(macos_architectures) if(architecture STREQUAL "Native architecture of build machine") set(xcode_archs "$(NATIVE_ARCH_ACTUAL)") elseif(architecture STREQUAL "Standard 32-bit") set(macos_architectures "i386") set(xcode_archs "$(ARCHS_STANDARD_32_BIT)") elseif(architecture STREQUAL "Standard 32/64-bit") set(macos_architectures "x86_64" "i386") set(xcode_archs "$(ARCHS_STANDARD_32_64_BIT)") elseif(architecture STREQUAL "Standard 64-bit") set(macos_architectures "x86_64") set(xcode_archs "$(ARCHS_STANDARD_64_BIT)") elseif(NOT architecture STREQUAL "Default") message(FATAL_ERROR "Unsupported value for MACOS_ARCHITECTURE: \"${architecture}\"") endif() if(DEFINED macos_architectures) set(JUCER_MACOS_ARCHITECTURES_${config} "${macos_architectures}" PARENT_SCOPE) endif() set(JUCER_XCODE_ARCHS_${config} "${xcode_archs}" PARENT_SCOPE) endif() if(DEFINED _OSX_ARCHITECTURE) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.2)) message(WARNING "OSX_ARCHITECTURE is deprecated, use MACOS_ARCHITECTURE instead.") endif() set(architecture "${_OSX_ARCHITECTURE}") unset(osx_architectures) if(architecture STREQUAL "Native architecture of build machine") set(xcode_archs "$(NATIVE_ARCH_ACTUAL)") elseif(architecture STREQUAL "Universal Binary (32-bit)") set(osx_architectures "i386") set(xcode_archs "$(ARCHS_STANDARD_32_BIT)") elseif(architecture STREQUAL "Universal Binary (32/64-bit)") set(osx_architectures "x86_64" "i386") set(xcode_archs "$(ARCHS_STANDARD_32_64_BIT)") elseif(architecture STREQUAL "64-bit Intel" OR architecture STREQUAL "Universal Binary (64-bit)") set(osx_architectures "x86_64") set(xcode_archs "$(ARCHS_STANDARD_64_BIT)") elseif(NOT architecture MATCHES "^(Use )?Default$") message(FATAL_ERROR "Unsupported value for OSX_ARCHITECTURE: \"${architecture}\"") endif() if(DEFINED osx_architectures) set(JUCER_OSX_ARCHITECTURES_${config} "${osx_architectures}" PARENT_SCOPE) endif() set(JUCER_XCODE_ARCHS_${config} "${xcode_archs}" PARENT_SCOPE) endif() if(DEFINED _IOS_BASE_SDK) set(JUCER_IOS_BASE_SDK_${config} "${_IOS_BASE_SDK}" PARENT_SCOPE) endif() if(DEFINED _IOS_DEPLOYMENT_TARGET) set(JUCER_IOS_DEPLOYMENT_TARGET_${config} "${_IOS_DEPLOYMENT_TARGET}" PARENT_SCOPE) endif() if(DEFINED _CUSTOM_XCODE_FLAGS) if(NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "CUSTOM_XCODE_FLAGS is only supported when using the Xcode" " generator. You should call `cmake -G Xcode`." ) endif() set(JUCER_CUSTOM_XCODE_FLAGS_${config} "${_CUSTOM_XCODE_FLAGS}" PARENT_SCOPE) endif() if(DEFINED _CXX_LANGUAGE_STANDARD) set(standard "${_CXX_LANGUAGE_STANDARD}") if(standard MATCHES "^(C|GNU)\\+\\+98$" AND DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) set(JUCER_CXX_LANGUAGE_STANDARD_${config} "${standard}" PARENT_SCOPE) elseif(standard MATCHES "^(C|GNU)\\+\\+(11|14)$") set(JUCER_CXX_LANGUAGE_STANDARD_${config} "${standard}" PARENT_SCOPE) elseif(NOT standard STREQUAL "Use Default") message(FATAL_ERROR "Unsupported value for CXX_LANGUAGE_STANDARD: \"${standard}\"") endif() endif() if(DEFINED _CXX_LIBRARY) set(cxx_library "${_CXX_LIBRARY}") if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2)) message(WARNING "The setting \"C++ Library\" was removed in Projucer 5.3.2, so" " CXX_LIBRARY \"${cxx_library}\" will be ignored." ) endif() if(cxx_library STREQUAL "LLVM libc++") set(JUCER_CXX_LIBRARY_${config} "libc++" PARENT_SCOPE) elseif(cxx_library STREQUAL "GNU libstdc++") set(JUCER_CXX_LIBRARY_${config} "libstdc++" PARENT_SCOPE) elseif(NOT cxx_library MATCHES "^(Use )?Default$") message(FATAL_ERROR "Unsupported value for CXX_LIBRARY: \"${cxx_library}\"") endif() endif() if(DEFINED _PLIST_PREPROCESSOR_DEFINITIONS) set(JUCER_PLIST_PREPROCESSOR_DEFINITIONS_${config} "${_PLIST_PREPROCESSOR_DEFINITIONS}" PARENT_SCOPE ) endif() if(DEFINED _CODE_SIGNING_IDENTITY) if(NOT CMAKE_GENERATOR STREQUAL "Xcode") message(WARNING "CODE_SIGNING_IDENTITY is only supported when using the Xcode" " generator. You should call `cmake -G Xcode`." ) endif() set(JUCER_CODE_SIGNING_IDENTITY_${config} "${_CODE_SIGNING_IDENTITY}" PARENT_SCOPE) endif() if(DEFINED _RELAX_IEEE_COMPLIANCE) set(JUCER_RELAX_IEEE_COMPLIANCE_${config} "${_RELAX_IEEE_COMPLIANCE}" PARENT_SCOPE) endif() if(DEFINED _STRIP_LOCAL_SYMBOLS) set(JUCER_STRIP_LOCAL_SYMBOLS_${config} "${_STRIP_LOCAL_SYMBOLS}" PARENT_SCOPE) endif() if(DEFINED _DEBUG_INFORMATION_FORMAT) set(format "${_DEBUG_INFORMATION_FORMAT}") if(format STREQUAL "C7 Compatible (/Z7)") set(format_flag "/Z7") elseif(format STREQUAL "Program Database (/Zi)") set(format_flag "/Zi") elseif(format STREQUAL "Program Database for Edit And Continue (/ZI)") set(format_flag "/ZI") elseif(NOT format STREQUAL "None") message(FATAL_ERROR "Unsupported value for DEBUG_INFORMATION_FORMAT: \"${format}\"") endif() set(JUCER_DEBUG_INFORMATION_FORMAT_FLAG_${config} "${format_flag}" PARENT_SCOPE) endif() if(DEFINED _WARNING_LEVEL) set(warning_level "${_WARNING_LEVEL}") if(warning_level STREQUAL "Low") set(level 2) elseif(warning_level STREQUAL "Medium") set(level 3) elseif(warning_level STREQUAL "High") set(level 4) else() message(FATAL_ERROR "Unsupported value for WARNING_LEVEL: \"${warning_level}\"") endif() set(JUCER_WARNING_LEVEL_FLAG_${config} "/W${level}" PARENT_SCOPE) endif() if(DEFINED _TREAT_WARNINGS_AS_ERRORS) set(JUCER_TREAT_WARNINGS_AS_ERRORS_${config} "${_TREAT_WARNINGS_AS_ERRORS}" PARENT_SCOPE ) endif() if(DEFINED _RUNTIME_LIBRARY) set(library "${_RUNTIME_LIBRARY}") if(library STREQUAL "Use DLL runtime") if(is_debug) set(flag "/MDd") else() set(flag "/MD") endif() elseif(library STREQUAL "Use static runtime") if(is_debug) set(flag "/MTd") else() set(flag "/MT") endif() elseif(NOT (library STREQUAL "(Default)" OR library STREQUAL "Default")) message(FATAL_ERROR "Unsupported value for RUNTIME_LIBRARY: \"${library}\"") endif() set(JUCER_RUNTIME_LIBRARY_FLAG_${config} "${flag}" PARENT_SCOPE) endif() if(DEFINED _WHOLE_PROGRAM_OPTIMISATION) set(optimisation "${_WHOLE_PROGRAM_OPTIMISATION}") if(optimisation STREQUAL "Always disable") set(JUCER_ALWAYS_DISABLE_WPO_${config} TRUE PARENT_SCOPE) elseif(NOT optimisation STREQUAL "Enable when possible") message(FATAL_ERROR "Unsupported value for WHOLE_PROGRAM_OPTIMISATION: \"${optimisation}\"" ) endif() endif() if(DEFINED _MULTI_PROCESSOR_COMPILATION) set(JUCER_MULTI_PROCESSOR_COMPILATION_${config} "${_MULTI_PROCESSOR_COMPILATION}" PARENT_SCOPE ) endif() if(DEFINED _INCREMENTAL_LINKING) set(JUCER_INCREMENTAL_LINKING_${config} "${_INCREMENTAL_LINKING}" PARENT_SCOPE) endif() if(DEFINED _FORCE_GENERATION_OF_DEBUG_SYMBOLS) set(JUCER_FORCE_GENERATION_OF_DEBUG_SYMBOLS_${config} "${_FORCE_GENERATION_OF_DEBUG_SYMBOLS}" PARENT_SCOPE ) endif() if(DEFINED _PREBUILD_COMMAND) set(script_content "${_PREBUILD_COMMAND}") configure_file("${Reprojucer_data_DIR}/script.in" "prebuild_${config}.cmd" @ONLY) set(JUCER_PREBUILD_COMMAND_${config} "${CMAKE_CURRENT_BINARY_DIR}/prebuild_${config}.cmd" PARENT_SCOPE ) endif() if(DEFINED _POSTBUILD_COMMAND) set(script_content "${_POSTBUILD_COMMAND}") configure_file("${Reprojucer_data_DIR}/script.in" "postbuild_${config}.cmd" @ONLY) set(JUCER_POSTBUILD_COMMAND_${config} "${CMAKE_CURRENT_BINARY_DIR}/postbuild_${config}.cmd" PARENT_SCOPE ) endif() if(DEFINED _GENERATE_MANIFEST) set(JUCER_GENERATE_MANIFEST_${config} "${_GENERATE_MANIFEST}" PARENT_SCOPE) endif() if(DEFINED _CHARACTER_SET) set(character_sets "Default" "MultiByte" "Unicode") if(_CHARACTER_SET IN_LIST character_sets) set(JUCER_CHARACTER_SET_${config} "${_CHARACTER_SET}" PARENT_SCOPE) else() message(FATAL_ERROR "Unsupported value for CHARACTER_SET: \"${_CHARACTER_SET}\"") endif() endif() if(DEFINED _ARCHITECTURE AND exporter MATCHES "^Visual Studio 20(22|1[9753])$") if(_ARCHITECTURE STREQUAL "32-bit") set(wants_x64 FALSE) elseif(_ARCHITECTURE STREQUAL "x64") set(wants_x64 TRUE) else() message(FATAL_ERROR "Unsupported value for ARCHITECTURE: \"${_ARCHITECTURE}\"") endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(is_x64 TRUE) else() set(is_x64 FALSE) endif() set(error_message "") if(wants_x64 AND NOT is_x64) set(error_message "Cannot honor \"ARCHITECTURE x64\" while targeting the Win32 architecture. " ) if(CMAKE_GENERATOR MATCHES "^Visual Studio") string(APPEND error_message "You must call `cmake -G\"${CMAKE_GENERATOR} Win64\"`" " or `cmake -G\"${CMAKE_GENERATOR}\" -A x64` in order to build for x64." ) else() string(APPEND error_message "You must use a compiler that targets x64 in order to" " build for x64." ) endif() elseif(NOT wants_x64 AND is_x64) set(error_message "Cannot honor \"ARCHITECTURE 32-bit\" while targeting the x64 architecture. " ) if(CMAKE_GENERATOR MATCHES "^Visual Studio") string(FIND "${CMAKE_GENERATOR}" " Win64" length REVERSE) string(SUBSTRING "${CMAKE_GENERATOR}" 0 ${length} 32_bit_generator) string(APPEND error_message "You must call `cmake -G\"${32_bit_generator}\"` or" " `cmake -G\"${32_bit_generator}\" -A Win32` in order to build for 32-bit." ) else() string(APPEND error_message "You must use a compiler that targets x86 in order to" " build for 32-bit." ) endif() endif() if(error_message) message(FATAL_ERROR "${error_message}") endif() endif() if(DEFINED _ARCHITECTURE AND exporter STREQUAL "Linux Makefile") set(architecture "${_ARCHITECTURE}") unset(architecture_flag) if(architecture STREQUAL "Native") set(architecture_flag "-march=native") elseif(architecture STREQUAL "") set(architecture_flag "") elseif(architecture STREQUAL "32-bit (-m32)") set(architecture_flag "-m32") elseif(architecture STREQUAL "64-bit (-m64)") set(architecture_flag "-m64") elseif(architecture STREQUAL "ARM v6") set(architecture_flag "-march=armv6") elseif(architecture STREQUAL "ARM v7") set(architecture_flag "-march=armv7") elseif(NOT (architecture STREQUAL "(Default)" OR architecture STREQUAL "Default")) message(FATAL_ERROR "Unsupported value for ARCHITECTURE: \"${architecture}\"") endif() if(DEFINED architecture_flag) set(JUCER_ARCHITECTURE_FLAG_${config} "${architecture_flag}" PARENT_SCOPE) endif() endif() if(DEFINED _ARCHITECTURE AND exporter MATCHES "^Code::Blocks \\((Windows|Linux)\\)$") set(architecture "${_ARCHITECTURE}") unset(architecture_flag) if(architecture STREQUAL "32-bit (-m32)") set(architecture_flag "-m32") elseif(architecture STREQUAL "64-bit (-m64)") set(architecture_flag "-m64") elseif(architecture STREQUAL "ARM v6") set(architecture_flag "-march=armv6") elseif(architecture STREQUAL "ARM v7") set(architecture_flag "-march=armv7") elseif(NOT architecture STREQUAL "Default") message(FATAL_ERROR "Unsupported value for ARCHITECTURE: \"${architecture}\"") endif() if(DEFINED architecture_flag) set(JUCER_ARCHITECTURE_FLAG_${config} "${architecture_flag}" PARENT_SCOPE) endif() endif() endfunction() function(jucer_project_end) unset(current_exporter) foreach(exporter_index RANGE 9) list(GET Reprojucer_supported_exporters_conditions ${exporter_index} condition) if(${condition}) if(DEFINED current_exporter) message(FATAL_ERROR "There is already a current exporter: ${current_exporter}") else() list(GET Reprojucer_supported_exporters ${exporter_index} exporter) set(current_exporter "${exporter}") endif() endif() endforeach() if(NOT DEFINED current_exporter) set(exporters_list "") foreach(exporter IN LISTS Reprojucer_supported_exporters) string(APPEND exporters_list "\n - ${exporter}") endforeach() message(FATAL_ERROR "Reprojucer.cmake doesn't support any export target for your" " current platform. It supports the following export targets:${exporters_list}.\n" "If you think Reprojucer.cmake should support another export target, please create" " an issue on GitHub: https://github.com/McMartin/FRUT/issues/new\n" ) endif() if(NOT current_exporter IN_LIST JUCER_PROJECT_EXPORT_TARGETS) message(FATAL_ERROR "You must call jucer_export_target(\"${current_exporter}\")" " before calling jucer_project_end()." ) endif() if(NOT JUCER_PROJECT_CONFIGURATIONS) message(FATAL_ERROR "You must call" " jucer_export_target_configuration(\"${current_exporter}\") before calling" " jucer_project_end()." ) endif() if(DEFINED CMAKE_CONFIGURATION_TYPES) set(CMAKE_CONFIGURATION_TYPES "${JUCER_PROJECT_CONFIGURATIONS}" PARENT_SCOPE) else() if(NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") list(GET JUCER_PROJECT_CONFIGURATIONS 0 first_configuration) message(STATUS "Setting CMAKE_BUILD_TYPE to \"${first_configuration}\" as it was not specified." ) set(CMAKE_BUILD_TYPE "${first_configuration}") set(CMAKE_BUILD_TYPE "${first_configuration}" PARENT_SCOPE) elseif(NOT CMAKE_BUILD_TYPE IN_LIST JUCER_PROJECT_CONFIGURATIONS) message(FATAL_ERROR "CMAKE_BUILD_TYPE is set to \"${CMAKE_BUILD_TYPE}\", which is" " not in the defined build configurations: ${JUCER_PROJECT_CONFIGURATIONS}." ) endif() endif() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) foreach(lang IN ITEMS C CXX) set(variable_name "CMAKE_${lang}_FLAGS_${upper_config}") if(NOT DEFINED ${variable_name}) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set(${variable_name} ${CMAKE_${lang}_FLAGS_DEBUG} CACHE STRING "Flags used by the compiler during \"${config}\" builds." ) else() set(${variable_name} ${CMAKE_${lang}_FLAGS_RELEASE} CACHE STRING "Flags used by the compiler during \"${config}\" builds." ) endif() mark_as_advanced(${variable_name}) endif() endforeach() foreach(type IN ITEMS EXE MODULE SHARED STATIC) set(variable_name "CMAKE_${type}_LINKER_FLAGS_${upper_config}") if(NOT DEFINED ${variable_name}) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set(${variable_name} ${CMAKE_${type}_LINKER_FLAGS_DEBUG} CACHE STRING "Flags used by the linker during \"${config}\" builds." ) else() set(${variable_name} ${CMAKE_${type}_LINKER_FLAGS_RELEASE} CACHE STRING "Flags used by the linker during \"${config}\" builds." ) endif() mark_as_advanced(${variable_name}) endif() endforeach() endforeach() # Translate old settings to new settings foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(old_vars "JUCER_OSX_BASE_SDK_VERSION_${config}" "JUCER_OSX_DEPLOYMENT_TARGET_${config}" "JUCER_OSX_ARCHITECTURES_${config}" "JUCER_MACOS_BASE_SDK_VERSION_${config}" ) set(new_vars "JUCER_MACOS_BASE_SDK_VERSION_${config}" "JUCER_MACOS_DEPLOYMENT_TARGET_${config}" "JUCER_MACOS_ARCHITECTURES_${config}" "JUCER_MACOS_BASE_SDK_${config}" ) foreach(index RANGE 2) list(GET old_vars ${index} old_var) list(GET new_vars ${index} new_var) if(DEFINED "${old_var}") if(DEFINED "${new_var}") message(WARNING "Both ${old_var} and ${new_var} are defined. The value of" " ${old_var} (${${old_var}}) will be ignored and the value of ${new_var}" " (${${new_var}}) will be used." ) else() set(${new_var} "${${old_var}}") endif() endif() endforeach() endforeach() if(IOS) execute_process( COMMAND "xcrun" "--sdk" "iphoneos" "--show-sdk-path" OUTPUT_VARIABLE sdk_path OUTPUT_STRIP_TRAILING_WHITESPACE ) if(IS_DIRECTORY "${sdk_path}") set(JUCER_IPHONEOS_SDK_PATH "${sdk_path}") else() message(WARNING "Running `xcrun --sdk iphoneos --show-sdk-path` didn't output a" " valid directory." ) endif() elseif(APPLE) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(sdk_version "${JUCER_MACOS_BASE_SDK_${config}}") execute_process( COMMAND "xcrun" "--sdk" "macosx${sdk_version}" "--show-sdk-path" OUTPUT_VARIABLE sdk_path OUTPUT_STRIP_TRAILING_WHITESPACE ) if(IS_DIRECTORY "${sdk_path}") set(JUCER_MACOSX_SDK_PATH_${config} "${sdk_path}") else() message(WARNING "Running `xcrun --sdk macosx${sdk_version} --show-sdk-path`" " didn't output a valid directory." ) endif() endforeach() endif() _FRUT_check_SDK_folders("${current_exporter}") _FRUT_generate_AppConfig_and_JucePluginDefines_header() _FRUT_generate_JuceHeader_header() if(DEFINED JUCER_SMALL_ICON OR DEFINED JUCER_LARGE_ICON) unset(icon_filename) if(APPLE) _FRUT_generate_icon_file("icns" "${CMAKE_CURRENT_BINARY_DIR}" icon_filename) elseif(WIN32 AND NOT JUCER_PROJECT_TYPE STREQUAL "Static Library") _FRUT_generate_icon_file("ico" "${CMAKE_CURRENT_BINARY_DIR}" icon_filename) endif() if(DEFINED icon_filename) set(JUCER_ICON_FILE "${CMAKE_CURRENT_BINARY_DIR}/${icon_filename}") if(NOT APPLE) # handled in _FRUT_add_bundle_resources() source_group("JUCE Library Code" FILES "${JUCER_ICON_FILE}") endif() endif() endif() if(WIN32 AND NOT JUCER_PROJECT_TYPE STREQUAL "Static Library") set(JUCER_RESOURCES_RC_FILE "${CMAKE_CURRENT_BINARY_DIR}/resources.rc") _FRUT_generate_resources_rc_file("${JUCER_RESOURCES_RC_FILE}") source_group("JUCE Library Code" FILES "${JUCER_RESOURCES_RC_FILE}") endif() if(IOS) if(NOT DEFINED JUCER_CUSTOM_XCASSETS_FOLDER OR JUCER_CUSTOM_XCASSETS_FOLDER STREQUAL "") _FRUT_create_xcassets_folder_from_icons(JUCER_XCASSETS) else() set(JUCER_XCASSETS "${JUCER_CUSTOM_XCASSETS_FOLDER}") endif() if( (DEFINED JUCER_CUSTOM_LAUNCH_STORYBOARD AND NOT JUCER_CUSTOM_LAUNCH_STORYBOARD STREQUAL "") OR (NOT DEFINED JUCER_CUSTOM_XCASSETS_FOLDER OR JUCER_CUSTOM_XCASSETS_FOLDER STREQUAL "") ) set(custom_launch_storyboard "${JUCER_CUSTOM_LAUNCH_STORYBOARD}") if(custom_launch_storyboard STREQUAL "") set(JUCER_LAUNCH_STORYBOARD_FILE "${Reprojucer_data_DIR}/LaunchScreen.storyboard") else() set(JUCER_LAUNCH_STORYBOARD_FILE "${custom_launch_storyboard}") endif() endif() endif() source_group("JUCE Library Code" REGULAR_EXPRESSION "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/" ) set_source_files_properties(${JUCER_PROJECT_MODULES_BROWSABLE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) string(REGEX REPLACE "[^A-Za-z0-9_.+-]" "_" target "${JUCER_PROJECT_NAME}") set(modules_sources "") foreach(module_name IN LISTS JUCER_PROJECT_MODULES) set(module_sources "${JUCER_PROJECT_MODULE_${module_name}_SOURCES}") list(APPEND modules_sources ${module_sources}) endforeach() set(all_sources ${JUCER_PROJECT_FILES} ${modules_sources} ${JUCER_PROJECT_MODULES_BROWSABLE_FILES} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) if(MSVC) list(APPEND all_sources ${JUCER_MANIFEST_FILE}) endif() if(JUCER_PROJECT_TYPE STREQUAL "Console Application") if(IOS) message(FATAL_ERROR "Console Application projects are not supported on iOS") endif() add_executable(${target} ${all_sources}) _FRUT_set_product_bundle_identifier(${target}) _FRUT_set_output_directory_properties(${target} "ConsoleApp") _FRUT_set_output_name_properties(${target}) _FRUT_set_compiler_and_linker_settings(${target} "ConsoleApp" "${current_exporter}") _FRUT_add_extra_commands(${target} "${current_exporter}") _FRUT_link_xcode_frameworks(${target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${target}) elseif(JUCER_PROJECT_TYPE STREQUAL "GUI Application") add_executable(${target} WIN32 MACOSX_BUNDLE ${all_sources}) _FRUT_add_bundle_resources(${target}) _FRUT_generate_plist_file(${target} "App" "APPL" "????") _FRUT_set_output_directory_properties(${target} "App") _FRUT_set_output_name_properties(${target}) _FRUT_set_compiler_and_linker_settings(${target} "GUIApp" "${current_exporter}") _FRUT_add_extra_commands(${target} "${current_exporter}") _FRUT_link_xcode_frameworks(${target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${target}) elseif(JUCER_PROJECT_TYPE STREQUAL "Static Library") add_library(${target} STATIC ${all_sources}) _FRUT_set_product_bundle_identifier(${target}) _FRUT_set_output_directory_properties(${target} "Static Library") if(APPLE OR current_exporter STREQUAL "Linux Makefile") _FRUT_set_output_name_properties(${target} ADD_lib_PREFIX) else() _FRUT_set_output_name_properties(${target}) endif() _FRUT_set_compiler_and_linker_settings( ${target} "StaticLibrary" "${current_exporter}" ) _FRUT_add_extra_commands(${target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${target}) elseif(JUCER_PROJECT_TYPE STREQUAL "Dynamic Library") add_library(${target} SHARED ${all_sources}) _FRUT_set_product_bundle_identifier(${target}) _FRUT_set_output_directory_properties(${target} "Dynamic Library") if(current_exporter STREQUAL "Linux Makefile") _FRUT_set_output_name_properties(${target} ADD_lib_PREFIX) else() _FRUT_set_output_name_properties(${target}) endif() _FRUT_set_compiler_and_linker_settings( ${target} "DynamicLibrary" "${current_exporter}" ) _FRUT_add_extra_commands(${target} "${current_exporter}") _FRUT_link_xcode_frameworks(${target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${target}) elseif(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") set(AudioUnit_sources "") set(AudioUnitv3_sources "") set(AAX_sources "") set(RTAS_sources "") set(VST_sources "") set(VST3_sources "") set(Standalone_sources "") set(Unity_sources "") set(SharedCode_sources "") foreach(src_file IN LISTS JUCER_PROJECT_FILES modules_sources) # See Project::getTargetTypeFromFilePath() # in JUCE/extras/Projucer/Source/Project/jucer_Project.cpp if(src_file MATCHES "_AU[._]") list(APPEND AudioUnit_sources "${src_file}") elseif(src_file MATCHES "_AUv3[._]") list(APPEND AudioUnitv3_sources "${src_file}") elseif(src_file MATCHES "_AAX[._]") list(APPEND AAX_sources "${src_file}") elseif(src_file MATCHES "_RTAS[._]") list(APPEND RTAS_sources "${src_file}") elseif(src_file MATCHES "_VST2[._]") list(APPEND VST_sources "${src_file}") elseif(src_file MATCHES "_VST3[._]") list(APPEND VST3_sources "${src_file}") elseif(src_file MATCHES "_Standalone[._]") list(APPEND Standalone_sources "${src_file}") elseif(src_file MATCHES "_Unity[._]") list(APPEND Unity_sources "${src_file}") else() list(APPEND SharedCode_sources "${src_file}") endif() endforeach() set(shared_code_target "${target}_Shared_Code") add_library(${shared_code_target} STATIC ${SharedCode_sources} ${JUCER_PROJECT_MODULES_BROWSABLE_FILES} ${JUCER_ICON_FILE} ) _FRUT_set_product_bundle_identifier(${shared_code_target}) _FRUT_set_output_directory_properties(${shared_code_target} "Shared Code") if(APPLE) _FRUT_set_output_name_properties(${shared_code_target} ADD_lib_PREFIX) else() _FRUT_set_output_name_properties(${shared_code_target}) endif() _FRUT_set_compiler_and_linker_settings( ${shared_code_target} "SharedCodeTarget" "${current_exporter}" ) _FRUT_add_extra_commands(${shared_code_target} "${current_exporter}") target_compile_definitions(${shared_code_target} PRIVATE "JUCE_SHARED_CODE=1") _FRUT_set_custom_xcode_flags(${shared_code_target}) if(JUCER_BUILD_VST AND NOT IOS) set(vst_target "${target}_VST") add_library(${vst_target} MODULE ${VST_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${vst_target}) target_link_libraries(${vst_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${vst_target} "VST" "BNDL" "????") _FRUT_set_bundle_properties(${vst_target} "vst") _FRUT_set_output_directory_properties(${vst_target} "VST") _FRUT_set_output_name_properties(${vst_target}) _FRUT_set_compiler_and_linker_settings( ${vst_target} "VSTPlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${vst_target} "${current_exporter}") if(APPLE) _FRUT_install_to_plugin_binary_location(${vst_target} "VST" "$ENV{HOME}/Library/Audio/Plug-Ins/VST" ) elseif(MSVC) if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(env_var "ProgramW6432") else() set(env_var "programfiles(x86)") endif() _FRUT_install_to_plugin_binary_location(${vst_target} "VST" "$ENV{${env_var}}/Steinberg/Vstplugins" ) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") _FRUT_install_to_plugin_binary_location(${vst_target} "VST" "$ENV{HOME}/.vst") endif() _FRUT_link_xcode_frameworks(${vst_target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${vst_target}) unset(vst_target) endif() set(can_build_vst3 FALSE) if((APPLE AND NOT IOS) OR MSVC) set(can_build_vst3 TRUE) elseif( NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" ) set(can_build_vst3 TRUE) endif() if(JUCER_BUILD_VST3 AND can_build_vst3) set(vst3_target "${target}_VST3") add_library(${vst3_target} MODULE ${VST3_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${vst3_target}) target_link_libraries(${vst3_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${vst3_target} "VST3" "BNDL" "????") _FRUT_set_bundle_properties(${vst3_target} "vst3") _FRUT_set_output_directory_properties(${vst3_target} "VST3") _FRUT_set_output_name_properties(${vst3_target}) _FRUT_set_compiler_and_linker_settings( ${vst3_target} "VST3PlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${vst3_target} "${current_exporter}") if(APPLE) _FRUT_install_to_plugin_binary_location(${vst3_target} "VST3" "$ENV{HOME}/Library/Audio/Plug-Ins/VST3" ) elseif(MSVC) set_target_properties(${vst3_target} PROPERTIES SUFFIX ".vst3") if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(common_files_env_var "CommonProgramW6432") else() set(common_files_env_var "CommonProgramFiles(x86)") endif() _FRUT_install_to_plugin_binary_location(${vst3_target} "VST3" "$ENV{${common_files_env_var}}/VST3" ) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") try_compile( RESULT_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${Reprojucer_data_DIR}/juce_runtime_arch_detection.cpp" OUTPUT_VARIABLE arch_detection_output ) if(arch_detection_output MATCHES "JUCE_ARCH ([A-Za-z0-9_]+)") set(vst3_arch "${CMAKE_MATCH_1}") else() message( FATAL_ERROR "Failed to find \"JUCE_ARCH \" in compiler output" ) endif() set(component "_install_${vst3_target}_to_VST3_binary_location") set(should_install FALSE) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) get_target_property(output_name ${vst3_target} OUTPUT_NAME_${upper_config}) set(vst3_dir "${output_name}.vst3") get_target_property( output_directory ${vst3_target} LIBRARY_OUTPUT_DIRECTORY_${upper_config} ) if(output_directory) set(vst3_dir "${output_directory}/${vst3_dir}") endif() set(vst3_subdir "Contents/${vst3_arch}-linux") set_target_properties(${vst3_target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${upper_config} "${vst3_dir}/${vst3_subdir}" ) if(NOT DEFINED JUCER_ENABLE_PLUGIN_COPY_STEP_${config} OR JUCER_ENABLE_PLUGIN_COPY_STEP_${config}) if(DEFINED JUCER_VST3_BINARY_LOCATION_${config}) set(destination "${JUCER_VST3_BINARY_LOCATION_${config}}") else() set(destination "$ENV{HOME}/.vst3") endif() get_filename_component(vst3_dir "${vst3_dir}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}" ) install(DIRECTORY "${vst3_dir}" CONFIGURATIONS "${config}" COMPONENT "${component}" DESTINATION "${destination}" ) set(should_install TRUE) endif() endforeach() if(should_install) add_custom_command(TARGET ${vst3_target} POST_BUILD COMMAND "${CMAKE_COMMAND}" "-DCMAKE_INSTALL_CONFIG_NAME=$" "-DCMAKE_INSTALL_COMPONENT=${component}" "-P" "${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake" ) endif() endif() _FRUT_link_xcode_frameworks(${vst3_target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${vst3_target}) unset(vst3_target) endif() if(JUCER_BUILD_AUDIOUNIT AND APPLE AND NOT IOS) set(au_target "${target}_AU") add_library(${au_target} MODULE ${AudioUnit_sources}) _FRUT_add_bundle_resources(${au_target}) target_link_libraries(${au_target} PRIVATE ${shared_code_target}) unset(rez_inputs) foreach(src_file IN LISTS AudioUnit_sources) get_filename_component(file_extension "${src_file}" EXT) if(file_extension STREQUAL ".r") list(APPEND rez_inputs "${src_file}") endif() endforeach() if(DEFINED rez_inputs) _FRUT_add_Rez_command_to_AU_plugin(${au_target} ${rez_inputs}) endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 7.0.3)) set(juce_audio_plugin_client_dir "${JUCER_PROJECT_MODULE_juce_audio_plugin_client_PATH}/juce_audio_plugin_client" ) target_include_directories(${au_target} PRIVATE "${juce_audio_plugin_client_dir}/AU" ) endif() _FRUT_generate_plist_file(${au_target} "AU" "BNDL" "????") _FRUT_set_bundle_properties(${au_target} "component") _FRUT_set_output_directory_properties(${au_target} "AU") _FRUT_set_output_name_properties(${au_target}) _FRUT_set_compiler_and_linker_settings( ${au_target} "AudioUnitPlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${au_target} "${current_exporter}") _FRUT_install_to_plugin_binary_location(${au_target} "AU" "$ENV{HOME}/Library/Audio/Plug-Ins/Components" ) _FRUT_link_xcode_frameworks(${au_target} "${current_exporter}" "AudioUnit" "CoreAudioKit" ) _FRUT_set_custom_xcode_flags(${au_target}) unset(au_target) endif() if(JUCER_BUILD_AUDIOUNIT_V3 AND APPLE) set(auv3_target "${target}_AUv3_AppExtension") add_executable(${auv3_target} ${AudioUnitv3_sources}) if(NOT (DEFINED JUCER_ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION AND NOT JUCER_ADD_DUPLICATE_RESOURCES_FOLDER_TO_APP_EXTENSION)) _FRUT_add_bundle_resources(${auv3_target}) endif() target_link_libraries(${auv3_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${auv3_target} "AUv3_AppExtension" "XPC!" "????") # Cannot use _FRUT_set_bundle_properties() since Projucer sets xcodeIsBundle=false # for this target, though it is a bundle... set_target_properties(${auv3_target} PROPERTIES BUNDLE TRUE BUNDLE_EXTENSION "appex" XCODE_ATTRIBUTE_WRAPPER_EXTENSION "appex" XCODE_PRODUCT_TYPE "com.apple.product-type.app-extension" ) _FRUT_set_output_directory_properties(${auv3_target} "AUv3 AppExtension") _FRUT_set_output_name_properties(${auv3_target}) _FRUT_set_compiler_and_linker_settings( ${auv3_target} "AudioUnitv3PlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${auv3_target} "${current_exporter}") set(extra_xcode_frameworks "AVFoundation" "CoreAudioKit") if(NOT IOS) list(APPEND extra_xcode_frameworks "AudioUnit") endif() _FRUT_link_xcode_frameworks(${auv3_target} "${current_exporter}" ${extra_xcode_frameworks} ) _FRUT_set_custom_xcode_flags(${auv3_target}) unset(auv3_target) endif() if(JUCER_BUILD_RTAS AND ((APPLE AND NOT IOS) OR MSVC)) set(rtas_target "${target}_RTAS") add_library(${rtas_target} MODULE ${RTAS_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${rtas_target}) target_link_libraries(${rtas_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${rtas_target} "RTAS" "TDMw" "PTul") _FRUT_set_bundle_properties(${rtas_target} "dpm") _FRUT_set_output_directory_properties(${rtas_target} "RTAS") _FRUT_set_output_name_properties(${rtas_target}) _FRUT_set_compiler_and_linker_settings( ${rtas_target} "RTASPlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${rtas_target} "${current_exporter}") if(APPLE) # See XcodeProjectExporter::XcodeTarget::getTargetExtraHeaderSearchPaths() # in JUCE/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h target_include_directories(${rtas_target} PRIVATE "$(DEVELOPER_DIR)/Headers/FlatCarbon" "$(SDKROOT)/Developer/Headers/FlatCarbon" ) foreach(include_dir IN ITEMS "AlturaPorts/TDMPlugIns/PlugInLibrary/Controls" "AlturaPorts/TDMPlugIns/PlugInLibrary/CoreClasses" "AlturaPorts/TDMPlugIns/PlugInLibrary/DSPClasses" "AlturaPorts/TDMPlugIns/PlugInLibrary/EffectClasses" "AlturaPorts/TDMPlugIns/PlugInLibrary/MacBuild" "AlturaPorts/TDMPlugIns/PlugInLibrary/Meters" "AlturaPorts/TDMPlugIns/PlugInLibrary/ProcessClasses" "AlturaPorts/TDMPlugIns/PlugInLibrary/ProcessClasses/Interfaces" "AlturaPorts/TDMPlugIns/PlugInLibrary/RTASP_Adapt" "AlturaPorts/TDMPlugIns/PlugInLibrary/Utilities" "AlturaPorts/TDMPlugIns/PlugInLibrary/ViewClasses" "AlturaPorts/TDMPlugIns/DSPManager/**" "AlturaPorts/TDMPlugIns/SupplementalPlugInLib/Encryption" "AlturaPorts/TDMPlugIns/SupplementalPlugInLib/GraphicsExtensions" "AlturaPorts/TDMPlugIns/common/**" "AlturaPorts/TDMPlugIns/common/PI_LibInterface" "AlturaPorts/TDMPlugIns/PACEProtection/**" "AlturaPorts/TDMPlugIns/SignalProcessing/**" "AlturaPorts/OMS/Headers" "AlturaPorts/Fic/Interfaces/**" "AlturaPorts/Fic/Source/SignalNets" "AlturaPorts/DSIPublicInterface/PublicHeaders" "DAEWin/Include" "AlturaPorts/DigiPublic/Interfaces" "AlturaPorts/DigiPublic" "AlturaPorts/NewFileLibs/DOA" "AlturaPorts/NewFileLibs/Cmn" "xplat/AVX/avx2/avx2sdk/inc" "xplat/AVX/avx2/avx2sdk/utils" ) target_include_directories(${rtas_target} PRIVATE "${JUCER_RTAS_SDK_FOLDER}/${include_dir}" ) endforeach() target_link_libraries(${rtas_target} PRIVATE "${JUCER_RTAS_SDK_FOLDER}/MacBag/Libs/Debug/libPluginLibrary.a" "${JUCER_RTAS_SDK_FOLDER}/MacBag/Libs/Release/libPluginLibrary.a" ) _FRUT_install_to_plugin_binary_location(${rtas_target} "RTAS" "/Library/Application Support/Digidesign/Plug-Ins/" ) elseif(MSVC) set_target_properties(${rtas_target} PROPERTIES SUFFIX ".dpm") target_compile_definitions(${rtas_target} PRIVATE "JucePlugin_WinBag_path=\"${JUCER_RTAS_SDK_FOLDER}/WinBag\"" ) foreach(src_file IN LISTS RTAS_sources) get_filename_component(src_file_basename "${src_file}" NAME) if(src_file_basename MATCHES "^(include_)?juce_audio_plugin_client_RTAS_") # Calling Convention: __stdcall (/Gz) set_source_files_properties("${src_file}" PROPERTIES COMPILE_FLAGS "/Gz") endif() endforeach() string(CONCAT module_definition_file "${JUCER_PROJECT_MODULE_juce_audio_plugin_client_PATH}/" "juce_audio_plugin_client/RTAS/juce_RTAS_WinExports.def" ) target_sources(${rtas_target} PRIVATE "${module_definition_file}") string(CONCAT rtas_link_flags " /DELAYLOAD:DAE.dll" " /DELAYLOAD:DigiExt.dll" " /DELAYLOAD:DSI.dll" " /DELAYLOAD:PluginLib.dll" " /DELAYLOAD:DSPManager.dll" " /DELAYLOAD:DSPManagerClientLib.dll" " /DELAYLOAD:RTASClientLib.dll" ) set_property(TARGET ${rtas_target} APPEND_STRING PROPERTY LINK_FLAGS "${rtas_link_flags}" ) # See MSVCProjectExporterBase::MSVCTargetBase::getExtraSearchPaths() # in JUCE/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h foreach(include_dir IN ITEMS "AlturaPorts/TDMPlugins/PluginLibrary/EffectClasses" "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses" "AlturaPorts/TDMPlugins/PluginLibrary/ProcessClasses/Interfaces" "AlturaPorts/TDMPlugins/PluginLibrary/Utilities" "AlturaPorts/TDMPlugins/PluginLibrary/RTASP_Adapt" "AlturaPorts/TDMPlugins/PluginLibrary/CoreClasses" "AlturaPorts/TDMPlugins/PluginLibrary/Controls" "AlturaPorts/TDMPlugins/PluginLibrary/Meters" "AlturaPorts/TDMPlugins/PluginLibrary/ViewClasses" "AlturaPorts/TDMPlugins/PluginLibrary/DSPClasses" "AlturaPorts/TDMPlugins/PluginLibrary/Interfaces" "AlturaPorts/TDMPlugins/common" "AlturaPorts/TDMPlugins/common/Platform" "AlturaPorts/TDMPlugins/common/Macros" "AlturaPorts/TDMPlugins/SignalProcessing/Public" "AlturaPorts/TDMPlugIns/DSPManager/Interfaces" "AlturaPorts/SADriver/Interfaces" "AlturaPorts/DigiPublic/Interfaces" "AlturaPorts/DigiPublic" "AlturaPorts/Fic/Interfaces/DAEClient" "AlturaPorts/NewFileLibs/Cmn" "AlturaPorts/NewFileLibs/DOA" "AlturaPorts/AlturaSource/PPC_H" "AlturaPorts/AlturaSource/AppSupport" "AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc" "xplat/AVX/avx2/avx2sdk/inc" ) target_include_directories(${rtas_target} PRIVATE "${JUCER_RTAS_SDK_FOLDER}/${include_dir}" ) endforeach() if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(common_files_env_var "CommonProgramW6432") else() set(common_files_env_var "CommonProgramFiles(x86)") endif() _FRUT_install_to_plugin_binary_location(${rtas_target} "RTAS" "$ENV{${common_files_env_var}}/Digidesign/DAE/Plug-Ins" ) endif() _FRUT_link_xcode_frameworks(${rtas_target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${rtas_target}) unset(rtas_target) endif() if(JUCER_BUILD_AAX AND ((APPLE AND NOT IOS) OR MSVC)) set(aax_target "${target}_AAX") add_library(${aax_target} MODULE ${AAX_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${aax_target}) target_link_libraries(${aax_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${aax_target} "AAX" "TDMw" "PTul") _FRUT_set_bundle_properties(${aax_target} "aaxplugin") _FRUT_set_output_directory_properties(${aax_target} "AAX") _FRUT_set_output_name_properties(${aax_target}) _FRUT_set_compiler_and_linker_settings( ${aax_target} "AAXPlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${aax_target} "${current_exporter}") if(APPLE) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set(aax_config "Debug") else() set(aax_config "Release") endif() set(aax_libcpp "_libcpp") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2 AND NOT (JUCER_CXX_LIBRARY_${config} STREQUAL "libc++" OR JUCER_MACOS_DEPLOYMENT_TARGET_${config} VERSION_GREATER 10.8)) set(aax_libcpp "") endif() set(aax_lib "${JUCER_AAX_SDK_FOLDER}/Libs/${aax_config}/libAAXLibrary${aax_libcpp}.a" ) target_link_libraries(${aax_target} PRIVATE $<$:${aax_lib}>) endforeach() _FRUT_install_to_plugin_binary_location(${aax_target} "AAX" "/Library/Application Support/Avid/Audio/Plug-Ins" ) elseif(MSVC) set_target_properties(${aax_target} PROPERTIES SUFFIX ".aaxdll") target_compile_definitions(${aax_target} PRIVATE "JucePlugin_AAXLibs_path=\"${JUCER_AAX_SDK_FOLDER}/Libs\"" ) set(all_confs_output_name "") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) get_target_property(output_name ${aax_target} OUTPUT_NAME_${upper_config}) string(APPEND all_confs_output_name $<$:${output_name}>) endforeach() set(all_confs_bundle "$/${all_confs_output_name}.aaxplugin" ) if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(arch_dir "x64") else() set(arch_dir "Win32") endif() add_custom_command(TARGET ${aax_target} PRE_BUILD COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" "${all_confs_bundle}/Contents/${arch_dir}" ) add_custom_command(TARGET ${aax_target} POST_BUILD COMMAND "${CMAKE_COMMAND}" "-E" "copy_if_different" "$" "${all_confs_bundle}/Contents/${arch_dir}/${all_confs_output_name}.aaxplugin" ) if(DEFINED JUCER_ICON_FILE) set(plugin_icon "${JUCER_ICON_FILE}") else() set(plugin_icon "${JUCER_AAX_SDK_FOLDER}/Utilities/PlugIn.ico") endif() add_custom_command(TARGET ${aax_target} POST_BUILD COMMAND "${JUCER_AAX_SDK_FOLDER}/Utilities/CreatePackage.bat" "${all_confs_bundle}/Contents/${arch_dir}" "${plugin_icon}" ) if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(common_files_env_var "CommonProgramW6432") else() set(common_files_env_var "CommonProgramFiles(x86)") endif() unset(all_confs_destination) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_AAX_BINARY_LOCATION_${config}) set(destination "${JUCER_AAX_BINARY_LOCATION_${config}}") else() set(destination "$ENV{${common_files_env_var}}/Avid/Audio/Plug-Ins") endif() if(JUCER_ENABLE_PLUGIN_COPY_STEP_${config}) string(APPEND all_confs_destination $<$:$> ) endif() endforeach() if(DEFINED all_confs_destination) add_custom_command(TARGET ${aax_target} POST_BUILD COMMAND "xcopy" "$" "${all_confs_destination}\\${all_confs_output_name}.aaxplugin\\" "/E" "/H" "/K" "/R" "/Y" ) endif() endif() _FRUT_link_xcode_frameworks(${aax_target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${aax_target}) unset(aax_target) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) if(JUCER_BUILD_AUDIOUNIT_V3) set(juce4_standalone ON) endif() elseif(JUCER_BUILD_STANDALONE_PLUGIN) set(juce5_standalone ON) endif() if(juce4_standalone OR juce5_standalone) if(juce4_standalone) set(standalone_target "${target}_AUv3_Standalone") else() set(standalone_target "${target}_StandalonePlugin") endif() add_executable(${standalone_target} WIN32 MACOSX_BUNDLE ${Standalone_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${standalone_target}) target_link_libraries(${standalone_target} PRIVATE ${shared_code_target}) if(juce4_standalone) _FRUT_generate_plist_file(${standalone_target} "AUv3_Standalone" "APPL" "????") else() _FRUT_generate_plist_file(${standalone_target} "Standalone_Plugin" "APPL" "????") endif() _FRUT_set_output_directory_properties(${standalone_target} "Standalone Plugin") _FRUT_set_output_name_properties(${standalone_target}) _FRUT_set_compiler_and_linker_settings( ${standalone_target} "StandalonePlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${standalone_target} "${current_exporter}") _FRUT_link_xcode_frameworks(${standalone_target} "${current_exporter}") if(TARGET ${target}_AUv3_AppExtension) add_dependencies(${standalone_target} ${target}_AUv3_AppExtension) if(IOS) set(destination "$/PlugIns") else() set(destination "$/../PlugIns") endif() install(TARGETS ${target}_AUv3_AppExtension COMPONENT _embed_app_extension_in_standalone_app DESTINATION "${destination}" ) unset(epn) if(IOS) set(epn "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)") endif() add_custom_command(TARGET ${standalone_target} POST_BUILD COMMAND "${CMAKE_COMMAND}" "-DCMAKE_INSTALL_CONFIG_NAME=$" ${epn} "-DCMAKE_INSTALL_COMPONENT=_embed_app_extension_in_standalone_app" "-P" "${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake" ) endif() _FRUT_set_custom_xcode_flags(${standalone_target}) unset(standalone_target) endif() if(JUCER_BUILD_UNITY_PLUGIN AND NOT IOS) set(unity_target "${target}_Unity_Plugin") add_library(${unity_target} MODULE ${Unity_sources} ${JUCER_ICON_FILE} ${JUCER_RESOURCES_RC_FILE} ) _FRUT_add_bundle_resources(${unity_target}) target_link_libraries(${unity_target} PRIVATE ${shared_code_target}) _FRUT_generate_plist_file(${unity_target} "Unity_Plugin" "BNDL" "????") _FRUT_set_bundle_properties(${unity_target} "bundle") _FRUT_set_output_directory_properties(${unity_target} "Unity Plugin") if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) set(unity_dir "Unity") get_target_property( output_directory ${unity_target} LIBRARY_OUTPUT_DIRECTORY_${upper_config} ) if(output_directory) set(unity_dir "${output_directory}/${unity_dir}") endif() set_target_properties(${unity_target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${upper_config} "${unity_dir}" ) endforeach() endif() _FRUT_set_output_name_properties_Unity(${unity_target}) _FRUT_set_compiler_and_linker_settings( ${unity_target} "UnityPlugIn" "${current_exporter}" ) _FRUT_add_extra_commands(${unity_target} "${current_exporter}") set(project_name "${JUCER_PROJECT_NAME}") if(NOT project_name MATCHES "^[Aa][Uu][Dd][Ii][Oo][Pp][Ll][Uu][Gg][Ii][Nn]") set(project_name "audioplugin_${project_name}") endif() string(REPLACE " " "_" plugin_class_name "${project_name}") set(plugin_name "${project_name}") set(plugin_vendor "${JUCER_PLUGIN_MANUFACTURER}") set(plugin_description "${JUCER_PLUGIN_DESCRIPTION}") set(unity_script_file "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/${project_name}_UnityScript.cs" ) configure_file("${Reprojucer_data_DIR}/UnityScript.cs.in" "${unity_script_file}" @ONLY ) if(APPLE) target_sources(${unity_target} PRIVATE "${unity_script_file}") set_source_files_properties("${unity_script_file}" PROPERTIES MACOSX_PACKAGE_LOCATION "." ) else() add_custom_command(TARGET ${unity_target} POST_BUILD COMMAND "${CMAKE_COMMAND}" "-E" "copy_if_different" "${unity_script_file}" "$" ) endif() if(APPLE) _FRUT_install_to_plugin_binary_location(${unity_target} "UNITY" "") elseif(MSVC) _FRUT_install_to_plugin_binary_location( ${unity_target} "UNITY" "" FILES "${unity_script_file}" ) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") _FRUT_install_to_plugin_binary_location( ${unity_target} "UNITY" "$ENV{HOME}/UnityPlugins" FILES "${unity_script_file}" ) endif() _FRUT_link_xcode_frameworks(${unity_target} "${current_exporter}") _FRUT_set_custom_xcode_flags(${unity_target}) unset(unity_target) endif() else() message(FATAL_ERROR "Unknown project type: ${JUCER_PROJECT_TYPE}") endif() if(WIN32) set(user_cmd "${JUCER_POST_EXPORT_SHELL_COMMAND_WINDOWS}") else() set(user_cmd "${JUCER_POST_EXPORT_SHELL_COMMAND_MACOS_LINUX}") endif() _FRUT_abs_path_based_on_jucer_project_dir(project_root_folder ".") string(REPLACE "%%1%%" "${project_root_folder}" user_cmd "${user_cmd}") if(NOT user_cmd STREQUAL "") if(WIN32) set(full_cmd "cmd.exe" "/c" "${user_cmd}") else() set(full_cmd "/bin/sh" "-c" "${user_cmd}") endif() if(JUCER_RUN_POST_EXPORT_SHELL_COMMANDS) message(STATUS "[${JUCER_PROJECT_NAME}] Running '${user_cmd}'") execute_process(COMMAND ${full_cmd} TIMEOUT 10 # seconds RESULT_VARIABLE cmd_result ) if(NOT cmd_result EQUAL 0) message(FATAL_ERROR "Running '${user_cmd}' failed with ${cmd_result}") endif() else() message(STATUS "[${JUCER_PROJECT_NAME}] Would run '${user_cmd}' if" " JUCER_RUN_POST_EXPORT_SHELL_COMMANDS was ON." ) endif() endif() endfunction() function(_FRUT_abs_path_based_on_jucer_project_dir out_path in_path) if(NOT IS_ABSOLUTE "${in_path}" AND NOT DEFINED JUCER_PROJECT_DIR) message(FATAL_ERROR "Cannot join \"\${JUCER_PROJECT_DIR}\" and \"${in_path}\" to" " construct an absolute path because JUCER_PROJECT_DIR is not defined. You should" " call jucer_project_begin() first, e.g.:\n" " jucer_project_begin(\n" " PROJECT_FILE \"\"\n" " )\n" "or if you don't have a .jucer file:\n" " jucer_project_begin()\n" ) endif() get_filename_component(in_path "${in_path}" ABSOLUTE BASE_DIR "${JUCER_PROJECT_DIR}") set(${out_path} "${in_path}" PARENT_SCOPE) endfunction() function(_FRUT_abs_path_based_on_jucer_target_project_folder out_path in_path exporter) if(NOT IS_ABSOLUTE "${in_path}" AND NOT DEFINED JUCER_TARGET_PROJECT_FOLDER) message(FATAL_ERROR "Cannot join \"\${JUCER_TARGET_PROJECT_FOLDER}\" and" " \"${in_path}\" to construct an absolute path because JUCER_TARGET_PROJECT_FOLDER" " is not defined. You have to provide TARGET_PROJECT_FOLDER when calling" " jucer_export_target(\"${exporter}\")." ) endif() get_filename_component(in_path "${in_path}" ABSOLUTE BASE_DIR "${JUCER_TARGET_PROJECT_FOLDER}" ) set(${out_path} "${in_path}" PARENT_SCOPE) endfunction() function(_FRUT_add_bundle_resources target) if(NOT APPLE) return() endif() set(bundle_resources ${JUCER_PROJECT_XCODE_RESOURCES} ${JUCER_ICON_FILE} ${JUCER_CUSTOM_XCODE_RESOURCE_FOLDERS} ) if(IOS) list(APPEND bundle_resources ${JUCER_XCASSETS} ${JUCER_LAUNCH_STORYBOARD_FILE}) endif() target_sources(${target} PRIVATE ${bundle_resources}) set_source_files_properties(${bundle_resources} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" ) source_group("Resources" FILES ${bundle_resources}) endfunction() function(_FRUT_add_extra_commands target exporter) if(APPLE) _FRUT_add_extra_commands_APPLE(${target} "${exporter}") elseif(MSVC) _FRUT_add_extra_commands_MSVC(${target} "${exporter}") endif() endfunction() function(_FRUT_add_extra_commands_APPLE target exporter) get_target_property(target_type ${target} TYPE) if(target_type STREQUAL "EXECUTABLE" OR target_type STREQUAL "MODULE_LIBRARY") if(NOT EXISTS "${strip_exe}") unset(strip_exe CACHE) endif() find_program(strip_exe "strip") if(NOT strip_exe) message(FATAL_ERROR "Could not find strip program") endif() if(CMAKE_GENERATOR STREQUAL "Xcode") unset(all_confs_strip_exe) unset(all_confs_strip_opt) unset(all_confs_strip_arg) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_STRIP_LOCAL_SYMBOLS_${config}) string(APPEND all_confs_strip_exe $<$:${strip_exe}>) string(APPEND all_confs_strip_opt $<$:-x>) string(APPEND all_confs_strip_arg $<$:$>) endif() endforeach() if(DEFINED all_confs_strip_exe) add_custom_command(TARGET ${target} POST_BUILD COMMAND ${all_confs_strip_exe} ${all_confs_strip_opt} ${all_confs_strip_arg} ) endif() elseif(JUCER_STRIP_LOCAL_SYMBOLS_${CMAKE_BUILD_TYPE}) add_custom_command(TARGET ${target} POST_BUILD COMMAND "${strip_exe}" "-x" "$" ) endif() endif() if(DEFINED JUCER_PREBUILD_SHELL_SCRIPT) if(NOT DEFINED JUCER_TARGET_PROJECT_FOLDER) message(FATAL_ERROR "JUCER_TARGET_PROJECT_FOLDER must be defined. Give" " TARGET_PROJECT_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() if(NOT IS_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") file(MAKE_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") endif() add_custom_command(TARGET ${target} PRE_BUILD COMMAND "/bin/sh" "${JUCER_PREBUILD_SHELL_SCRIPT}" WORKING_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}" ) endif() if(DEFINED JUCER_POSTBUILD_SHELL_SCRIPT) if(NOT DEFINED JUCER_TARGET_PROJECT_FOLDER) message(FATAL_ERROR "JUCER_TARGET_PROJECT_FOLDER must be defined. Give" " TARGET_PROJECT_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() if(NOT IS_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") file(MAKE_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") endif() add_custom_command(TARGET ${target} POST_BUILD COMMAND "/bin/sh" "${JUCER_POSTBUILD_SHELL_SCRIPT}" WORKING_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}" ) endif() endfunction() function(_FRUT_add_extra_commands_MSVC target exporter) unset(all_confs_prebuild_command) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_PREBUILD_COMMAND_${config}) set(prebuild_command "${JUCER_PREBUILD_COMMAND_${config}}") string(APPEND all_confs_prebuild_command $<$:${prebuild_command}> ) endif() endforeach() if(DEFINED all_confs_prebuild_command) if(NOT DEFINED JUCER_TARGET_PROJECT_FOLDER) message(FATAL_ERROR "JUCER_TARGET_PROJECT_FOLDER must be defined. Give" " TARGET_PROJECT_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() if(NOT IS_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") file(MAKE_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") endif() add_custom_command(TARGET ${target} PRE_BUILD COMMAND ${all_confs_prebuild_command} WORKING_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}" ) endif() unset(all_confs_postbuild_command) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_POSTBUILD_COMMAND_${config}) set(postbuild_command "${JUCER_POSTBUILD_COMMAND_${config}}") string(APPEND all_confs_postbuild_command $<$:${postbuild_command}> ) endif() endforeach() if(DEFINED all_confs_postbuild_command) if(NOT DEFINED JUCER_TARGET_PROJECT_FOLDER) message(FATAL_ERROR "JUCER_TARGET_PROJECT_FOLDER must be defined. Give" " TARGET_PROJECT_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() if(NOT IS_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") file(MAKE_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}") endif() add_custom_command(TARGET ${target} POST_BUILD COMMAND ${all_confs_postbuild_command} WORKING_DIRECTORY "${JUCER_TARGET_PROJECT_FOLDER}" ) endif() endfunction() function(_FRUT_add_Rez_command_to_AU_plugin au_target) if(NOT EXISTS "${Rez_exe}") unset(Rez_exe CACHE) endif() find_program(Rez_exe "Rez") if(NOT Rez_exe) message(WARNING "Could not find Rez tool. Discovery of AU plugins might not work.") return() endif() set(rez_output "${CMAKE_CURRENT_BINARY_DIR}/${JUCER_PROJECT_NAME}.rsrc") set(audio_unit_headers "/System/Library/Frameworks/AudioUnit.framework/Headers") set(rez_defines "") set(rez_archs "") set(all_confs_sysroot "") set(all_confs_include_audio_unit_headers "") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) foreach(macos_architecture IN LISTS JUCER_MACOS_ARCHITECTURES_${config}) list(APPEND rez_defines "$<$:-d>" "$<$:${macos_architecture}_YES>" ) list(APPEND rez_archs "$<$:-arch>" "$<$:${macos_architecture}>" ) endforeach() set(sysroot "${JUCER_MACOSX_SDK_PATH_${config}}") if(IS_DIRECTORY "${sysroot}") list(APPEND all_confs_sysroot "$<$:-isysroot>" "$<$:${sysroot}>" ) list(APPEND all_confs_include_audio_unit_headers "$<$:-i>" "$<$:${sysroot}${audio_unit_headers}>" ) endif() endforeach() string(CONCAT carbon_include_dir "/System/Library/Frameworks/CoreServices.framework/Frameworks/" "CarbonCore.framework/Versions/A/Headers" ) string(CONCAT juce_audio_plugin_client_include_dir "${JUCER_PROJECT_MODULE_juce_audio_plugin_client_PATH}/" "juce_audio_plugin_client" ) add_custom_command(OUTPUT ${rez_output} COMMAND "${Rez_exe}" "-o" "${rez_output}" "-d" "SystemSevenOrLater=1" "-useDF" ${rez_defines} ${rez_archs} "-i" "${carbon_include_dir}" ${all_confs_include_audio_unit_headers} "-i" "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode" "-i" "${juce_audio_plugin_client_include_dir}" ${all_confs_sysroot} ${ARGN} ) set_source_files_properties("${rez_output}" PROPERTIES GENERATED TRUE MACOSX_PACKAGE_LOCATION "Resources" ) target_sources(${au_target} PRIVATE "${rez_output}") endfunction() function(_FRUT_bool_to_int bool_value out_int_value) if(bool_value) set(${out_int_value} 1 PARENT_SCOPE) else() set(${out_int_value} 0 PARENT_SCOPE) endif() endfunction() function(_FRUT_build_and_install_tool tool_name tool_version) set(tool_filename "${tool_name}-${tool_version}") set(install_prefix "${Reprojucer.cmake_DIR}/bin") if(NOT EXISTS "${${tool_name}_exe}" OR NOT ${tool_name}_exe MATCHES "${tool_filename}") unset(${tool_name}_exe CACHE) endif() find_program(${tool_name}_exe "${tool_filename}" PATHS "${install_prefix}" NO_DEFAULT_PATH ) if(NOT ${tool_name}_exe) set(binary_dir "${Reprojucer.cmake_DIR}/tools/_build/${CMAKE_GENERATOR}") message(STATUS "Configuring ${tool_name} in \"${binary_dir}\"") file(MAKE_DIRECTORY "${binary_dir}") execute_process( COMMAND "${CMAKE_COMMAND}" "${Reprojucer.cmake_DIR}/tools" "-G" "${CMAKE_GENERATOR}" "-DJUCE_modules_DIRS=${JUCER_PROJECT_MODULES_FOLDERS}" "-DCMAKE_INSTALL_PREFIX=${install_prefix}" "-Dbuilt_by_Reprojucer=TRUE" "-Dtool_to_build=${tool_name}" WORKING_DIRECTORY "${binary_dir}" OUTPUT_VARIABLE configure_output RESULT_VARIABLE configure_result ) set(output "${configure_output}") if(NOT configure_result EQUAL 0) _FRUT_write_failure_report_and_abort("configure" "${tool_name}" "${output}") endif() message(STATUS "Building ${tool_name} in \"${binary_dir}\"") set(build_command "${CMAKE_COMMAND}" "--build" "${binary_dir}") if(CMAKE_GENERATOR STREQUAL "Xcode") list(APPEND build_command "--" "-parallelizeTargets") elseif(NOT CMAKE_VERSION VERSION_LESS 3.12) list(APPEND build_command "--parallel") endif() execute_process( COMMAND ${build_command} OUTPUT_VARIABLE build_output RESULT_VARIABLE build_result ) string(APPEND output "\n${build_output}") if(NOT build_result EQUAL 0) _FRUT_write_failure_report_and_abort("build" "${tool_name}" "${output}") endif() message(STATUS "Installing ${tool_name} in \"${install_prefix}\"") execute_process( COMMAND "${CMAKE_COMMAND}" "--build" "${binary_dir}" "--target" "install" OUTPUT_VARIABLE install_output RESULT_VARIABLE install_result ) string(APPEND output "\n${install_output}") if(NOT install_result EQUAL 0) _FRUT_write_failure_report_and_abort("install" "${tool_name}" "${output}") endif() message(STATUS "Installed ${tool_name} in \"${install_prefix}\"") find_program(${tool_name}_exe "${tool_filename}" PATHS "${install_prefix}" NO_DEFAULT_PATH ) if(NOT ${tool_name}_exe) message(FATAL_ERROR "Could not find ${tool_filename}") endif() endif() endfunction() function(_FRUT_char_literal value out_char_literal) if(ARGC GREATER 2) if(NOT ARGV2 STREQUAL "WITH_COMMENT") message(FATAL_ERROR "Unexpected argument \"${ARGV2}\"") endif() endif() set(all_ascii_codes "") foreach(ascii_code RANGE 1 127) list(APPEND all_ascii_codes ${ascii_code}) endforeach() string(ASCII ${all_ascii_codes} all_ascii_chars) set(four_chars "${value}") if(DEFINED JUCER_VERSION AND NOT JUCER_VERSION VERSION_GREATER 5.2.0) string(STRIP "${four_chars}" four_chars) endif() string(SUBSTRING "${four_chars}" 0 4 four_chars) string(LENGTH "${four_chars}" four_chars_length) set(dec_value 0) foreach(index IN ITEMS 0 1 2 3) if(index LESS four_chars_length) string(SUBSTRING "${four_chars}" ${index} 1 ascii_char) string(FIND "${all_ascii_chars}" "${ascii_char}" ascii_code) if(ascii_code EQUAL -1) message(FATAL_ERROR "${value} cannot contain non-ASCII characters") endif() math(EXPR ascii_code "${ascii_code} + 1") else() set(ascii_code 0) endif() math(EXPR dec_value "(${dec_value} << 8) | (${ascii_code} & 255)") endforeach() _FRUT_dec_to_hex("${dec_value}" hex_value) if(ARGV2 STREQUAL "WITH_COMMENT") set(${out_char_literal} "${hex_value} // '${four_chars}'" PARENT_SCOPE) else() set(${out_char_literal} "${hex_value}" PARENT_SCOPE) endif() endfunction() function(_FRUT_check_SDK_folders exporter) if(JUCER_BUILD_VST OR JUCER_FLAG_JUCE_PLUGINHOST_VST) if(DEFINED JUCER_VST_LEGACY_SDK_FOLDER) if(NOT IS_DIRECTORY "${JUCER_VST_LEGACY_SDK_FOLDER}") message(WARNING "JUCER_VST_LEGACY_SDK_FOLDER: no such directory" " \"${JUCER_VST_LEGACY_SDK_FOLDER}\"" ) elseif(NOT EXISTS "${JUCER_VST_LEGACY_SDK_FOLDER}/pluginterfaces/vst2.x/aeffect.h") message(WARNING "JUCER_VST_LEGACY_SDK_FOLDER: \"${JUCER_VST_LEGACY_SDK_FOLDER}\"" " doesn't seem to contain the VST SDK" ) endif() elseif((NOT DEFINED JUCER_VERSION OR JUCER_VERSION VERSION_GREATER 5.3.2) AND NOT IOS) message(WARNING "JUCER_VST_LEGACY_SDK_FOLDER is not defined. You should give" " VST_LEGACY_SDK_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() if(DEFINED JUCER_VST_SDK_FOLDER) if(NOT IS_DIRECTORY "${JUCER_VST_SDK_FOLDER}") message(WARNING "JUCER_VST_SDK_FOLDER: no such directory \"${JUCER_VST_SDK_FOLDER}\"" ) elseif(NOT EXISTS "${JUCER_VST_SDK_FOLDER}/public.sdk/source/vst2.x/audioeffectx.h") message(WARNING "JUCER_VST_SDK_FOLDER: \"${JUCER_VST_SDK_FOLDER}\" doesn't seem" " to contain the VST SDK" ) endif() elseif((DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 4.2.4) AND NOT IOS) message(WARNING "JUCER_VST_SDK_FOLDER is not defined. You should give" " VST_SDK_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() endif() if(JUCER_BUILD_VST3 OR JUCER_FLAG_JUCE_PLUGINHOST_VST3) string(CONCAT juce_internal_vst3_sdk_path "${JUCER_PROJECT_MODULE_juce_audio_processors_PATH}/" "juce_audio_processors/format_types/VST3_SDK" ) if(DEFINED JUCER_VST3_SDK_FOLDER) if(NOT IS_DIRECTORY "${JUCER_VST3_SDK_FOLDER}") message(WARNING "JUCER_VST3_SDK_FOLDER: no such directory \"${JUCER_VST3_SDK_FOLDER}\"" ) elseif(NOT EXISTS "${JUCER_VST3_SDK_FOLDER}/base/source/baseiids.cpp") message(WARNING "JUCER_VST3_SDK_FOLDER: \"${JUCER_VST3_SDK_FOLDER}\" doesn't" " seem to contain the VST3 SDK" ) endif() elseif(((APPLE AND NOT IOS) OR MSVC) AND NOT EXISTS "${juce_internal_vst3_sdk_path}") message(WARNING "JUCER_VST3_SDK_FOLDER is not defined. You should give" " VST3_SDK_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() endif() if(JUCER_BUILD_RTAS) if(DEFINED JUCER_RTAS_SDK_FOLDER) set(file_to_check_for "AlturaPorts/TDMPlugIns/PlugInLibrary/EffectClasses/CEffectProcessMIDI.cpp" ) if(NOT IS_DIRECTORY "${JUCER_RTAS_SDK_FOLDER}") message(WARNING "JUCER_RTAS_SDK_FOLDER: no such directory \"${JUCER_RTAS_SDK_FOLDER}\"" ) elseif(NOT EXISTS "${JUCER_RTAS_SDK_FOLDER}/${file_to_check_for}") message(WARNING "JUCER_RTAS_SDK_FOLDER: \"${JUCER_RTAS_SDK_FOLDER}\" doesn't" " seem to contain the RTAS SDK" ) endif() elseif((APPLE AND NOT IOS) OR MSVC) message(WARNING "JUCER_RTAS_SDK_FOLDER is not defined. You should give" " RTAS_SDK_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() endif() if(JUCER_BUILD_AAX) if(DEFINED JUCER_AAX_SDK_FOLDER) if(NOT IS_DIRECTORY "${JUCER_AAX_SDK_FOLDER}") message(WARNING "JUCER_AAX_SDK_FOLDER: no such directory \"${JUCER_AAX_SDK_FOLDER}\"" ) elseif(NOT EXISTS "${JUCER_AAX_SDK_FOLDER}/Interfaces/AAX_Exports.cpp") message(WARNING "JUCER_AAX_SDK_FOLDER: \"${JUCER_AAX_SDK_FOLDER}\" doesn't" " seem to contain the AAX SDK" ) endif() elseif((APPLE AND NOT IOS) OR MSVC) message(WARNING "JUCER_AAX_SDK_FOLDER is not defined. You should give" " AAX_SDK_FOLDER when calling jucer_export_target(\"${exporter}\")." ) endif() endif() endfunction() function(_FRUT_compute_rtas_aax_category RTAS_or_AAX category_prefix out_var) set(category_suffixes "None" "EQ" "Dynamics" "PitchShift" "Reverb" "Delay" "Modulation" "Harmonic" "NoiseReduction" "Dither" "SoundField" "HWGenerators" "SWGenerators" "WrappedPlugin" "Effect" ) set(categories_as_int 0) foreach(category IN LISTS JUCER_PLUGIN_${RTAS_or_AAX}_CATEGORY) if(NOT category MATCHES "^${category_prefix}_(.+)$" OR NOT CMAKE_MATCH_1 IN_LIST category_suffixes) message(WARNING "Ignoring unknown ${RTAS_or_AAX} category: ${category}") continue() endif() list(FIND category_suffixes "${CMAKE_MATCH_1}" suffix_index) if(suffix_index EQUAL 0) set(category_as_int 0) else() math(EXPR category_as_int "1 << (${suffix_index} - 1)") endif() math(EXPR categories_as_int "${categories_as_int} | ${category_as_int}") endforeach() set(${out_var} "${categories_as_int}" PARENT_SCOPE) endfunction() function(_FRUT_compute_vst3_category out_var) set(categories "${JUCER_PLUGIN_VST3_CATEGORY}") # See getVST3CategoryStringFromSelection() # in JUCE/extras/Projucer/Source/Project/jucer_Project.cpp if(NOT "Fx" IN_LIST categories AND NOT "Instrument" IN_LIST categories) if(JUCER_PLUGIN_IS_A_SYNTH) list(INSERT categories 0 "Instrument") else() list(INSERT categories 0 "Fx") endif() else() if("Instrument" IN_LIST categories) list(FIND categories "Instrument" Instrument_index) list(REMOVE_AT categories ${Instrument_index}) list(INSERT categories 0 "Instrument") endif() if("Fx" IN_LIST categories) list(FIND categories "Fx" Fx_index) list(REMOVE_AT categories ${Fx_index}) list(INSERT categories 0 "Fx") endif() endif() list(LENGTH categories categories_count) if(categories_count EQUAL 1) set(vst3_category "${categories}") else() list(GET categories 0 first_category) set(vst3_category "${first_category}") math(EXPR categories_max "${categories_count} - 1") foreach(index RANGE 1 ${categories_max}) list(GET categories ${index} category) string(APPEND vst3_category "|${category}") endforeach() endif() set(${out_var} "${vst3_category}" PARENT_SCOPE) endfunction() function(_FRUT_create_xcassets_folder_from_icons out_var) _FRUT_build_and_install_tool("XcassetsBuilder" "0.1.0") set(XcassetsBuilder_args "${CMAKE_CURRENT_BINARY_DIR}/${JUCER_PROJECT_NAME}") if(DEFINED JUCER_SMALL_ICON) list(APPEND XcassetsBuilder_args "${JUCER_SMALL_ICON}") else() list(APPEND XcassetsBuilder_args "") endif() if(DEFINED JUCER_LARGE_ICON) list(APPEND XcassetsBuilder_args "${JUCER_LARGE_ICON}") else() list(APPEND XcassetsBuilder_args "") endif() execute_process( COMMAND "${XcassetsBuilder_exe}" ${XcassetsBuilder_args} OUTPUT_VARIABLE xcassets_path RESULT_VARIABLE XcassetsBuilder_return_code ) if(NOT XcassetsBuilder_return_code EQUAL 0) message(FATAL_ERROR "Error when executing XcassetsBuilder") endif() set(${out_var} "${xcassets_path}" PARENT_SCOPE) endfunction() function(_FRUT_dec_to_hex dec_value out_hex_value) if(dec_value EQUAL 0) set(${out_hex_value} "0x0" PARENT_SCOPE) return() endif() if(dec_value LESS 0) math(EXPR dec_value "2147483647 ${dec_value} + 1") endif() while(dec_value GREATER 0) math(EXPR hex_unit "${dec_value} & 15") if(hex_unit LESS 10) set(hex_char "${hex_unit}") else() math(EXPR hex_unit "${hex_unit} + 87") string(ASCII ${hex_unit} hex_char) endif() set(hex_value "${hex_char}${hex_value}") math(EXPR dec_value "${dec_value} >> 4") endwhile() set(${out_hex_value} "0x${hex_value}" PARENT_SCOPE) endfunction() function(_FRUT_generate_AppConfig_and_JucePluginDefines_header) if(DEFINED JUCER_APPCONFIG_USER_CODE_SECTION) set(user_code_section "\n${JUCER_APPCONFIG_USER_CODE_SECTION}\n") if(user_code_section STREQUAL "\n\n") set(user_code_section "\n") endif() else() string(CONCAT user_code_section "\n\n// (You can get your own code in this section by" " calling jucer_appconfig_header)\n\n" ) endif() if(DEFINED JUCER_DISPLAY_THE_JUCE_SPLASH_SCREEN AND NOT JUCER_DISPLAY_THE_JUCE_SPLASH_SCREEN) set(display_splash_screen 0) else() set(display_splash_screen 1) endif() if(DEFINED JUCER_REPORT_JUCE_APP_USAGE AND NOT JUCER_REPORT_JUCE_APP_USAGE) set(report_app_usage 0) else() set(report_app_usage 1) endif() if(DEFINED JUCER_SPLASH_SCREEN_COLOUR AND NOT JUCER_SPLASH_SCREEN_COLOUR STREQUAL "Dark") set(use_dark_splash_screen 0) else() set(use_dark_splash_screen 1) endif() set(max_right_padding 0) foreach(module_name IN LISTS JUCER_PROJECT_MODULES) string(LENGTH "${module_name}" module_name_length) if(module_name_length GREATER max_right_padding) set(max_right_padding ${module_name_length}) endif() endforeach() math(EXPR max_right_padding "${max_right_padding} + 5") set(module_available_defines "") set(config_flags_defines "") foreach(module_name IN LISTS JUCER_PROJECT_MODULES) string(LENGTH "${module_name}" right_padding) set(padding_spaces "") while(right_padding LESS max_right_padding) string(APPEND padding_spaces " ") math(EXPR right_padding "${right_padding} + 1") endwhile() string(APPEND module_available_defines "#define JUCE_MODULE_AVAILABLE_${module_name}${padding_spaces} 1\n" ) if(JUCER_${module_name}_CONFIG_FLAGS) string(APPEND config_flags_defines "\n" "//==============================================================================" "\n// ${module_name} flags:\n" ) endif() foreach(config_flag IN LISTS JUCER_${module_name}_CONFIG_FLAGS) string(APPEND config_flags_defines "\n#ifndef ${config_flag}\n") if(NOT DEFINED JUCER_FLAG_${config_flag}) string(APPEND config_flags_defines " //#define ${config_flag}\n") elseif(JUCER_FLAG_${config_flag}) string(APPEND config_flags_defines " #define ${config_flag} 1\n") else() string(APPEND config_flags_defines " #define ${config_flag} 0\n") endif() string(APPEND config_flags_defines "#endif\n") endforeach() endforeach() set(is_standalone_application 1) if(JUCER_PROJECT_TYPE STREQUAL "Dynamic Library") set(is_standalone_application 0) elseif(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") set(is_standalone_application 0) _FRUT_get_audio_plugin_flags(audio_plugin_flags WITH_COMMENTS) string(CONCAT audio_plugin_settings_defines "\n" "//==============================================================================\n" "// Audio plugin settings..\n\n" ) foreach(flag IN LISTS audio_plugin_flags) string(LENGTH "JucePlugin_${flag}" right_padding) set(padding_spaces "") while(right_padding LESS 32) string(APPEND padding_spaces " ") math(EXPR right_padding "${right_padding} + 1") endwhile() string(APPEND audio_plugin_settings_defines "#ifndef JucePlugin_${flag}\n" " #define JucePlugin_${flag}${padding_spaces} ${${flag}_value}\n" "#endif\n" ) endforeach() endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) string(TOUPPER "${JUCER_PROJECT_ID}" upper_project_id) set(template_file "${Reprojucer_data_DIR}/AppConfig-4.h.in") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) set(template_file "${Reprojucer_data_DIR}/AppConfig-5.h.in") else() if(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") string(STRIP "${audio_plugin_settings_defines}" audio_plugin_settings_defines) configure_file("${Reprojucer_data_DIR}/JucePluginDefines.h.in" "JuceLibraryCode/JucePluginDefines.h" @ONLY ) list(APPEND JUCER_PROJECT_FILES "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/JucePluginDefines.h" ) set(include_JucePluginDefines_header "\n#include \"JucePluginDefines.h\"\n") endif() set(template_file "${Reprojucer_data_DIR}/AppConfig.h.in") endif() if(NOT DEFINED JUCER_USE_GLOBAL_APPCONFIG_HEADER OR JUCER_USE_GLOBAL_APPCONFIG_HEADER) configure_file("${template_file}" "JuceLibraryCode/AppConfig.h" @ONLY) list(APPEND JUCER_PROJECT_FILES "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/AppConfig.h" ) endif() set(JUCER_PROJECT_FILES "${JUCER_PROJECT_FILES}" PARENT_SCOPE) endfunction() function(_FRUT_generate_entitlements_file target output_filename out_var) set(entitlements_content "") if(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") if(IOS AND JUCER_ENABLE_INTER_APP_AUDIO) string(APPEND entitlements_content "\tinter-app-audio\n" "\t\n") endif() else() if(JUCER_PUSH_NOTIFICATIONS_CAPABILITY) if(IOS) string(APPEND entitlements_content "\taps-environment\n") else() string(APPEND entitlements_content "\tcom.apple.developer.aps-environment\n" ) endif() string(APPEND entitlements_content "\tdevelopment\n") endif() endif() if(JUCER_APP_GROUPS_CAPABILITY) string(APPEND entitlements_content "\tcom.apple.security.application-groups\n" "\t\n" ) foreach(group IN LISTS JUCER_APP_GROUP_ID) string(STRIP "${group}" group) string(APPEND entitlements_content "\t\t${group}\n") endforeach() string(APPEND entitlements_content "\t\n") endif() if(JUCER_USE_HARDENED_RUNTIME) foreach(option IN LISTS JUCER_HARDENED_RUNTIME_OPTIONS) string(APPEND entitlements_content "\t${option}\n" "\t\n") endforeach() endif() if(JUCER_USE_APP_SANDBOX OR ( NOT IOS AND JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in" AND target MATCHES "_AUv3_AppExtension$" )) string(APPEND entitlements_content "\tcom.apple.security.app-sandbox\n" "\t\n" ) if(JUCER_APP_SANDBOX_INHERITANCE) if(JUCER_APP_SANDBOX_OPTIONS) message(WARNING "Setting APP_SANDBOX_OPTIONS in addition to enabling" " APP_SANDBOX_INHERITANCE can make child processes fail to launch." ) endif() string(APPEND entitlements_content "\tcom.apple.security.inherit\n" "\t\n" ) endif() endif() if(JUCER_USE_APP_SANDBOX) foreach(option IN LISTS JUCER_APP_SANDBOX_OPTIONS) string(APPEND entitlements_content "\t${option}\n" "\t\n") endforeach() endif() if(IOS AND JUCER_ICLOUD_PERMISSIONS) string(APPEND entitlements_content "\tcom.apple.developer.icloud-container-identifiers\n" "\t\n" " iCloud.$(CFBundleIdentifier)\n" " \n" "\tcom.apple.developer.icloud-services\n" "\t\n" " CloudDocuments\n" " \n" "\tcom.apple.developer.ubiquity-container-identifiers\n" "\t\n" " iCloud.$(CFBundleIdentifier)\n" " \n" ) endif() configure_file("${Reprojucer_data_DIR}/target.entitlements.in" "${output_filename}" @ONLY ) set(${out_var} "${CMAKE_CURRENT_BINARY_DIR}/${output_filename}" PARENT_SCOPE) endfunction() function(_FRUT_generate_icon_file icon_format icon_file_output_dir out_icon_filename) _FRUT_build_and_install_tool("IconBuilder" "0.2.0") if(DEFINED JUCER_VERSION) set(projucer_version "${JUCER_VERSION}") else() set(projucer_version "latest") endif() set(IconBuilder_args "${projucer_version}" "${icon_format}" "${icon_file_output_dir}") if(DEFINED JUCER_SMALL_ICON) list(APPEND IconBuilder_args "${JUCER_SMALL_ICON}") else() list(APPEND IconBuilder_args "") endif() if(DEFINED JUCER_LARGE_ICON) list(APPEND IconBuilder_args "${JUCER_LARGE_ICON}") else() list(APPEND IconBuilder_args "") endif() execute_process( COMMAND "${IconBuilder_exe}" ${IconBuilder_args} OUTPUT_VARIABLE icon_filename RESULT_VARIABLE IconBuilder_return_code ) if(NOT IconBuilder_return_code EQUAL 0) message(FATAL_ERROR "Error when executing IconBuilder") endif() if(NOT "${icon_filename}" STREQUAL "") set(${out_icon_filename} "${icon_filename}" PARENT_SCOPE) endif() endfunction() function(_FRUT_generate_JuceHeader_header) list(LENGTH JUCER_PROJECT_RESOURCES resources_count) if(resources_count GREATER 0) _FRUT_build_and_install_tool("BinaryDataBuilder" "0.3.1") if(DEFINED JUCER_VERSION) set(projucer_version "${JUCER_VERSION}") else() set(projucer_version "latest") endif() if(DEFINED JUCER_PROJECT_ID) set(project_uid "${JUCER_PROJECT_ID}") else() set(project_uid "FRUT") endif() if(NOT DEFINED JUCER_BINARYDATACPP_SIZE_LIMIT) set(JUCER_BINARYDATACPP_SIZE_LIMIT 10240) endif() math(EXPR size_limit_in_bytes "${JUCER_BINARYDATACPP_SIZE_LIMIT} * 1024") if(NOT DEFINED size_limit_in_bytes) message(FATAL_ERROR "Error when computing size_limit_in_bytes =" " ${JUCER_BINARYDATACPP_SIZE_LIMIT} * 1024" ) endif() if("${JUCER_BINARYDATA_NAMESPACE}" STREQUAL "") set(JUCER_BINARYDATA_NAMESPACE "BinaryData") endif() set(BinaryDataBuilder_args "${projucer_version}" "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/" "${project_uid}" ${size_limit_in_bytes} "${JUCER_BINARYDATA_NAMESPACE}" ) foreach(resource_path IN LISTS JUCER_PROJECT_RESOURCES) get_filename_component(resource_abs_path "${resource_path}" ABSOLUTE) list(APPEND BinaryDataBuilder_args "${resource_abs_path}") endforeach() execute_process( COMMAND "${BinaryDataBuilder_exe}" ${BinaryDataBuilder_args} OUTPUT_VARIABLE binary_data_filenames RESULT_VARIABLE BinaryDataBuilder_return_code ) if(NOT BinaryDataBuilder_return_code EQUAL 0) message(FATAL_ERROR "Error when executing BinaryDataBuilder") endif() foreach(filename IN LISTS binary_data_filenames) list(APPEND JUCER_PROJECT_FILES "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/${filename}" ) endforeach() if(DEFINED JUCER_INCLUDE_BINARYDATA AND NOT JUCER_INCLUDE_BINARYDATA) set(binary_data_include "") else() set(binary_data_include "#include \"BinaryData.h\"\n") endif() endif() if(DEFINED JUCER_USE_GLOBAL_APPCONFIG_HEADER AND NOT JUCER_USE_GLOBAL_APPCONFIG_HEADER) set(appconfig_include "") else() set(appconfig_include "#include \"AppConfig.h\"\n") endif() set(modules_includes "") if(JUCER_PROJECT_MODULES) set(modules_includes "\n") endif() foreach(module_name IN LISTS JUCER_PROJECT_MODULES) string(APPEND modules_includes "#include <${module_name}/${module_name}.h>\n") endforeach() if(JUCER_PROJECT_MODULES) string(APPEND modules_includes "\n") endif() if(DEFINED JUCER_ADD_USING_NAMESPACE_JUCE_TO_JUCE_HEADER AND NOT JUCER_ADD_USING_NAMESPACE_JUCE_TO_JUCE_HEADER) set(using_namespace_juce_block "") else() string(CONCAT using_namespace_juce_block "#if ! DONT_SET_USING_JUCE_NAMESPACE\n" " // If your code uses a lot of JUCE classes, then this will obviously save you\n" " // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE.\n" " using namespace juce;\n" "#endif\n\n" ) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2) set(company_name_field "") else() string(CONCAT company_name_field "\n" " const char* const companyName = \"${JUCER_COMPANY_NAME}\";" ) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) string(TOUPPER "${JUCER_PROJECT_ID}" upper_project_id) string(CONCAT include_guard_top "#ifndef __APPHEADERFILE_${upper_project_id}__\n" "#define __APPHEADERFILE_${upper_project_id}__" ) set(include_guard_bottom "\n\n#endif // __APPHEADERFILE_${upper_project_id}__") else() set(include_guard_top "#pragma once") set(include_guard_bottom "") endif() configure_file("${Reprojucer_data_DIR}/JuceHeader.h.in" "JuceLibraryCode/JuceHeader.h" @ONLY ) list(APPEND JUCER_PROJECT_FILES "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode/JuceHeader.h" ) set(JUCER_PROJECT_FILES "${JUCER_PROJECT_FILES}" PARENT_SCOPE) endfunction() function(_FRUT_generate_plist_file target plist_suffix bundle_package_type bundle_signature ) if(DEFINED JUCER_EXPORTER_BUNDLE_IDENTIFIER AND NOT JUCER_EXPORTER_BUNDLE_IDENTIFIER STREQUAL "") set(bundle_identifier "${JUCER_EXPORTER_BUNDLE_IDENTIFIER}") else() set(bundle_identifier "${JUCER_BUNDLE_IDENTIFIER}") endif() if(target MATCHES "_AUv3_AppExtension$") # com.yourcompany.NewProject -> com.yourcompany.NewProject.NewProjectAUv3 string(REPLACE "." ";" bundle_id_parts "${bundle_identifier}") list(LENGTH bundle_id_parts bundle_id_parts_length) math(EXPR bundle_id_parts_last_index "${bundle_id_parts_length} - 1") list(GET bundle_id_parts ${bundle_id_parts_last_index} bundle_id_last_part) list(APPEND bundle_id_parts "${bundle_id_last_part}AUv3") string(REPLACE ";" "." bundle_identifier "${bundle_id_parts}") endif() set(plist_filename "Info-${plist_suffix}.plist") if(CMAKE_GENERATOR STREQUAL "Xcode") if(JUCER_PLIST_PREPROCESS) set(infoplist_preprocess "YES") else() set(infoplist_preprocess "NO") endif() set(bundle_executable "\${EXECUTABLE_NAME}") set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_INFOPLIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/${plist_filename}" XCODE_ATTRIBUTE_INFOPLIST_PREPROCESS "${infoplist_preprocess}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_identifier}" ) if(DEFINED JUCER_PLIST_PREFIX_HEADER AND NOT JUCER_PLIST_PREFIX_HEADER STREQUAL "") set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_INFOPLIST_PREFIX_HEADER "${JUCER_PLIST_PREFIX_HEADER}" ) endif() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_PLIST_PREPROCESSOR_DEFINITIONS_${config}) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_INFOPLIST_PREPROCESSOR_DEFINITIONS[variant=${config}] "${JUCER_PLIST_PREPROCESSOR_DEFINITIONS_${config}}" ) endif() endforeach() else() set(bundle_executable "\${MACOSX_BUNDLE_EXECUTABLE_NAME}") set_target_properties(${target} PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "${bundle_identifier}" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/${plist_filename}" ) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.0) if(CMAKE_GENERATOR STREQUAL "Xcode") set(bundle_identifier_in_plist "\$(PRODUCT_BUNDLE_IDENTIFIER)") else() set(bundle_identifier_in_plist "\${MACOSX_BUNDLE_GUI_IDENTIFIER}") endif() else() set(bundle_identifier_in_plist "${bundle_identifier}") endif() set(plist_entries "") if(JUCER_MICROPHONE_ACCESS) if(DEFINED JUCER_MICROPHONE_ACCESS_TEXT) set(microphone_usage_description "${JUCER_MICROPHONE_ACCESS_TEXT}") else() string(CONCAT microphone_usage_description "This app requires audio input. If you" " do not have an audio interface connected it will use the built-in microphone." ) endif() string(APPEND plist_entries " NSMicrophoneUsageDescription ${microphone_usage_description}" ) endif() if(JUCER_CAMERA_ACCESS) if(DEFINED JUCER_CAMERA_ACCESS_TEXT) set(camera_usage_description "${JUCER_CAMERA_ACCESS_TEXT}") else() string(CONCAT camera_usage_description "This app requires access to the camera to" " function correctly." ) endif() string(APPEND plist_entries " NSCameraUsageDescription ${camera_usage_description}" ) endif() if(JUCER_BLUETOOTH_ACCESS) if(DEFINED JUCER_BLUETOOTH_ACCESS_TEXT) set(bluetooth_usage_description "${JUCER_BLUETOOTH_ACCESS_TEXT}") else() string(CONCAT bluetooth_usage_description "This app requires access to Bluetooth to" " function correctly." ) endif() string(APPEND plist_entries " NSBluetoothAlwaysUsageDescription ${bluetooth_usage_description}" ) endif() if(IOS) if(JUCER_BLUETOOTH_ACCESS) string(APPEND plist_entries " NSBluetoothPeripheralUsageDescription ${bluetooth_usage_description}" ) endif() string(APPEND plist_entries " LSRequiresIPhoneOS " ) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.8) if(NOT target MATCHES "_AUv3_AppExtension$") string(APPEND plist_entries " UIViewControllerBasedStatusBarAppearance " ) endif() else() string(APPEND plist_entries " UIViewControllerBasedStatusBarAppearance " ) endif() if( (DEFINED JUCER_CUSTOM_LAUNCH_STORYBOARD AND NOT JUCER_CUSTOM_LAUNCH_STORYBOARD STREQUAL "") OR (NOT DEFINED JUCER_CUSTOM_XCASSETS_FOLDER OR JUCER_CUSTOM_XCASSETS_FOLDER STREQUAL "") ) set(storyboard_name "${JUCER_CUSTOM_LAUNCH_STORYBOARD}") if(storyboard_name STREQUAL "") set(storyboard_name "LaunchScreen") else() get_filename_component(storyboard_name "${storyboard_name}" NAME) string(REGEX REPLACE "[.]storyboard$" "" storyboard_name "${storyboard_name}") endif() string(APPEND plist_entries " UILaunchStoryboardName ${storyboard_name}" ) endif() else() if(JUCER_SEND_APPLE_EVENTS) if(DEFINED JUCER_SEND_APPLE_EVENTS_TEXT) set(apple_events_usage_description "${JUCER_SEND_APPLE_EVENTS_TEXT}") else() string(CONCAT apple_events_usage_description "This app requires the ability to" " send Apple events to function correctly." ) endif() string(APPEND plist_entries " NSAppleEventsUsageDescription ${apple_events_usage_description}" ) endif() endif() string(APPEND plist_entries " CFBundleExecutable ${bundle_executable}" ) if(NOT IOS) get_filename_component(bundle_icon_file "${JUCER_ICON_FILE}" NAME) string(APPEND plist_entries " CFBundleIconFile ${bundle_icon_file}" ) endif() if(DEFINED JUCER_COMPANY_COPYRIGHT OR NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.0)) set(ns_human_readable_copyright "@JUCER_COMPANY_COPYRIGHT@") else() set(ns_human_readable_copyright "@JUCER_COMPANY_NAME@") endif() string(APPEND plist_entries " CFBundleIdentifier ${bundle_identifier_in_plist} CFBundleName @JUCER_PROJECT_NAME@ CFBundleDisplayName @JUCER_PROJECT_NAME@ CFBundlePackageType ${bundle_package_type} CFBundleSignature ${bundle_signature} CFBundleShortVersionString @JUCER_PROJECT_VERSION@ CFBundleVersion @JUCER_PROJECT_VERSION@ NSHumanReadableCopyright ${ns_human_readable_copyright} NSHighResolutionCapable " ) list(LENGTH JUCER_DOCUMENT_FILE_EXTENSIONS file_extensions_length) if(file_extensions_length GREATER 0 AND NOT target MATCHES "_AUv3_AppExtension$") set(bundle_type_extensions "") foreach(type_extension IN LISTS JUCER_DOCUMENT_FILE_EXTENSIONS) if(type_extension MATCHES "^\\.") string(SUBSTRING "${type_extension}" 1 -1 type_extension) endif() string(APPEND bundle_type_extensions "\n ${type_extension}" ) endforeach() list(GET JUCER_DOCUMENT_FILE_EXTENSIONS 0 first_type_extension) if(first_type_extension MATCHES "^\\.") string(SUBSTRING "${first_type_extension}" 1 -1 first_type_extension) endif() string(APPEND plist_entries " CFBundleDocumentTypes CFBundleTypeExtensions ${bundle_type_extensions} CFBundleTypeName ${first_type_extension} CFBundleTypeRole Editor CFBundleTypeIconFile Icon NSPersistentStoreTypeKey XML " ) endif() if(JUCER_FILE_SHARING_ENABLED AND NOT target MATCHES "_AUv3_AppExtension$") string(APPEND plist_entries " UIFileSharingEnabled " ) endif() if(JUCER_SUPPORT_DOCUMENT_BROWSER) string(APPEND plist_entries " UISupportsDocumentBrowser " ) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.8 AND JUCER_STATUS_BAR_HIDDEN AND NOT target MATCHES "_AUv3_AppExtension$") string(APPEND plist_entries " UIStatusBarHidden " ) endif() if(IOS AND NOT target MATCHES "_AUv3_AppExtension$") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.8) string(APPEND plist_entries " UIRequiresFullScreen " ) if(NOT JUCER_STATUS_BAR_HIDDEN) string(APPEND plist_entries " UIStatusBarHidden " ) endif() else() if(JUCER_STATUS_BAR_HIDDEN) string(APPEND plist_entries " UIStatusBarHidden " ) endif() if(NOT DEFINED JUCER_REQUIRES_FULL_SCREEN OR JUCER_REQUIRES_FULL_SCREEN) string(APPEND plist_entries " UIRequiresFullScreen " ) else() string(APPEND plist_entries " UIRequiresFullScreen " ) endif() endif() set(default_screen_orientations "UIInterfaceOrientationPortrait" "UIInterfaceOrientationLandscapeLeft" "UIInterfaceOrientationLandscapeRight" ) string(APPEND plist_entries " UISupportedInterfaceOrientations " ) if(DEFINED JUCER_IPHONE_SCREEN_ORIENTATIONS) set(iphone_screen_orientations "${JUCER_IPHONE_SCREEN_ORIENTATIONS}") else() set(iphone_screen_orientations "${default_screen_orientations}") endif() foreach(item IN LISTS iphone_screen_orientations) string(APPEND plist_entries " ${item}" ) endforeach() string(APPEND plist_entries "\n ") if(DEFINED JUCER_IPAD_SCREEN_ORIENTATIONS) set(ipad_screen_orientations "${JUCER_IPAD_SCREEN_ORIENTATIONS}") else() set(ipad_screen_orientations "${default_screen_orientations}") endif() if(NOT ipad_screen_orientations STREQUAL iphone_screen_orientations) string(APPEND plist_entries " UISupportedInterfaceOrientations~ipad " ) foreach(item IN LISTS ipad_screen_orientations) string(APPEND plist_entries " ${item}" ) endforeach() string(APPEND plist_entries "\n ") endif() string(APPEND plist_entries "\n UIBackgroundModes") if(JUCER_AUDIO_BACKGROUND_CAPABILITY OR JUCER_BLUETOOTH_MIDI_BACKGROUND_CAPABILITY OR JUCER_PUSH_NOTIFICATIONS_CAPABILITY) string(APPEND plist_entries "\n ") if(JUCER_AUDIO_BACKGROUND_CAPABILITY) string(APPEND plist_entries "\n audio") endif() if(JUCER_BLUETOOTH_MIDI_BACKGROUND_CAPABILITY) string(APPEND plist_entries "\n bluetooth-central") endif() if(JUCER_PUSH_NOTIFICATIONS_CAPABILITY) string(APPEND plist_entries "\n remote-notification") endif() string(APPEND plist_entries "\n ") else() string(APPEND plist_entries "\n ") endif() endif() _FRUT_version_to_dec("${JUCER_PROJECT_VERSION}" dec_version) if(IOS AND target MATCHES "_StandalonePlugin$" AND JUCER_ENABLE_INTER_APP_AUDIO) _FRUT_get_iaa_type_code(iaa_type_code) string(APPEND plist_entries " AudioComponents name @JUCER_PLUGIN_MANUFACTURER@: @JUCER_PLUGIN_NAME@ manufacturer @JUCER_PLUGIN_MANUFACTURER_CODE@ type ${iaa_type_code} subtype @JUCER_PLUGIN_CODE@ version ${dec_version} " ) endif() if(target MATCHES "_AU$") _FRUT_get_au_main_type_code(au_main_type_code) string(APPEND plist_entries " AudioComponents name @JUCER_PLUGIN_MANUFACTURER@: @JUCER_PLUGIN_NAME@ description @JUCER_PLUGIN_DESCRIPTION@ factoryFunction @JUCER_PLUGIN_AU_EXPORT_PREFIX@Factory manufacturer @JUCER_PLUGIN_MANUFACTURER_CODE@ type ${au_main_type_code} subtype @JUCER_PLUGIN_CODE@ version ${dec_version}" ) if(JUCER_PLUGIN_AU_IS_SANDBOX_SAFE) string(APPEND plist_entries " sandboxSafe " ) elseif(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.4.0) AND NOT JUCER_SUPPRESS_AUDIOUNIT_PLIST_RESOURCE_USAGE_KEY) string(APPEND plist_entries " resourceUsage network.client temporary-exception.files.all.read-write " ) endif() string(APPEND plist_entries " " ) endif() if(target MATCHES "_AUv3_AppExtension$") _FRUT_get_au_main_type_code(au_main_type_code) _FRUT_version_to_dec("${JUCER_PROJECT_VERSION}" dec_version) if(JUCER_PLUGIN_IS_A_SYNTH) set(tag "Synth") else() set(tag "Effects") endif() string(APPEND plist_entries " NSExtension NSExtensionPrincipalClass @JUCER_PLUGIN_AU_EXPORT_PREFIX@FactoryAUv3 NSExtensionPointIdentifier com.apple.AudioUnit-UI NSExtensionAttributes AudioComponents name @JUCER_PLUGIN_MANUFACTURER@: @JUCER_PLUGIN_NAME@ description @JUCER_PLUGIN_DESCRIPTION@ factoryFunction @JUCER_PLUGIN_AU_EXPORT_PREFIX@FactoryAUv3 manufacturer @JUCER_PLUGIN_MANUFACTURER_CODE@ type ${au_main_type_code} subtype @JUCER_PLUGIN_CODE@ version ${dec_version} sandboxSafe tags ${tag} " ) endif() if(JUCER_CUSTOM_PLIST) _FRUT_build_and_install_tool("PListMerger" "0.1.0") execute_process( COMMAND "${PListMerger_exe}" "${JUCER_CUSTOM_PLIST}" "${plist_entries}" OUTPUT_VARIABLE PListMerger_output OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE PListMerger_return_code ) if(NOT PListMerger_return_code EQUAL 0) message(FATAL_ERROR "Error when executing PListMerger") endif() if(WIN32) string(REPLACE "\r\n" "\n" PListMerger_output "${PListMerger_output}") endif() string(REPLACE "\n " "" PListMerger_output "${PListMerger_output}") string(REPLACE "\n \n" "" PListMerger_output "${PListMerger_output}") set(plist_entries "${PListMerger_output}") endif() string(CONFIGURE "${plist_entries}" plist_entries @ONLY) configure_file("${Reprojucer_data_DIR}/Info.plist.in" "${plist_filename}" @ONLY) endfunction() function(_FRUT_generate_resources_rc_file output_path) set(rc_keys "CompanyName" "LegalCopyright" "FileDescription" "FileVersion" "ProductName" "ProductVersion" ) set(rc_values "JUCER_COMPANY_NAME" "JUCER_COMPANY_COPYRIGHT" "JUCER_PROJECT_NAME" "JUCER_PROJECT_VERSION" "JUCER_PROJECT_NAME" "JUCER_PROJECT_VERSION" ) set(rc_string_file_info_values "") foreach(index RANGE 5) list(GET rc_keys ${index} rc_key) list(GET rc_values ${index} rc_value) if(DEFINED ${rc_value} AND NOT ${rc_value} STREQUAL "") string(APPEND rc_string_file_info_values " VALUE \"${rc_key}\", \"${${rc_value}}\\0\"\n" ) endif() endforeach() if(JUCER_ICON_FILE) get_filename_component(icon_filename "${JUCER_ICON_FILE}" NAME) string(CONCAT resources_rc_icon_settings "\n" "\nIDI_ICON1 ICON DISCARDABLE \"${icon_filename}\"" "\nIDI_ICON2 ICON DISCARDABLE \"${icon_filename}\"" ) endif() string(REPLACE "." ";" version_parts "${JUCER_PROJECT_VERSION}") list(LENGTH version_parts version_parts_length) while(version_parts_length LESS 4) list(APPEND version_parts 0) list(LENGTH version_parts version_parts_length) endwhile() string(REPLACE ";" "," comma_separated_version_number "${version_parts}") configure_file("${Reprojucer_data_DIR}/resources.rc.in" "${output_path}" @ONLY) endfunction() function(_FRUT_get_au_main_type_code out_value) if(NOT DEFINED JUCER_PLUGIN_AU_MAIN_TYPE OR JUCER_PLUGIN_AU_MAIN_TYPE STREQUAL "") if(JUCER_MIDI_EFFECT_PLUGIN) set(code "aumi") elseif(JUCER_PLUGIN_IS_A_SYNTH) set(code "aumu") elseif(JUCER_PLUGIN_MIDI_INPUT) set(code "aumf") else() set(code "aufx") endif() else() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1) set(code "${JUCER_PLUGIN_AU_MAIN_TYPE}") else() _FRUT_get_au_quoted_four_chars("${JUCER_PLUGIN_AU_MAIN_TYPE}" quoted_four_chars) string(REPLACE "'" "" code "${quoted_four_chars}") endif() endif() set(${out_value} "${code}" PARENT_SCOPE) endfunction() function(_FRUT_get_au_quoted_four_chars au_enum_case out_var) if(au_enum_case STREQUAL "kAudioUnitType_Effect") set(quoted_four_chars "'aufx'") elseif(au_enum_case STREQUAL "kAudioUnitType_FormatConverter") set(quoted_four_chars "'aufc'") elseif(au_enum_case STREQUAL "kAudioUnitType_Generator") set(quoted_four_chars "'augn'") elseif(au_enum_case STREQUAL "kAudioUnitType_MIDIProcessor") set(quoted_four_chars "'aumi'") elseif(au_enum_case STREQUAL "kAudioUnitType_Mixer") set(quoted_four_chars "'aumx'") elseif(au_enum_case STREQUAL "kAudioUnitType_MusicDevice") set(quoted_four_chars "'aumu'") elseif(au_enum_case STREQUAL "kAudioUnitType_MusicEffect") set(quoted_four_chars "'aumf'") elseif(au_enum_case STREQUAL "kAudioUnitType_OfflineEffect") set(quoted_four_chars "'auol'") elseif(au_enum_case STREQUAL "kAudioUnitType_Output") set(quoted_four_chars "'auou'") elseif(au_enum_case STREQUAL "kAudioUnitType_Panner") set(quoted_four_chars "'aupn'") else() message(WARNING "Unknown Audio Unit type \"${au_enum_case}\", not converting it to" " four chars literal." ) set(quoted_four_chars "${au_enum_case}") endif() set(${out_var} "${quoted_four_chars}" PARENT_SCOPE) endfunction() function(_FRUT_get_audio_plugin_flags out_var) if(ARGC GREATER 1) if(NOT ARGV1 STREQUAL "WITH_COMMENTS") message(FATAL_ERROR "Unexpected argument \"${ARGV1}\"") endif() endif() # See Project::getAudioPluginFlags() # in JUCE/extras/Projucer/Source/Project/jucer_Project.cpp set(audio_plugin_flags "Build_VST" "Build_VST3" "Build_AU" "Build_AUv3" "Build_RTAS" "Build_AAX" ) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) list(APPEND audio_plugin_flags "Build_STANDALONE") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.1.0) list(APPEND audio_plugin_flags "Build_Standalone") list(APPEND audio_plugin_flags "Build_STANDALONE") else() list(APPEND audio_plugin_flags "Build_Standalone") endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2)) list(APPEND audio_plugin_flags "Build_Unity") endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0)) list(APPEND audio_plugin_flags "Enable_IAA") endif() list(APPEND audio_plugin_flags "Name" "Desc" "Manufacturer" "ManufacturerWebsite" "ManufacturerEmail" "ManufacturerCode" "PluginCode" "IsSynth" "WantsMidiInput" "ProducesMidiOutput" "IsMidiEffect" "EditorRequiresKeyboardFocus" "Version" "VersionCode" "VersionString" "VSTUniqueID" "VSTCategory" ) if(DEFINED JUCER_PLUGIN_VST3_CATEGORY OR NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1)) list(APPEND audio_plugin_flags "Vst3Category") endif() list(APPEND audio_plugin_flags "AUMainType" "AUSubType" "AUExportPrefix" "AUExportPrefixQuoted" "AUManufacturerCode" "CFBundleIdentifier" "RTASCategory" "RTASManufacturerCode" "RTASProductId" "RTASDisableBypass" "RTASDisableMultiMono" "AAXIdentifier" "AAXManufacturerCode" "AAXProductId" "AAXCategory" "AAXDisableBypass" "AAXDisableMultiMono" ) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0)) list(APPEND audio_plugin_flags "IAAType" "IAASubType" "IAAName") endif() if(DEFINED JUCER_PLUGIN_VST_NUM_MIDI_INPUTS OR DEFINED JUCER_PLUGIN_VST_NUM_MIDI_OUTPUTS OR NOT DEFINED JUCER_VERSION OR JUCER_VERSION VERSION_GREATER 5.4.1) list(APPEND audio_plugin_flags "VSTNumMidiInputs" "VSTNumMidiOutputs") endif() _FRUT_bool_to_int("${JUCER_BUILD_VST}" Build_VST_value) _FRUT_bool_to_int("${JUCER_BUILD_VST3}" Build_VST3_value) _FRUT_bool_to_int("${JUCER_BUILD_AUDIOUNIT}" Build_AU_value) _FRUT_bool_to_int("${JUCER_BUILD_AUDIOUNIT_V3}" Build_AUv3_value) _FRUT_bool_to_int("${JUCER_BUILD_RTAS}" Build_RTAS_value) _FRUT_bool_to_int("${JUCER_BUILD_AAX}" Build_AAX_value) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) _FRUT_bool_to_int("${JUCER_BUILD_AUDIOUNIT_V3}" Build_STANDALONE_value) elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.1.0) _FRUT_bool_to_int("${JUCER_BUILD_STANDALONE_PLUGIN}" Build_Standalone_value) set(Build_STANDALONE_value "JucePlugin_Build_Standalone") else() _FRUT_bool_to_int("${JUCER_BUILD_STANDALONE_PLUGIN}" Build_Standalone_value) endif() _FRUT_bool_to_int("${JUCER_BUILD_UNITY_PLUGIN}" Build_Unity_value) _FRUT_bool_to_int("${JUCER_ENABLE_INTER_APP_AUDIO}" Enable_IAA_value) set(Name_value "\"${JUCER_PLUGIN_NAME}\"") set(Desc_value "\"${JUCER_PLUGIN_DESCRIPTION}\"") set(Manufacturer_value "\"${JUCER_PLUGIN_MANUFACTURER}\"") set(ManufacturerWebsite_value "\"${JUCER_COMPANY_WEBSITE}\"") set(ManufacturerEmail_value "\"${JUCER_COMPANY_EMAIL}\"") if(ARGV1 STREQUAL "WITH_COMMENTS") _FRUT_char_literal( "${JUCER_PLUGIN_MANUFACTURER_CODE}" ManufacturerCode_value WITH_COMMENT ) _FRUT_char_literal("${JUCER_PLUGIN_CODE}" PluginCode_value WITH_COMMENT) else() _FRUT_char_literal("${JUCER_PLUGIN_MANUFACTURER_CODE}" ManufacturerCode_value) _FRUT_char_literal("${JUCER_PLUGIN_CODE}" PluginCode_value) endif() _FRUT_bool_to_int("${JUCER_PLUGIN_IS_A_SYNTH}" IsSynth_value) _FRUT_bool_to_int("${JUCER_PLUGIN_MIDI_INPUT}" WantsMidiInput_value) _FRUT_bool_to_int("${JUCER_PLUGIN_MIDI_OUTPUT}" ProducesMidiOutput_value) _FRUT_bool_to_int("${JUCER_MIDI_EFFECT_PLUGIN}" IsMidiEffect_value) _FRUT_bool_to_int("${JUCER_KEY_FOCUS}" EditorRequiresKeyboardFocus_value) set(Version_value "${JUCER_PROJECT_VERSION}") _FRUT_version_to_hex("${JUCER_PROJECT_VERSION}" VersionCode_value) set(VersionString_value "\"${JUCER_PROJECT_VERSION}\"") set(VSTUniqueID_value "JucePlugin_PluginCode") if(DEFINED JUCER_PLUGIN_VST_LEGACY_CATEGORY) set(VSTCategory_value "${JUCER_PLUGIN_VST_LEGACY_CATEGORY}") elseif(DEFINED JUCER_PLUGIN_VST_CATEGORY) set(VSTCategory_value "${JUCER_PLUGIN_VST_CATEGORY}") elseif(DEFINED JUCER_VST_CATEGORY) set(VSTCategory_value "${JUCER_VST_CATEGORY}") else() if(JUCER_PLUGIN_IS_A_SYNTH) set(VSTCategory_value "kPlugCategSynth") else() set(VSTCategory_value "kPlugCategEffect") endif() endif() if(DEFINED JUCER_PLUGIN_VST3_CATEGORY) _FRUT_compute_vst3_category(vst3_category) else() if(JUCER_PLUGIN_IS_A_SYNTH) set(vst3_category "Instrument|Synth") else() set(vst3_category "Fx") endif() endif() set(Vst3Category_value "\"${vst3_category}\"") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1) if(NOT DEFINED JUCER_PLUGIN_AU_MAIN_TYPE OR JUCER_PLUGIN_AU_MAIN_TYPE STREQUAL "") if(JUCER_MIDI_EFFECT_PLUGIN) set(AUMainType_value "'aumi'") elseif(JUCER_PLUGIN_IS_A_SYNTH) set(AUMainType_value "kAudioUnitType_MusicDevice") elseif(JUCER_PLUGIN_MIDI_INPUT) set(AUMainType_value "kAudioUnitType_MusicEffect") else() set(AUMainType_value "kAudioUnitType_Effect") endif() else() set(AUMainType_value "${JUCER_PLUGIN_AU_MAIN_TYPE}") endif() else() if(NOT DEFINED JUCER_PLUGIN_AU_MAIN_TYPE OR JUCER_PLUGIN_AU_MAIN_TYPE STREQUAL "") if(JUCER_MIDI_EFFECT_PLUGIN) set(AUMainType_value "'aumi'") elseif(JUCER_PLUGIN_IS_A_SYNTH) set(AUMainType_value "'aumu'") elseif(JUCER_PLUGIN_MIDI_INPUT) set(AUMainType_value "'aumf'") else() set(AUMainType_value "'aufx'") endif() else() _FRUT_get_au_quoted_four_chars("${JUCER_PLUGIN_AU_MAIN_TYPE}" AUMainType_value) endif() endif() set(AUSubType_value "JucePlugin_PluginCode") set(AUExportPrefix_value "${JUCER_PLUGIN_AU_EXPORT_PREFIX}") set(AUExportPrefixQuoted_value "\"${JUCER_PLUGIN_AU_EXPORT_PREFIX}\"") set(AUManufacturerCode_value "JucePlugin_ManufacturerCode") set(CFBundleIdentifier_value "${JUCER_BUNDLE_IDENTIFIER}") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1) if(JUCER_PLUGIN_IS_A_SYNTH) set(RTASCategory_value "ePlugInCategory_SWGenerators") elseif(NOT DEFINED JUCER_PLUGIN_RTAS_CATEGORY) set(RTASCategory_value "ePlugInCategory_None") else() set(RTASCategory_value "${JUCER_PLUGIN_RTAS_CATEGORY}") endif() else() if(DEFINED JUCER_PLUGIN_RTAS_CATEGORY) _FRUT_compute_rtas_aax_category("RTAS" "ePlugInCategory" RTASCategory_value) else() if(JUCER_PLUGIN_IS_A_SYNTH) set(RTASCategory_value "2048") # ePlugInCategory_SWGenerators else() set(RTASCategory_value "0") # ePlugInCategory_None endif() endif() endif() set(RTASManufacturerCode_value "JucePlugin_ManufacturerCode") set(RTASProductId_value "JucePlugin_PluginCode") _FRUT_bool_to_int("${JUCER_PLUGIN_RTAS_DISABLE_BYPASS}" RTASDisableBypass_value) _FRUT_bool_to_int("${JUCER_PLUGIN_RTAS_DISABLE_MULTI_MONO}" RTASDisableMultiMono_value ) if(NOT DEFINED JUCER_PLUGIN_AAX_IDENTIFIER) set(AAXIdentifier_value "${JUCER_BUNDLE_IDENTIFIER}") else() set(AAXIdentifier_value "${JUCER_PLUGIN_AAX_IDENTIFIER}") endif() set(AAXManufacturerCode_value "JucePlugin_ManufacturerCode") set(AAXProductId_value "JucePlugin_PluginCode") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.1) if(NOT DEFINED JUCER_PLUGIN_AAX_CATEGORY) set(AAXCategory_value "AAX_ePlugInCategory_Dynamics") else() set(AAXCategory_value "${JUCER_PLUGIN_AAX_CATEGORY}") endif() else() if(DEFINED JUCER_PLUGIN_AAX_CATEGORY) _FRUT_compute_rtas_aax_category("AAX" "AAX_ePlugInCategory" AAXCategory_value) else() if(JUCER_PLUGIN_IS_A_SYNTH) set(AAXCategory_value "2048") # AAX_ePlugInCategory_SWGenerators else() set(AAXCategory_value "0") # AAX_ePlugInCategory_None endif() endif() endif() _FRUT_bool_to_int("${JUCER_PLUGIN_AAX_DISABLE_BYPASS}" AAXDisableBypass_value) _FRUT_bool_to_int("${JUCER_PLUGIN_AAX_DISABLE_MULTI_MONO}" AAXDisableMultiMono_value) _FRUT_get_iaa_type_code(iaa_type_code) if(ARGV1 STREQUAL "WITH_COMMENTS") _FRUT_char_literal("${iaa_type_code}" IAAType_value WITH_COMMENT) else() _FRUT_char_literal("${iaa_type_code}" IAAType_value) endif() set(IAASubType_value "JucePlugin_PluginCode") set(IAAName_value "\"${JUCER_PLUGIN_MANUFACTURER}: ${JUCER_PLUGIN_NAME}\"") if(DEFINED JUCER_PLUGIN_VST_NUM_MIDI_INPUTS) set(VSTNumMidiInputs_value "${JUCER_PLUGIN_VST_NUM_MIDI_INPUTS}") else() set(VSTNumMidiInputs_value "16") endif() if(DEFINED JUCER_PLUGIN_VST_NUM_MIDI_OUTPUTS) set(VSTNumMidiOutputs_value "${JUCER_PLUGIN_VST_NUM_MIDI_OUTPUTS}") else() set(VSTNumMidiOutputs_value "16") endif() string(LENGTH "${JUCER_PLUGIN_CHANNEL_CONFIGURATIONS}" plugin_channel_config_length) if(plugin_channel_config_length GREATER 0) # See Project::getAudioPluginFlags()::countMaxPluginChannels # in JUCE/extras/Projucer/Source/Project/jucer_Project.cpp string(REGEX REPLACE "[, {}]" ";" configs "${JUCER_PLUGIN_CHANNEL_CONFIGURATIONS}") set(max_num_input 0) set(max_num_output 0) set(is_input TRUE) foreach(element IN LISTS configs) if(is_input) if(element GREATER max_num_input) set(max_num_input "${element}") endif() set(is_input FALSE) else() if(element GREATER max_num_output) set(max_num_output "${element}") endif() set(is_input TRUE) endif() endforeach() list(APPEND audio_plugin_flags "MaxNumInputChannels" "MaxNumOutputChannels" "PreferredChannelConfigurations" ) set(MaxNumInputChannels_value "${max_num_input}") set(MaxNumOutputChannels_value "${max_num_output}") set(PreferredChannelConfigurations_value "${JUCER_PLUGIN_CHANNEL_CONFIGURATIONS}") endif() set(${out_var} "${audio_plugin_flags}" PARENT_SCOPE) foreach(flag IN LISTS audio_plugin_flags) set(${flag}_value "${${flag}_value}" PARENT_SCOPE) endforeach() endfunction() function(_FRUT_get_iaa_type_code out_var) if(JUCER_PLUGIN_MIDI_INPUT) if(JUCER_PLUGIN_IS_A_SYNTH) set(code "auri") else() set(code "aurm") endif() else() if(JUCER_PLUGIN_IS_A_SYNTH) set(code "aurg") else() set(code "aurx") endif() endif() set(${out_var} "${code}" PARENT_SCOPE) endfunction() function(_FRUT_get_recommended_compiler_warning_flags kind out_var) if(kind STREQUAL "LLVM") set(flags "-Wall" "-Wshadow-all" "-Wshorten-64-to-32" "-Wstrict-aliasing" "-Wuninitialized" "-Wunused-parameter" "-Wconversion" "-Wsign-compare" "-Wint-conversion" "-Wconditional-uninitialized" "-Woverloaded-virtual" "-Wreorder" "-Wconstant-conversion" "-Wsign-conversion" "-Wunused-private-field" "-Wbool-conversion" "-Wextra-semi" "-Wunreachable-code" "-Wzero-as-null-pointer-constant" "-Wcast-align" "-Winconsistent-missing-destructor-override" "-Wshift-sign-overflow" "-Wnullable-to-nonnull-conversion" "-Wno-missing-field-initializers" "-Wno-ignored-qualifiers" ) elseif(kind STREQUAL "GCC" OR kind STREQUAL "GCC-7") set(flags "-Wall" "-Wextra" "-Wstrict-aliasing" "-Wuninitialized" "-Wunused-parameter" "-Wsign-compare" "-Woverloaded-virtual" "-Wreorder" "-Wsign-conversion" "-Wunreachable-code" "-Wzero-as-null-pointer-constant" "-Wcast-align" "-Wno-implicit-fallthrough" "-Wno-maybe-uninitialized" "-Wno-missing-field-initializers" "-Wno-ignored-qualifiers" ) if(kind STREQUAL "GCC-7") list(APPEND flags "-Wno-strict-overflow") endif() else() set(flags "") endif() set(${out_var} "${flags}" PARENT_SCOPE) endfunction() function(_FRUT_install_to_plugin_binary_location target plugin_type default_destination) if(ARGC GREATER 3) if(NOT ARGV3 STREQUAL "FILES") message(FATAL_ERROR "Unexpected argument \"${ARGV3}\"") endif() endif() set(component "_install_${target}_to_${plugin_type}_binary_location") set(should_install FALSE) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_${plugin_type}_BINARY_LOCATION_${config}) set(destination "${JUCER_${plugin_type}_BINARY_LOCATION_${config}}") else() set(destination "${default_destination}") endif() if(NOT destination STREQUAL "") if((NOT DEFINED JUCER_ENABLE_PLUGIN_COPY_STEP_${config} AND (APPLE OR CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")) OR JUCER_ENABLE_PLUGIN_COPY_STEP_${config}) install(TARGETS ${target} CONFIGURATIONS "${config}" COMPONENT "${component}" DESTINATION "${destination}" ) if(ARGV3 STREQUAL "FILES") install(${ARGN} CONFIGURATIONS "${config}" COMPONENT "${component}" DESTINATION "${destination}" ) endif() set(should_install TRUE) endif() endif() endforeach() if(should_install) add_custom_command(TARGET ${target} POST_BUILD COMMAND "${CMAKE_COMMAND}" "-DCMAKE_INSTALL_CONFIG_NAME=$" "-DCMAKE_INSTALL_COMPONENT=${component}" "-P" "${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake" ) endif() endfunction() function(_FRUT_link_xcode_frameworks target exporter) if(NOT APPLE) return() endif() set(xcode_frameworks ${JUCER_PROJECT_XCODE_FRAMEWORKS} ${JUCER_EXTRA_SYSTEM_FRAMEWORKS} ${JUCER_EXTRA_FRAMEWORKS} ${ARGN} ) if(JUCER_FLAG_JUCE_PLUGINHOST_AU) list(APPEND xcode_frameworks "CoreAudioKit") if(NOT IOS) list(APPEND xcode_frameworks "AudioUnit") endif() endif() if(IOS AND JUCER_PUSH_NOTIFICATIONS_CAPABILITY) list(APPEND xcode_frameworks "UserNotifications") endif() if(IOS AND JUCER_FLAG_JUCE_USE_CAMERA) list(APPEND xcode_frameworks "ImageIO") endif() if(JUCER_IN_APP_PURCHASES_CAPABILITY) list(APPEND xcode_frameworks "StoreKit") endif() if(xcode_frameworks) list(SORT xcode_frameworks) list(REMOVE_DUPLICATES xcode_frameworks) if(NOT JUCER_FLAG_JUCE_QUICKTIME) list(REMOVE_ITEM xcode_frameworks "QuickTime") endif() if("AudioUnit" IN_LIST xcode_frameworks) list(REMOVE_ITEM xcode_frameworks "AudioUnit") list(INSERT xcode_frameworks 0 "AudioUnit") endif() if(IOS) foreach(framework_name IN LISTS xcode_frameworks) target_link_libraries(${target} PRIVATE "-framework ${framework_name}") endforeach() else() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(CMAKE_FRAMEWORK_PATH "") set(sdk_version "${JUCER_MACOS_BASE_SDK_${config}}") set(sdk_path "${JUCER_MACOSX_SDK_PATH_${config}}") if(IS_DIRECTORY "${sdk_path}") set(CMAKE_FRAMEWORK_PATH "${sdk_path}/System/Library/Frameworks") endif() foreach(framework_name IN LISTS xcode_frameworks) find_library(${framework_name}_framework_${sdk_version} ${framework_name}) target_link_libraries(${target} PRIVATE "$<$:${${framework_name}_framework_${sdk_version}}>" ) endforeach() endforeach() endif() endif() if(JUCER_EXTRA_CUSTOM_FRAMEWORKS) set(CMAKE_FIND_FRAMEWORK ONLY) set(search_paths) foreach(path IN LISTS JUCER_FRAMEWORK_SEARCH_PATHS) _FRUT_abs_path_based_on_jucer_target_project_folder(path "${path}" "${exporter}") list(APPEND search_paths "${path}") endforeach() set(CMAKE_FRAMEWORK_PATH "${search_paths}") foreach(framework_path IN LISTS JUCER_EXTRA_CUSTOM_FRAMEWORKS) get_filename_component(framework_name "${framework_path}" NAME) string(REGEX REPLACE "\\.framework$" "" framework_name "${framework_name}") find_library(${framework_name}_framework ${framework_name}) target_link_libraries(${target} PRIVATE ${${framework_name}_framework}) endforeach() endif() endfunction() function(_FRUT_make_valid_configuration_name config out_var) string(REGEX REPLACE "[^A-Za-z0-9_]+" " " config "${config}") string(STRIP "${config}" config) string(REGEX REPLACE "[ ]+" "_" config "${config}") set(${out_var} "${config}" PARENT_SCOPE) endfunction() function(_FRUT_parse_arguments single_value_keywords multi_value_keywords arguments) foreach(keyword IN LISTS single_value_keywords multi_value_keywords) unset(_${keyword}) endforeach() unset(keyword) foreach(argument IN LISTS arguments) list(FIND single_value_keywords "${argument}" single_value_index) list(FIND multi_value_keywords "${argument}" multi_value_index) if(NOT DEFINED keyword) if(NOT single_value_index EQUAL -1) set(keyword "${argument}") set(keyword_type "single") elseif(NOT multi_value_index EQUAL -1) set(keyword "${argument}") set(keyword_type "multi") else() message(FATAL_ERROR "Unknown keyword: \"${argument}\"") endif() elseif(keyword_type STREQUAL "single") set(_${keyword} "${argument}") unset(keyword) elseif(keyword_type STREQUAL "multi") if(DEFINED _${keyword}) if(NOT single_value_index EQUAL -1) set(keyword "${argument}") set(keyword_type "single") elseif(NOT multi_value_index EQUAL -1) set(keyword "${argument}") set(keyword_type "multi") else() list(APPEND _${keyword} ${argument}) endif() else() list(APPEND _${keyword} ${argument}) endif() else() message(FATAL_ERROR "There is a bug!") endif() endforeach() foreach(keyword IN LISTS single_value_keywords multi_value_keywords) unset(_${keyword} PARENT_SCOPE) if(DEFINED _${keyword}) set(_${keyword} "${_${keyword}}" PARENT_SCOPE) endif() endforeach() endfunction() function(_FRUT_sanitize_path_in_user_folder out_path in_path) file(TO_CMAKE_PATH "$ENV{HOME}" user_folder) if(NOT user_folder MATCHES "/$") string(APPEND user_folder "/") endif() string(REGEX REPLACE "^~/" "${user_folder}" in_path "${in_path}") string(REGEX REPLACE "^\\$\\(HOME\\)/" "${user_folder}" in_path "${in_path}") set(${out_path} "${in_path}" PARENT_SCOPE) endfunction() function(_FRUT_set_AppConfig_compile_definitions target) # See ProjectExporter::getAppConfigDefs # in JUCE/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp if(DEFINED JUCER_DISPLAY_THE_JUCE_SPLASH_SCREEN AND NOT JUCER_DISPLAY_THE_JUCE_SPLASH_SCREEN) set(display_splash_screen 0) else() set(display_splash_screen 1) endif() if(DEFINED JUCER_SPLASH_SCREEN_COLOUR AND NOT JUCER_SPLASH_SCREEN_COLOUR STREQUAL "Dark") set(use_dark_splash_screen 0) else() set(use_dark_splash_screen 1) endif() target_compile_definitions(${target} PRIVATE "JUCE_DISPLAY_SPLASH_SCREEN=${display_splash_screen}" "JUCE_USE_DARK_SPLASH_SCREEN=${use_dark_splash_screen}" ) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) if(DEFINED JUCER_REPORT_JUCE_APP_USAGE AND NOT JUCER_REPORT_JUCE_APP_USAGE) set(report_app_usage 0) else() set(report_app_usage 1) endif() target_compile_definitions(${target} PRIVATE "JUCE_REPORT_APP_USAGE=${report_app_usage}" ) endif() foreach(module_name IN LISTS JUCER_PROJECT_MODULES) target_compile_definitions(${target} PRIVATE "JUCE_MODULE_AVAILABLE_${module_name}=1") endforeach() target_compile_definitions(${target} PRIVATE "JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1") foreach(module_name IN LISTS JUCER_PROJECT_MODULES) foreach(config_flag IN LISTS JUCER_${module_name}_CONFIG_FLAGS) if(NOT DEFINED JUCER_FLAG_${config_flag}) elseif(JUCER_FLAG_${config_flag}) target_compile_definitions(${target} PRIVATE "${config_flag}=1") else() target_compile_definitions(${target} PRIVATE "${config_flag}=0") endif() endforeach() endforeach() if(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") _FRUT_get_audio_plugin_flags(audio_plugin_flags) foreach(flag IN LISTS audio_plugin_flags) target_compile_definitions(${target} PRIVATE "JucePlugin_${flag}=${${flag}_value}") endforeach() target_compile_definitions(${target} PRIVATE "JUCE_STANDALONE_APPLICATION=JucePlugin_Build_Standalone" ) elseif(JUCER_PROJECT_TYPE STREQUAL "Dynamic Library") target_compile_definitions(${target} PRIVATE "JUCE_STANDALONE_APPLICATION=0") else() target_compile_definitions(${target} PRIVATE "JUCE_STANDALONE_APPLICATION=1") endif() endfunction() function(_FRUT_set_bundle_properties target extension) if(NOT APPLE) return() endif() set_target_properties(${target} PROPERTIES BUNDLE TRUE BUNDLE_EXTENSION "${extension}" XCODE_ATTRIBUTE_WRAPPER_EXTENSION "${extension}" ) target_sources(${target} PRIVATE "${Reprojucer_data_DIR}/PkgInfo") set_source_files_properties("${Reprojucer_data_DIR}/PkgInfo" PROPERTIES MACOSX_PACKAGE_LOCATION "." ) endfunction() function(_FRUT_set_compiler_and_linker_settings target target_type exporter) target_include_directories(${target} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/JuceLibraryCode" ${JUCER_PROJECT_MODULES_FOLDERS} ${JUCER_PROJECT_MODULES_INTERNAL_SEARCH_PATHS} ) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(search_paths "") foreach(path IN LISTS JUCER_HEADER_SEARCH_PATHS_${config}) file(TO_CMAKE_PATH "${path}" path) _FRUT_abs_path_based_on_jucer_target_project_folder(path "${path}" "${exporter}") list(APPEND search_paths "${path}") endforeach() target_include_directories(${target} PRIVATE $<$:${search_paths}>) endforeach() set(search_paths "") foreach(path IN LISTS JUCER_HEADER_SEARCH_PATHS) file(TO_CMAKE_PATH "${path}" path) _FRUT_abs_path_based_on_jucer_target_project_folder(path "${path}" "${exporter}") list(APPEND search_paths "${path}") endforeach() target_include_directories(${target} PRIVATE ${search_paths}) if(JUCER_BUILD_VST OR JUCER_FLAG_JUCE_PLUGINHOST_VST) if(DEFINED JUCER_VST_LEGACY_SDK_FOLDER) target_include_directories(${target} PRIVATE "${JUCER_VST_LEGACY_SDK_FOLDER}") endif() if(DEFINED JUCER_VST_SDK_FOLDER) target_include_directories(${target} PRIVATE "${JUCER_VST_SDK_FOLDER}") endif() endif() if(JUCER_BUILD_VST3 OR JUCER_FLAG_JUCE_PLUGINHOST_VST3) string(CONCAT juce_internal_vst3_sdk_path "${JUCER_PROJECT_MODULE_juce_audio_processors_PATH}/" "juce_audio_processors/format_types/VST3_SDK" ) if(DEFINED JUCER_VST3_SDK_FOLDER) target_include_directories(${target} PRIVATE "${JUCER_VST3_SDK_FOLDER}") elseif(EXISTS "${juce_internal_vst3_sdk_path}") target_include_directories(${target} PRIVATE "${juce_internal_vst3_sdk_path}") endif() endif() if(JUCER_BUILD_AAX AND DEFINED JUCER_AAX_SDK_FOLDER) target_include_directories(${target} PRIVATE "${JUCER_AAX_SDK_FOLDER}" "${JUCER_AAX_SDK_FOLDER}/Interfaces" "${JUCER_AAX_SDK_FOLDER}/Interfaces/ACF" ) endif() if(DEFINED JUCER_ADD_RECOMMENDED_COMPILER_WARNING_FLAGS) _FRUT_get_recommended_compiler_warning_flags( "${JUCER_ADD_RECOMMENDED_COMPILER_WARNING_FLAGS}" warning_flags ) target_compile_options(${target} PRIVATE ${warning_flags}) endif() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_OPTIMISATION_FLAG_${config}) target_compile_options(${target} PRIVATE $<$:${JUCER_OPTIMISATION_FLAG_${config}}> ) endif() endforeach() _FRUT_set_cxx_language_standard_properties(${target}) if(APPLE) _FRUT_set_compiler_and_linker_settings_APPLE(${target}) elseif(MSVC) if(DEFINED JUCER_USE_IPP_LIBRARY AND NOT JUCER_USE_IPP_LIBRARY STREQUAL "No") _FRUT_set_IPP_windows_compiler_and_linker_settings(${target}) endif() _FRUT_set_compiler_and_linker_settings_MSVC(${target}) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") _FRUT_set_compiler_and_linker_settings_Linux(${target}) elseif(WIN32 AND NOT MSVC) _FRUT_set_compiler_and_linker_settings_MinGW(${target}) endif() target_compile_definitions(${target} PRIVATE ${JUCER_PREPROCESSOR_DEFINITIONS} ${JUCER_EXTRA_PREPROCESSOR_DEFINITIONS} ) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(definitions "${JUCER_PREPROCESSOR_DEFINITIONS_${config}}") target_compile_definitions(${target} PRIVATE $<$:${definitions}>) endforeach() if(DEFINED JUCER_USE_GLOBAL_APPCONFIG_HEADER AND NOT JUCER_USE_GLOBAL_APPCONFIG_HEADER) _FRUT_set_AppConfig_compile_definitions(${target}) elseif(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in") _FRUT_set_JucePlugin_Build_defines(${target} ${target_type}) endif() target_compile_options(${target} PRIVATE ${JUCER_EXTRA_COMPILER_FLAGS}) foreach(scheme IN LISTS JUCER_COMPILER_FLAG_SCHEMES) if(DEFINED JUCER_COMPILER_FLAGS_FOR_${scheme}) set_source_files_properties(${JUCER_COMPILER_FLAG_SCHEME_${scheme}_FILES} PROPERTIES COMPILE_FLAGS "${JUCER_COMPILER_FLAGS_FOR_${scheme}}" ) endif() endforeach() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) foreach(path IN LISTS JUCER_EXTRA_LIBRARY_SEARCH_PATHS_${config}) file(TO_CMAKE_PATH "${path}" path) _FRUT_abs_path_based_on_jucer_target_project_folder(path "${path}" "${exporter}") if(MSVC) target_link_libraries(${target} PRIVATE $<$:-LIBPATH:${path}>) else() target_link_libraries(${target} PRIVATE $<$:-L${path}>) endif() endforeach() foreach(path IN LISTS JUCER_PROJECT_MODULES_LIBRARY_SEARCH_PATHS) if(MSVC) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(arch "x64") else() set(arch "Win32") endif() if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set(d_or_empty "d") else() set(d_or_empty "") endif() if(DEFINED JUCER_RUNTIME_LIBRARY_FLAG_${config}) string(SUBSTRING "${JUCER_RUNTIME_LIBRARY_FLAG_${config}}" 1 -1 runtime) elseif(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.1)) set(runtime "MD${d_or_empty}") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0 AND (JUCER_BUILD_VST OR JUCER_BUILD_VST3 OR JUCER_BUILD_RTAS OR JUCER_BUILD_AAX)) set(runtime "MD${d_or_empty}") elseif(JUCER_BUILD_RTAS OR JUCER_BUILD_AAX) set(runtime "MD${d_or_empty}") else() set(runtime "MT${d_or_empty}") endif() target_link_libraries(${target} PRIVATE $<$:-LIBPATH:${path}/${arch}/${runtime}> ) else() unset(arch) if(APPLE) if(CMAKE_GENERATOR STREQUAL "Xcode") set(arch "\${CURRENT_ARCH}") elseif(DEFINED JUCER_MACOS_ARCHITECTURES_${config}) list(LENGTH JUCER_MACOS_ARCHITECTURES_${config} macos_architectures_length) if(macos_architectures_length EQUAL 1) set(arch "${JUCER_MACOS_ARCHITECTURES_${config}}") endif() endif() elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" OR (WIN32 AND NOT MSVC)) if(DEFINED JUCER_ARCHITECTURE_FLAG_${config}) if(JUCER_ARCHITECTURE_FLAG_${config} MATCHES "^-march=") string(SUBSTRING "JUCER_ARCHITECTURE_FLAG_${config}" 7 -1 arch) elseif(JUCER_ARCHITECTURE_FLAG_${config} STREQUAL "-m64") set(arch "x86_64") elseif(JUCER_ARCHITECTURE_FLAG_${config} STREQUAL "-m32") set(arch "i386") endif() endif() endif() if(NOT DEFINED arch) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(arch "x86_64") else() set(arch "i386") endif() endif() target_link_libraries(${target} PRIVATE $<$:-L${path}/${arch}>) endif() endforeach() endforeach() foreach(flag IN LISTS JUCER_EXTRA_LINKER_FLAGS) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}") set_property(TARGET ${target} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS " ${flag}") endforeach() target_link_libraries(${target} PRIVATE ${JUCER_EXTERNAL_LIBRARIES_TO_LINK}) endfunction() function(_FRUT_set_compiler_and_linker_settings_APPLE target) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) target_compile_definitions(${target} PRIVATE $<$:_DEBUG=1> $<$:DEBUG=1> ) else() target_compile_definitions(${target} PRIVATE $<$:_NDEBUG=1> $<$:NDEBUG=1> ) endif() if(JUCER_RELAX_IEEE_COMPLIANCE_${config}) target_compile_options(${target} PRIVATE $<$:-ffast-math>) endif() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.0) if(JUCER_LINK_TIME_OPTIMISATION_${config}) target_compile_options(${target} PRIVATE $<$:-flto>) endif() else() if(JUCER_CONFIGURATION_IS_DEBUG_${config}) if(JUCER_LINK_TIME_OPTIMISATION_${config}) target_compile_options(${target} PRIVATE $<$:-flto>) endif() else() if(NOT (DEFINED JUCER_LINK_TIME_OPTIMISATION_${config} AND NOT JUCER_LINK_TIME_OPTIMISATION_${config})) target_compile_options(${target} PRIVATE $<$:-flto>) endif() endif() endif() endforeach() if(CMAKE_GENERATOR STREQUAL "Xcode") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_CXX_LIBRARY_${config}) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY[variant=${config}] "${JUCER_CXX_LIBRARY_${config}}" ) endif() endforeach() else() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++" ) endif() else() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_CXX_LIBRARY_${config}) target_compile_options(${target} PRIVATE $<$:-stdlib=${JUCER_CXX_LIBRARY_${config}}> ) string(TOUPPER "${config}" upper_config) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " -stdlib=${JUCER_CXX_LIBRARY_${config}}" ) endif() endforeach() else() target_compile_options(${target} PRIVATE "-stdlib=libc++") set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -stdlib=libc++" ) endif() endif() if(JUCER_IN_APP_PURCHASES_CAPABILITY) target_compile_definitions(${target} PRIVATE "JUCE_IN_APP_PURCHASES=1") endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.0) AND IOS AND (NOT DEFINED JUCER_CONTENT_SHARING OR JUCER_CONTENT_SHARING) ) target_compile_definitions(${target} PRIVATE "JUCE_CONTENT_SHARING=1") endif() if(JUCER_PUSH_NOTIFICATIONS_CAPABILITY) target_compile_definitions(${target} PRIVATE "JUCE_PUSH_NOTIFICATIONS=1") endif() if(NOT IOS AND target MATCHES "_AUv3_AppExtension$") if(CMAKE_GENERATOR STREQUAL "Xcode") set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD_64_BIT)" ) else() set_target_properties(${target} PROPERTIES OSX_ARCHITECTURES "x86_64") endif() else() if(CMAKE_GENERATOR STREQUAL "Xcode") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_XCODE_ARCHS_${config}) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ARCHS[variant=${config}] "${JUCER_XCODE_ARCHS_${config}}" ) else() if(NOT CMAKE_VERSION VERSION_LESS 3.18.1 AND NOT XCODE_VERSION VERSION_LESS 12) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ARCHS[variant=${config}] "$(ARCHS_STANDARD)" ) endif() if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=${config}] "YES" ) endif() endif() endforeach() else() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_MACOS_ARCHITECTURES_${config}) string(TOUPPER "${config}" upper_config) set_target_properties(${target} PROPERTIES OSX_ARCHITECTURES_${upper_config} "${JUCER_MACOS_ARCHITECTURES_${config}}" ) endif() endforeach() endif() endif() if(NOT IOS AND NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.0.2)) unset(valid_archs) set(excluded_archs "") if(DEFINED JUCER_VALID_ARCHITECTURES AND NOT JUCER_VALID_ARCHITECTURES STREQUAL "") string(REPLACE ";" " " valid_archs "${JUCER_VALID_ARCHITECTURES}") foreach(arch "i386" "x86_64" "arm64" "arm64e") if(NOT arch IN_LIST JUCER_VALID_ARCHITECTURES) list(APPEND excluded_archs "${arch}") endif() endforeach() string(REPLACE ";" " " excluded_archs "${excluded_archs}") elseif(NOT DEFINED JUCER_VALID_ARCHITECTURES) set(valid_archs "i386 x86_64 arm64 arm64e") endif() if(DEFINED valid_archs) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_VALID_ARCHS "${valid_archs}" ) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.3)) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_EXCLUDED_ARCHS "${excluded_archs}" ) endif() endif() endif() if(IOS) if(DEFINED JUCER_DEVICE_FAMILY) set(targeted_device_family "${JUCER_DEVICE_FAMILY}") else() set(targeted_device_family "1,2") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME "LaunchImage" XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "${targeted_device_family}" ) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_SDKROOT[variant=${config}] "iphoneos${JUCER_IOS_BASE_SDK_${config}}" ) if(DEFINED JUCER_IOS_DEPLOYMENT_TARGET_${config} AND NOT JUCER_IOS_DEPLOYMENT_TARGET_${config} STREQUAL "default") set(ios_deployment_target "${JUCER_IOS_DEPLOYMENT_TARGET_${config}}") else() set(ios_deployment_target "9.3") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET[variant=${config}] "${ios_deployment_target}" ) endforeach() elseif(CMAKE_GENERATOR STREQUAL "Xcode") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(macos_deployment_target "10.11") if(DEFINED JUCER_MACOS_DEPLOYMENT_TARGET_${config}) set(macos_deployment_target "${JUCER_MACOS_DEPLOYMENT_TARGET_${config}}") endif() if(target MATCHES "_AUv3_AppExtension$" AND macos_deployment_target VERSION_LESS 10.11) set(macos_deployment_target "10.11") message(STATUS "Set macOS Deployment Target to 10.11 for ${target} in ${config}") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET[variant=${config}] "${macos_deployment_target}" ) unset(sdkroot) if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.4.6) if(DEFINED JUCER_MACOS_BASE_SDK_${config}) set(sdkroot "macosx${JUCER_MACOS_BASE_SDK_${config}}") endif() else() set(sdkroot "macosx${JUCER_MACOS_BASE_SDK_${config}}") endif() if(DEFINED sdkroot) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_SDKROOT[variant=${config}] "${sdkroot}" ) endif() endforeach() else() set(macos_deployment_target "10.11") if(DEFINED JUCER_MACOS_DEPLOYMENT_TARGET_${CMAKE_BUILD_TYPE}) set(macos_deployment_target "${JUCER_MACOS_DEPLOYMENT_TARGET_${CMAKE_BUILD_TYPE}}") endif() if(target MATCHES "_AUv3_AppExtension$" AND macos_deployment_target VERSION_LESS 10.11) set(macos_deployment_target "10.11") message(STATUS "Set macOS Deployment Target to 10.11 for ${target}") endif() target_compile_options(${target} PRIVATE "-mmacosx-version-min=${macos_deployment_target}" ) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -mmacosx-version-min=${macos_deployment_target}" ) set(sysroot "${JUCER_MACOSX_SDK_PATH_${CMAKE_BUILD_TYPE}}") if(IS_DIRECTORY "${sysroot}") target_compile_options(${target} PRIVATE -isysroot "${sysroot}") set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -isysroot ${sysroot}" ) endif() endif() set(development_team_id_string "${JUCER_DEVELOPMENT_TEAM_ID}") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.4.5) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(IOS) if(DEFINED JUCER_CODE_SIGNING_IDENTITY_${config}) set(identity "${JUCER_CODE_SIGNING_IDENTITY_${config}}") else() set(identity "iPhone Developer") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[sdk=iphoneos*][variant=${config}] "${identity}" ) else() if(DEFINED JUCER_CODE_SIGNING_IDENTITY_${config} AND NOT JUCER_CODE_SIGNING_IDENTITY_${config} STREQUAL "Mac Developer") set(is_using_default FALSE) else() set(is_using_default TRUE) endif() if(NOT is_using_default OR NOT development_team_id_string STREQUAL "") if(is_using_default) set(identity "Mac Developer") else() set(identity "${JUCER_CODE_SIGNING_IDENTITY_${config}}") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=${config}] "${identity}" ) endif() endif() endforeach() else() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(identity_string "${JUCER_CODE_SIGNING_IDENTITY_${config}}") if(identity_string STREQUAL "" AND NOT development_team_id_string STREQUAL "") set(is_using_default_signing_identity TRUE) else() set(is_using_default_signing_identity FALSE) endif() if(is_using_default_signing_identity) if(IOS) set(identity "iPhone Developer") else() set(identity "Mac Developer") endif() else() set(identity "${identity_string}") endif() if(IOS) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[sdk=iphoneos*][variant=${config}] "${identity}" ) else() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=${config}] "${identity}" ) endif() if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.0)) if(NOT identity STREQUAL "" AND NOT is_using_default_signing_identity) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_STYLE[variant=${config}] "Manual" ) endif() endif() endforeach() endif() if(NOT development_team_id_string STREQUAL "") set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${development_team_id_string}" ) endif() if( JUCER_PUSH_NOTIFICATIONS_CAPABILITY OR JUCER_APP_GROUPS_CAPABILITY OR JUCER_USE_APP_SANDBOX OR JUCER_USE_HARDENED_RUNTIME OR (IOS AND JUCER_ICLOUD_PERMISSIONS) OR ( JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in" AND ( (NOT IOS AND target MATCHES "_AUv3_AppExtension$") OR ( IOS AND target MATCHES "_StandalonePlugin$" AND JUCER_ENABLE_INTER_APP_AUDIO ) ) ) ) _FRUT_generate_entitlements_file(${target} "${target}.entitlements" entitlements_file) if(CMAKE_GENERATOR STREQUAL "Xcode") target_sources(${target} PRIVATE "${entitlements_file}") set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${entitlements_file}" ) else() message(WARNING "Reprojucer.cmake only supports entitlements when using the Xcode" " generator. You should call `cmake -G Xcode` if you want to use entitlements." ) endif() endif() if(JUCER_USE_HARDENED_RUNTIME) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES" ) endif() if(CMAKE_GENERATOR STREQUAL "Xcode" AND DEFINED JUCER_USE_HEADERMAP) if(JUCER_USE_HEADERMAP) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_USE_HEADERMAP "YES") else() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_USE_HEADERMAP "NO") endif() endif() foreach(xcode_lib IN LISTS JUCER_PROJECT_XCODE_LIBS) target_link_libraries(${target} PRIVATE "-l${xcode_lib}") endforeach() foreach(framework_name IN LISTS JUCER_PROJECT_XCODE_WEAK_FRAMEWORKS) target_link_libraries(${target} PRIVATE "-weak_framework ${framework_name}") endforeach() endfunction() function(_FRUT_set_compiler_and_linker_settings_Linux target) target_compile_definitions(${target} PRIVATE "LINUX=1") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) target_compile_definitions(${target} PRIVATE $<$:DEBUG=1> $<$:_DEBUG=1> ) else() target_compile_definitions(${target} PRIVATE $<$:NDEBUG=1>) endif() string(TOUPPER "${config}" upper_config) if(JUCER_LINK_TIME_OPTIMISATION_${config}) target_compile_options(${target} PRIVATE $<$:-flto>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " -flto" ) endif() if(DEFINED JUCER_ARCHITECTURE_FLAG_${config}) set(architecture_flag "${JUCER_ARCHITECTURE_FLAG_${config}}") else() if(CMAKE_EXTRA_GENERATOR STREQUAL "CodeBlocks") set(architecture_flag "-m64") else() if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.4.7) set(architecture_flag "-march=native") else() set(architecture_flag "") endif() endif() endif() target_compile_options(${target} PRIVATE $<$:${architecture_flag}>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " ${architecture_flag}" ) endforeach() set(linux_packages ${JUCER_PROJECT_LINUX_PACKAGES} ${JUCER_PKGCONFIG_LIBRARIES}) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) AND "juce_gui_extra" IN_LIST JUCER_PROJECT_MODULES AND (NOT DEFINED JUCER_FLAG_JUCE_WEB_BROWSER OR JUCER_FLAG_JUCE_WEB_BROWSER)) list(APPEND linux_packages "webkit2gtk-4.0" "gtk+-x11-3.0") endif() if((NOT DEFINED JUCER_VERSION OR JUCER_VERSION VERSION_GREATER 5.3.2) AND "juce_core" IN_LIST JUCER_PROJECT_MODULES AND (NOT DEFINED JUCER_FLAG_JUCE_USE_CURL OR JUCER_FLAG_JUCE_USE_CURL) AND NOT JUCER_FLAG_JUCE_LOAD_CURL_SYMBOLS_LAZILY) list(APPEND linux_packages "libcurl") endif() if(linux_packages) find_package(PkgConfig REQUIRED) list(REMOVE_DUPLICATES linux_packages) unset(missing_packages) foreach(pkg IN LISTS linux_packages) pkg_check_modules(${pkg} "${pkg}") if(NOT ${pkg}_FOUND) string(APPEND missing_packages " ${pkg}") endif() target_compile_options(${target} PRIVATE ${${pkg}_CFLAGS}) target_link_libraries(${target} PRIVATE ${${pkg}_LIBRARIES}) endforeach() if(DEFINED missing_packages) message(FATAL_ERROR "pkg-config could not find the following packages:" "${missing_packages}" ) endif() else() if("juce_graphics" IN_LIST JUCER_PROJECT_MODULES) target_include_directories(${target} PRIVATE "/usr/include/freetype2") endif() if(JUCER_FLAG_JUCE_USE_CURL) target_link_libraries(${target} PRIVATE "-lcurl") endif() endif() foreach(linux_lib IN LISTS JUCER_PROJECT_LINUX_LIBS) if(linux_lib STREQUAL "pthread") target_compile_options(${target} PRIVATE "-pthread") endif() target_link_libraries(${target} PRIVATE "-l${linux_lib}") endforeach() if(JUCER_PROJECT_TYPE STREQUAL "Audio Plug-in" OR JUCER_PROJECT_TYPE STREQUAL "Dynamic Library") target_compile_options(${target} PRIVATE "-fPIC") endif() endfunction() function(_FRUT_set_compiler_and_linker_settings_MinGW target) target_compile_definitions(${target} PRIVATE "__MINGW__=1" "__MINGW_EXTENSION=") if(DEFINED JUCER_TARGET_PLATFORM AND NOT JUCER_TARGET_PLATFORM STREQUAL "Default") set(target_platform_values "Windows NT 4.0" "Windows 2000" "Windows XP" "Windows Server 2003" "Windows Vista" "Windows Server 2008" "Windows 7" "Windows 8" "Windows 8.1" "Windows 10" ) set(winver_define_values "0x0400" "0x0500" "0x0501" "0x0502" "0x0600" "0x0600" "0x0601" "0x0602" "0x0603" "0x0A00" ) list(FIND target_platform_values "${JUCER_TARGET_PLATFORM}" target_platform_index) if(target_platform_index EQUAL -1) message(FATAL_ERROR "Unsupported value for JUCER_TARGET_PLATFORM: \"${target_platform}\"" ) endif() list(GET winver_define_values ${target_platform_index} winver_define_value) target_compile_definitions(${target} PRIVATE "WINVER=${winver_define_value}") endif() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) if(JUCER_CONFIGURATION_IS_DEBUG_${config}) target_compile_definitions(${target} PRIVATE $<$:DEBUG=1> $<$:_DEBUG=1> ) target_compile_options(${target} PRIVATE $<$:-g>) else() target_compile_definitions(${target} PRIVATE $<$:NDEBUG=1>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " -s" ) endif() if(JUCER_LINK_TIME_OPTIMISATION_${config}) target_compile_options(${target} PRIVATE $<$:-flto>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " -flto" ) endif() if(DEFINED JUCER_ARCHITECTURE_FLAG_${config}) target_compile_options(${target} PRIVATE $<$:${JUCER_ARCHITECTURE_FLAG_${config}}> ) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " ${JUCER_ARCHITECTURE_FLAG_${config}}" ) endif() endforeach() target_compile_options(${target} PRIVATE "-mstackrealign") if(JUCER_PROJECT_MINGW_LIBS) target_link_libraries(${target} PRIVATE ${JUCER_PROJECT_MINGW_LIBS}) endif() endfunction() function(_FRUT_set_compiler_and_linker_settings_MSVC target) target_compile_definitions(${target} PRIVATE "_CRT_SECURE_NO_WARNINGS") if(MSVC_VERSION EQUAL 1800) # Visual Studio 2013 set(ltcg_link_flag "/LTCG") else() set(ltcg_link_flag "/LTCG:incremental") endif() foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) if(NOT DEFINED JUCER_MULTI_PROCESSOR_COMPILATION_${config} OR JUCER_MULTI_PROCESSOR_COMPILATION_${config}) target_compile_options(${target} PRIVATE $<$:/MP>) endif() if(JUCER_CONFIGURATION_IS_DEBUG_${config}) target_compile_definitions(${target} PRIVATE $<$:DEBUG> $<$:_DEBUG> ) if(JUCER_LINK_TIME_OPTIMISATION_${config}) target_compile_options(${target} PRIVATE $<$:/GL>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " ${ltcg_link_flag}" ) set_property(TARGET ${target} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS_${upper_config} " /LTCG" ) endif() else() target_compile_definitions(${target} PRIVATE $<$:NDEBUG>) if(NOT JUCER_ALWAYS_DISABLE_WPO_${config} AND NOT (DEFINED JUCER_LINK_TIME_OPTIMISATION_${config} AND NOT JUCER_LINK_TIME_OPTIMISATION_${config})) target_compile_options(${target} PRIVATE $<$:/GL>) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " ${ltcg_link_flag}" ) set_property(TARGET ${target} APPEND_STRING PROPERTY STATIC_LIBRARY_FLAGS_${upper_config} " /LTCG" ) endif() endif() if(NOT DEFINED JUCER_CHARACTER_SET_${config} OR JUCER_CHARACTER_SET_${config} STREQUAL "Default") target_compile_definitions(${target} PRIVATE $<$:_SBCS>) elseif(JUCER_CHARACTER_SET_${config} STREQUAL "MultiByte") # Nothing to do, this is CMake's default elseif(JUCER_CHARACTER_SET_${config} STREQUAL "Unicode") target_compile_definitions(${target} PRIVATE $<$:_UNICODE> $<$:UNICODE> ) endif() if(JUCER_CONFIGURATION_IS_DEBUG_${config}) set(d_or_empty "d") else() set(d_or_empty "") endif() if(DEFINED JUCER_RUNTIME_LIBRARY_FLAG_${config}) target_compile_options(${target} PRIVATE $<$:${JUCER_RUNTIME_LIBRARY_FLAG_${config}}> ) elseif(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.1)) target_compile_options(${target} PRIVATE $<$:/MD${d_or_empty}>) elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0 AND (JUCER_BUILD_VST OR JUCER_BUILD_VST3 OR JUCER_BUILD_RTAS OR JUCER_BUILD_AAX)) target_compile_options(${target} PRIVATE $<$:/MD${d_or_empty}>) elseif(JUCER_BUILD_RTAS OR JUCER_BUILD_AAX) target_compile_options(${target} PRIVATE $<$:/MD${d_or_empty}>) else() target_compile_options(${target} PRIVATE $<$:/MT${d_or_empty}>) endif() if(DEFINED JUCER_DEBUG_INFORMATION_FORMAT_FLAG_${config}) target_compile_options(${target} PRIVATE $<$:${JUCER_DEBUG_INFORMATION_FORMAT_FLAG_${config}}> ) endif() if(DEFINED JUCER_WARNING_LEVEL_FLAG_${config}) target_compile_options(${target} PRIVATE $<$:${JUCER_WARNING_LEVEL_FLAG_${config}}> ) else() target_compile_options(${target} PRIVATE $<$:/W4>) endif() if(JUCER_TREAT_WARNINGS_AS_ERRORS_${config}) target_compile_options(${target} PRIVATE $<$:/WX>) endif() if(JUCER_RELAX_IEEE_COMPLIANCE_${config}) target_compile_options(${target} PRIVATE $<$:/fp:fast>) endif() if(DEFINED JUCER_INCREMENTAL_LINKING_${config}) if(JUCER_INCREMENTAL_LINKING_${config}) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " /INCREMENTAL" ) endif() endif() if(DEFINED JUCER_FORCE_GENERATION_OF_DEBUG_SYMBOLS_${config}) if(JUCER_FORCE_GENERATION_OF_DEBUG_SYMBOLS_${config}) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " /DEBUG" ) endif() endif() if(DEFINED JUCER_GENERATE_MANIFEST_${config}) if(NOT JUCER_GENERATE_MANIFEST_${config}) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_${upper_config} " /MANIFEST:NO" ) endif() endif() endforeach() foreach(windows_lib IN LISTS JUCER_PROJECT_WINDOWS_LIBS) target_link_libraries(${target} PRIVATE "${windows_lib}.lib") endforeach() endfunction() function(_FRUT_set_custom_xcode_flags target) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) if(DEFINED JUCER_CUSTOM_XCODE_FLAGS_${config}) foreach(xcode_flag IN LISTS JUCER_CUSTOM_XCODE_FLAGS_${config}) string(REGEX MATCH "^([^= ]+) *= *(.+)" m "${xcode_flag}") if(NOT CMAKE_MATCH_0) message(FATAL_ERROR "Invalid Xcode flag: \"${xcode_flag}\"") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_${CMAKE_MATCH_1}[variant=${config}] "${CMAKE_MATCH_2}" ) endforeach() endif() endforeach() endfunction() function(_FRUT_set_cxx_language_standard_properties target) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.1.0)) if(DEFINED JUCER_CXX_LANGUAGE_STANDARD) set(cxx_language_standard "${JUCER_CXX_LANGUAGE_STANDARD}") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.2.1) set(cxx_language_standard "11") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 7.0.3) set(cxx_language_standard "14") else() set(cxx_language_standard "17") endif() if(CMAKE_GENERATOR STREQUAL "Xcode") if(cxx_language_standard STREQUAL "latest") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.0) set(cxx_language_standard "1z") elseif(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.3) set(cxx_language_standard "17") else() set(cxx_language_standard "20") endif() endif() if(JUCER_GNU_COMPILER_EXTENSIONS) set(cxx_language_standard "gnu++${cxx_language_standard}") else() set(cxx_language_standard "c++${cxx_language_standard}") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "${cxx_language_standard}" ) elseif(MSVC) if(MSVC_VERSION EQUAL 1900 OR MSVC_VERSION GREATER 1900) # VS2015 and later if(cxx_language_standard STREQUAL "17" AND MSVC_VERSION LESS 1911) # -std:c++17 is available since Visual Studio 2017 version 15.3, which is # MSVC_VERSION 1911. set(cxx_language_standard "latest") endif() if(NOT cxx_language_standard STREQUAL "11") target_compile_options(${target} PRIVATE "-std:c++${cxx_language_standard}") endif() endif() else() if(JUCER_GNU_COMPILER_EXTENSIONS) set_target_properties(${target} PROPERTIES CXX_EXTENSIONS ON) else() set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF) endif() if(cxx_language_standard STREQUAL "latest") if(DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 6.1.3) set(cxx_language_standard "17") else() set(cxx_language_standard "20") endif() endif() set_target_properties(${target} PROPERTIES CXX_STANDARD ${cxx_language_standard}) endif() else() if(APPLE) if(CMAKE_GENERATOR STREQUAL "Xcode") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) set(cxx_language_standard "c++0x") if(DEFINED JUCER_CXX_LANGUAGE_STANDARD_${config}) string(TOLOWER cxx_language_standard "${JUCER_CXX_LANGUAGE_STANDARD_${config}}" ) endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD[variant=${config}] "${cxx_language_standard}" ) endforeach() else() set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(${target} PROPERTIES CXX_STANDARD 11) set(cxx_language_standard "${JUCER_CXX_LANGUAGE_STANDARD_${CMAKE_BUILD_TYPE}}") if(cxx_language_standard) if(cxx_language_standard MATCHES "^GNU\\+\\+") set_target_properties(${target} PROPERTIES CXX_EXTENSIONS ON) endif() if(cxx_language_standard MATCHES "98$") set_target_properties(${target} PROPERTIES CXX_STANDARD 98) elseif(cxx_language_standard MATCHES "14$") set_target_properties(${target} PROPERTIES CXX_STANDARD 14) endif() endif() endif() elseif(MSVC) if(MSVC_VERSION EQUAL 1900 OR MSVC_VERSION GREATER 1900) # VS2015 and later if(JUCER_CXX_STANDARD_TO_USE STREQUAL "14") target_compile_options(${target} PRIVATE "-std:c++14") elseif(JUCER_CXX_STANDARD_TO_USE STREQUAL "latest") target_compile_options(${target} PRIVATE "-std:c++latest") endif() endif() elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(${target} PROPERTIES CXX_STANDARD 11) if(DEFINED JUCER_CXX_STANDARD_TO_USE) if(JUCER_CXX_STANDARD_TO_USE MATCHES "03$") set_target_properties(${target} PROPERTIES CXX_STANDARD 98) elseif(JUCER_CXX_STANDARD_TO_USE MATCHES "14$") set_target_properties(${target} PROPERTIES CXX_STANDARD 14) endif() endif() elseif(WIN32 AND NOT MSVC) set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(${target} PROPERTIES CXX_STANDARD 11) endif() endif() endfunction() function(_FRUT_set_IPP_windows_compiler_and_linker_settings target) set(ipp_registry_base_path "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Intel\\Suites") if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit set(ipp_registry_key "EMT64") set(ipp_arch "intel64_win") else() set(ipp_registry_key "IA32") set(ipp_arch "ia32_win") endif() get_filename_component(JUCER_IPP_SUB_KEY "[${ipp_registry_base_path}\\Defaults\\${ipp_registry_key};IPPSubKey]" ABSOLUTE BASE_DIR "" CACHE ) file(TO_NATIVE_PATH "${JUCER_IPP_SUB_KEY}" ipp_sub_key) set(env_var "programfiles(x86)") # needed because $ENV{} can't deal with parentheses find_path(JUCER_IPP_INSTALL_DIR NAMES "compiler/lib" "ipp/include" "ipp/lib" HINTS "[${ipp_registry_base_path}\\${ipp_sub_key}\\IPP;ProductDir]" "$ENV{${env_var}}/IntelSWTools/compilers_and_libraries/windows" ) if(NOT JUCER_IPP_INSTALL_DIR OR NOT IS_DIRECTORY "${JUCER_IPP_INSTALL_DIR}") message(FATAL_ERROR "Could not find Intel IPP. Please set JUCER_IPP_INSTALL_DIR to" " the Intel IPP , as documented on" " https://software.intel.com/ipp-dev-guide-finding-intel-ipp-on-your-system." ) endif() set(use_ipp_library_values "Yes (Default Mode)" "Yes (Default Linking)" "Multi-Threaded Static Library" "Single-Threaded Static Library" "Multi-Threaded DLL" "Single-Threaded DLL" ) list(FIND use_ipp_library_values "${JUCER_USE_IPP_LIBRARY}" ipp_linking_method_index) if(ipp_linking_method_index EQUAL -1) message(FATAL_ERROR "Unsupported value for JUCER_USE_IPP_LIBRARY: \"${JUCER_USE_IPP_LIBRARY}\"" ) endif() set(ipp_compile_definitions "_IPP_SEQUENTIAL_DYNAMIC" "_IPP_SEQUENTIAL_DYNAMIC" "_IPP_PARALLEL_STATIC" "_IPP_SEQUENTIAL_STATIC" "_IPP_PARALLEL_DYNAMIC" "_IPP_SEQUENTIAL_DYNAMIC" ) list(GET ipp_compile_definitions ${ipp_linking_method_index} ipp_compile_definition) target_compile_definitions(${target} PRIVATE "${ipp_compile_definition}") target_include_directories(${target} PRIVATE "${JUCER_IPP_INSTALL_DIR}/ipp/include") target_link_libraries(${target} PRIVATE "-LIBPATH:${JUCER_IPP_INSTALL_DIR}/ipp/lib/${ipp_arch}" "-LIBPATH:${JUCER_IPP_INSTALL_DIR}/compiler/lib/${ipp_arch}" ) endfunction() function(_FRUT_set_JucePlugin_Build_defines target target_type) if(JUCER_BUILD_AUDIOUNIT_V3 AND DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0) set(JUCER_BUILD_STANDALONE_PLUGIN ON) endif() set(plugin_types VST VST3 AudioUnit AudioUnitv3 RTAS AAX Standalone ) set(setting_suffixes VST VST3 AUDIOUNIT AUDIOUNIT_V3 RTAS AAX STANDALONE_PLUGIN) set(define_suffixes VST VST3 AU AUv3 RTAS AAX Standalone ) set(range_max 6) if(NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.3.2)) list(APPEND plugin_types Unity) list(APPEND setting_suffixes UNITY_PLUGIN) list(APPEND define_suffixes Unity) set(range_max 7) endif() foreach(index RANGE ${range_max}) list(GET setting_suffixes ${index} setting_suffix) list(GET plugin_types ${index} plugin_type) list(GET define_suffixes ${index} define_suffix) if(target_type STREQUAL "${plugin_type}PlugIn" OR (target_type STREQUAL "SharedCodeTarget" AND JUCER_BUILD_${setting_suffix})) target_compile_definitions(${target} PRIVATE "JucePlugin_Build_${define_suffix}=1") else() target_compile_definitions(${target} PRIVATE "JucePlugin_Build_${define_suffix}=0") endif() endforeach() endfunction() function(_FRUT_set_output_directory_properties target subfolder) foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) unset(output_directory) string(TOUPPER "${config}" upper_config) if(MSVC AND NOT (DEFINED JUCER_VERSION AND JUCER_VERSION VERSION_LESS 5.0.0)) if(DEFINED JUCER_BINARY_LOCATION_${config}) set(output_directory "${JUCER_BINARY_LOCATION_${config}}/${subfolder}") else() set(output_directory "${CMAKE_CURRENT_BINARY_DIR}/$/${subfolder}") endif() elseif(DEFINED JUCER_BINARY_LOCATION_${config}) set(output_directory "${JUCER_BINARY_LOCATION_${config}}") endif() if(DEFINED output_directory) set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY_${upper_config} "${output_directory}" LIBRARY_OUTPUT_DIRECTORY_${upper_config} "${output_directory}" RUNTIME_OUTPUT_DIRECTORY_${upper_config} "${output_directory}" ) endif() endforeach() endfunction() function(_FRUT_set_output_name_properties target) if(ARGC GREATER 1) if(NOT ARGV1 STREQUAL "ADD_lib_PREFIX") message(FATAL_ERROR "Unexpected argument \"${ARGV1}\"") endif() endif() set_target_properties(${target} PROPERTIES PREFIX "") foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) if(JUCER_BINARY_NAME_${config}) set(output_name "${JUCER_BINARY_NAME_${config}}") else() set(output_name "${JUCER_PROJECT_NAME}") endif() if(NOT output_name MATCHES "^lib" AND ARGV1 STREQUAL "ADD_lib_PREFIX") set(output_name "lib${output_name}") endif() set_target_properties(${target} PROPERTIES OUTPUT_NAME_${upper_config} "${output_name}" ) endforeach() endfunction() function(_FRUT_set_output_name_properties_Unity unity_target) set_target_properties(${unity_target} PROPERTIES PREFIX "") # Like _FRUT_set_output_name_properties(${unity_target}), but handles the # "audioplugin" prefix as well foreach(config IN LISTS JUCER_PROJECT_CONFIGURATIONS) string(TOUPPER "${config}" upper_config) if(JUCER_BINARY_NAME_${config}) set(output_name "${JUCER_BINARY_NAME_${config}}") else() set(output_name "${JUCER_PROJECT_NAME}") endif() if(NOT output_name MATCHES "^[Aa][Uu][Dd][Ii][Oo][Pp][Ll][Uu][Gg][Ii][Nn]") set(output_name "audioplugin_${output_name}") endif() set_target_properties(${unity_target} PROPERTIES OUTPUT_NAME_${upper_config} "${output_name}" ) endforeach() endfunction() function(_FRUT_set_product_bundle_identifier target) if(DEFINED JUCER_EXPORTER_BUNDLE_IDENTIFIER AND NOT JUCER_EXPORTER_BUNDLE_IDENTIFIER STREQUAL "") set(bundle_identifier "${JUCER_EXPORTER_BUNDLE_IDENTIFIER}") else() set(bundle_identifier "${JUCER_BUNDLE_IDENTIFIER}") endif() set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_identifier}" ) endfunction() function(_FRUT_version_to_dec version out_dec_value) string(REPLACE "." ";" segments "${version}") list(LENGTH segments segments_size) while(segments_size LESS 3) list(APPEND segments 0) math(EXPR segments_size "${segments_size} + 1") endwhile() list(GET segments 0 major) list(GET segments 1 minor) list(GET segments 2 patch) math(EXPR dec_value "(${major} << 16) + (${minor} << 8) + ${patch}") if(segments_size GREATER 3) list(GET segments 3 revision) math(EXPR dec_value "${dec_value} << 8 + ${revision}") endif() set(${out_dec_value} "${dec_value}" PARENT_SCOPE) endfunction() function(_FRUT_version_to_hex version out_hex_value) _FRUT_version_to_dec("${version}" dec_value) _FRUT_dec_to_hex("${dec_value}" hex_value) set(${out_hex_value} "${hex_value}" PARENT_SCOPE) endfunction() function(_FRUT_warn_about_unsupported_setting setting projucer_setting issue_number) message(WARNING "Reprojucer.cmake doesn't support the setting ${setting}" " (\"${projucer_setting}\" in Projucer). If you would like Reprojucer.cmake to" " support this setting, please write a new comment on the issue \"Reprojucer.cmake" " doesn't support the setting `${setting}`\" on GitHub:" " https://github.com/McMartin/FRUT/issues/${issue_number}" ) endfunction() function(_FRUT_write_failure_report_and_abort action tool_name execute_process_output) execute_process( COMMAND "git" "rev-parse" "HEAD" WORKING_DIRECTORY "${Reprojucer.cmake_DIR}" OUTPUT_VARIABLE git_rev_parse_output RESULT_VARIABLE git_rev_parse_return_code OUTPUT_STRIP_TRAILING_WHITESPACE ) if(git_rev_parse_return_code EQUAL 0) set(frut_version "commit ${git_rev_parse_output}") else() set(frut_version "unknown (`git rev-parse HEAD` failed)") endif() if(DEFINED JUCER_PROJECT_MODULE_juce_core_PATH) execute_process( COMMAND "git" "describe" "--tags" "--always" WORKING_DIRECTORY "${JUCER_PROJECT_MODULE_juce_core_PATH}" OUTPUT_VARIABLE git_describe_output RESULT_VARIABLE git_describe_return_code OUTPUT_STRIP_TRAILING_WHITESPACE ) if(git_describe_return_code EQUAL 0) set(juce_version "`${git_describe_output}`") else() set(juce_version "`${JUCER_PROJECT_MODULE_juce_core_VERSION}`") endif() else() set(juce_version "unknown (no juce_core module)") endif() string(REPLACE "\r\n" "\n" execute_process_output "${execute_process_output}") configure_file("${Reprojucer_data_DIR}/failed-to.md.in" "failed-to-${action}-${tool_name}.md" @ONLY ) message(FATAL_ERROR "Failed to ${action} ${tool_name}. Please report this problem by" " creating a new issue on GitHub: https://github.com/McMartin/FRUT/issues/new." "\nPlease copy-paste the contents of" " ${CMAKE_CURRENT_BINARY_DIR}/failed-to-${action}-${tool_name}.md in the commment." ) endfunction() ================================================ FILE: cmake/data/AppConfig-4.h.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - if you alter its contents, your changes may be overwritten! Any commented-out settings will assume their default values. */ #ifndef __JUCE_APPCONFIG_@upper_project_id@__ #define __JUCE_APPCONFIG_@upper_project_id@__ //============================================================================== // [BEGIN_USER_CODE_SECTION]@user_code_section@// [END_USER_CODE_SECTION] //============================================================================== @module_available_defines@ //============================================================================== #ifndef JUCE_STANDALONE_APPLICATION #ifdef JucePlugin_Build_Standalone #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone #else #define JUCE_STANDALONE_APPLICATION @is_standalone_application@ #endif #endif #define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 @config_flags_defines@ @audio_plugin_settings_defines@ #endif // __JUCE_APPCONFIG_@upper_project_id@__ ================================================ FILE: cmake/data/AppConfig-5.h.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - if you alter its contents, your changes may be overwritten! Any commented-out settings will assume their default values. */ #pragma once //============================================================================== // [BEGIN_USER_CODE_SECTION]@user_code_section@// [END_USER_CODE_SECTION] /* ============================================================================== In accordance with the terms of the JUCE 5 End-Use License Agreement, the JUCE Code in SECTION A cannot be removed, changed or otherwise rendered ineffective unless you have a JUCE Indie or Pro license, or are using JUCE under the GPL v3 license. End User License Agreement: www.juce.com/juce-5-licence ============================================================================== */ // BEGIN SECTION A #ifndef JUCE_DISPLAY_SPLASH_SCREEN #define JUCE_DISPLAY_SPLASH_SCREEN @display_splash_screen@ #endif #ifndef JUCE_REPORT_APP_USAGE #define JUCE_REPORT_APP_USAGE @report_app_usage@ #endif // END SECTION A #define JUCE_USE_DARK_SPLASH_SCREEN @use_dark_splash_screen@ //============================================================================== @module_available_defines@ #define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 @config_flags_defines@@audio_plugin_settings_defines@ //============================================================================== #ifndef JUCE_STANDALONE_APPLICATION #if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone) #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone #else #define JUCE_STANDALONE_APPLICATION @is_standalone_application@ #endif #endif ================================================ FILE: cmake/data/AppConfig.h.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - if you alter its contents, your changes may be overwritten! Any commented-out settings will assume their default values. */ #pragma once //============================================================================== // [BEGIN_USER_CODE_SECTION]@user_code_section@// [END_USER_CODE_SECTION] @include_JucePluginDefines_header@ /* ============================================================================== In accordance with the terms of the JUCE 6 End-Use License Agreement, the JUCE Code in SECTION A cannot be removed, changed or otherwise rendered ineffective unless you have a JUCE Indie or Pro license, or are using JUCE under the GPL v3 license. End User License Agreement: www.juce.com/juce-6-licence ============================================================================== */ // BEGIN SECTION A #ifndef JUCE_DISPLAY_SPLASH_SCREEN #define JUCE_DISPLAY_SPLASH_SCREEN @display_splash_screen@ #endif // END SECTION A #define JUCE_USE_DARK_SPLASH_SCREEN @use_dark_splash_screen@ //============================================================================== @module_available_defines@ #define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 @config_flags_defines@ //============================================================================== #ifndef JUCE_STANDALONE_APPLICATION #if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone) #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone #else #define JUCE_STANDALONE_APPLICATION @is_standalone_application@ #endif #endif ================================================ FILE: cmake/data/Info.plist.in ================================================ @plist_entries@ ================================================ FILE: cmake/data/JuceHeader.h.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - 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. */ @include_guard_top@ @appconfig_include@@modules_includes@@binary_data_include@ @using_namespace_juce_block@#if ! JUCE_DONT_DECLARE_PROJECTINFO namespace ProjectInfo { const char* const projectName = "@JUCER_PROJECT_NAME@";@company_name_field@ const char* const versionString = "@JUCER_PROJECT_VERSION@"; const int versionNumber = @JUCER_PROJECT_VERSION_AS_HEX@; } #endif@include_guard_bottom@ ================================================ FILE: cmake/data/JuceLibraryCode-Wrapper.cpp.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - if you alter its contents, your changes may be overwritten! */ @appconfig_include@#include <@proxied_src_file@> ================================================ FILE: cmake/data/JucePluginDefines.h.in ================================================ /* IMPORTANT! This file is auto-generated each time you run cmake on your project - if you alter its contents, your changes may be overwritten! */ #pragma once @audio_plugin_settings_defines@ ================================================ FILE: cmake/data/LaunchScreen.storyboard ================================================ ================================================ FILE: cmake/data/PkgInfo ================================================ BNDL???? ================================================ FILE: cmake/data/UnityScript.cs.in ================================================ #if UNITY_EDITOR using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.Runtime.InteropServices; 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@"; } } //============================================================================== [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 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 unitySetScreenBounds (int id, float x, float y, float w, float h); //============================================================================== private class PluginGUIInstance { public PluginGUIInstance (ref IAudioEffectPlugin plugin, int id) { instanceID = id; float[] arr; plugin.GetFloatBuffer ("Editor", out arr, 1); hasEditor = (arr[0] > 0.0f); } public void repaint (Rect r) { Vector2 newScreenPosition = GUIUtility.GUIToScreenPoint (r.position); if (bounds != r || screenPosition != newScreenPosition) { screenPosition = newScreenPosition; bounds = r; unitySetScreenBounds (instanceID, screenPosition.x, screenPosition.y, bounds.width, bounds.height); setupTexture(); } GL.IssuePluginEvent (getRenderCallback(), instanceID); texture.SetPixels32 (pixels); texture.Apply(); EditorGUI.DrawPreviewTexture (bounds, texture); } public bool handleMouseEvent (EventType eventType) { Vector2 mousePos = Event.current.mousePosition; EventModifiers mods = Event.current.modifiers; if (! bounds.Contains (mousePos)) return false; Vector2 relativePos = new Vector2 (mousePos.x - bounds.x, mousePos.y - bounds.y); if (eventType == EventType.MouseDown) { unityMouseDown (instanceID, relativePos.x, relativePos.y, mods, Event.current.button); GUIUtility.hotControl = GUIUtility.GetControlID (FocusType.Passive); } else if (eventType == EventType.MouseUp) { unityMouseUp (instanceID, relativePos.x, relativePos.y, mods); GUIUtility.hotControl = 0; } else if (eventType == EventType.MouseDrag) { unityMouseDrag (instanceID, relativePos.x, relativePos.y, mods, Event.current.button); } Event.current.Use(); return true; } public void handleKeyEvent (EventType eventType) { if (eventType == EventType.KeyDown) { KeyCode code = Event.current.keyCode; if (code == KeyCode.None) return; EventModifiers mods = Event.current.modifiers; unityKeyEvent (instanceID, code, mods, code.ToString()); } } private void setupTexture() { if (pixelHandle.IsAllocated) pixelHandle.Free(); texture = new Texture2D ((int) bounds.width, (int) bounds.height, TextureFormat.ARGB32, false); pixels = texture.GetPixels32(); pixelHandle = GCHandle.Alloc (pixels, GCHandleType.Pinned); unityInitialiseTexture (instanceID, pixelHandle.AddrOfPinnedObject(), texture.width, texture.height); } public int instanceID = -1; public bool hasEditor; private Vector2 screenPosition; private Rect bounds; private Texture2D texture; private Color32[] pixels; private GCHandle pixelHandle; } List guis = new List(); private PluginGUIInstance getGUIInstanceForPlugin (ref IAudioEffectPlugin plugin) { float[] idArray; plugin.GetFloatBuffer ("ID", out idArray, 1); int id = (int) idArray[0]; for (int i = 0; i < guis.Count; ++i) { if (guis[i].instanceID == id) return guis[i]; } PluginGUIInstance newInstance = new PluginGUIInstance (ref plugin, id); guis.Add (newInstance); return guis[guis.Count - 1]; } //============================================================================== public override bool OnGUI (IAudioEffectPlugin plugin) { PluginGUIInstance guiInstance = getGUIInstanceForPlugin (ref plugin); if (! guiInstance.hasEditor) return true; float[] arr; plugin.GetFloatBuffer ("Size", out arr, 6); Rect r = GUILayoutUtility.GetRect (arr[0], arr[1], new GUILayoutOption[] { GUILayout.MinWidth (arr[2]), GUILayout.MinHeight (arr[3]), GUILayout.MaxWidth (arr[4]), GUILayout.MaxHeight (arr[5]) }); int controlID = GUIUtility.GetControlID (FocusType.Passive); Event currentEvent = Event.current; EventType currentEventType = currentEvent.GetTypeForControl (controlID); if (currentEventType == EventType.Repaint) guiInstance.repaint (r); else if (currentEvent.isMouse) guiInstance.handleMouseEvent (currentEventType); else if (currentEvent.isKey) guiInstance.handleKeyEvent (currentEventType); return false; } } #endif ================================================ FILE: cmake/data/failed-to.md.in ================================================ ### Failed to @action@ `@tool_name@` #### Versions CMake: `@CMAKE_VERSION@` FRUT: @frut_version@ JUCE: @juce_version@ #### CMake variables ``` CMAKE_C_COMPILER: "@CMAKE_C_COMPILER@" CMAKE_C_COMPILER_ID: "@CMAKE_C_COMPILER_ID@" CMAKE_C_COMPILER_VERSION: "@CMAKE_C_COMPILER_VERSION@" CMAKE_CXX_COMPILER: "@CMAKE_CXX_COMPILER@" CMAKE_CXX_COMPILER_ID: "@CMAKE_CXX_COMPILER_ID@" CMAKE_CXX_COMPILER_VERSION: "@CMAKE_CXX_COMPILER_VERSION@" CMAKE_EXTRA_GENERATOR: "@CMAKE_EXTRA_GENERATOR@" CMAKE_GENERATOR: "@CMAKE_GENERATOR@" CMAKE_GENERATOR_PLATFORM: "@CMAKE_GENERATOR_PLATFORM@" CMAKE_GENERATOR_TOOLSET: "@CMAKE_GENERATOR_TOOLSET@" CMAKE_SYSTEM: "@CMAKE_SYSTEM@" ``` #### Variables from `Reprojucer.cmake` ``` JUCER_PROJECT_TYPE: "@JUCER_PROJECT_TYPE@" JUCER_VERSION: "@JUCER_VERSION@" ``` #### Output of `execute_process()` ``` @execute_process_output@ ``` ================================================ FILE: cmake/data/juce_runtime_arch_detection.cpp ================================================ // This file was copied from // https://github.com/juce-framework/JUCE/blob/6.0.8/extras/Build/CMake/juce_runtime_arch_detection.cpp #if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) #if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) #error JUCE_ARCH aarch64 #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__) #error JUCE_ARCH armv8l #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEXA__) #error JUCE_ARCH armv7l #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6M__) #error JUCE_ARCH armv6l #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 5) || defined(__ARM_ARCH_5TEJ__) #error JUCE_ARCH armv5l #else #error JUCE_ARCH arm #endif #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) #error JUCE_ARCH i386 #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) #error JUCE_ARCH x86_64 #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) #error JUCE_ARCH ia64 #elif defined(__mips) || defined(__mips__) || defined(_M_MRX000) #if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) #error JUCE_ARCH mips64 #else #error JUCE_ARCH mips #endif #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_M_MPPC) || defined(_M_PPC) #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) #error JUCE_ARCH ppc64 #else #error JUCE_ARCH ppc #endif #elif defined(__riscv) #if __riscv_xlen == 64 #error JUCE_ARCH riscv64 #else #error JUCE_ARCH riscv #endif #else #error JUCE_ARCH unknown #endif ================================================ FILE: cmake/data/resources.rc.in ================================================ #ifdef JUCE_USER_DEFINED_RC_FILE #include JUCE_USER_DEFINED_RC_FILE #else #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include VS_VERSION_INFO VERSIONINFO FILEVERSION @comma_separated_version_number@ BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN @rc_string_file_info_values@ END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1252 END END #endif@resources_rc_icon_settings@ ================================================ FILE: cmake/data/script.in ================================================ @script_content@ ================================================ FILE: cmake/data/target.entitlements.in ================================================ @entitlements_content@ ================================================ FILE: cmake/tools/BinaryDataBuilder/CMakeLists.txt ================================================ # Copyright (C) 2016-2020 Alain Martin # # This file is part of FRUT. # # FRUT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # FRUT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FRUT. If not, see . add_executable(BinaryDataBuilder "${CMAKE_CURRENT_LIST_DIR}/main.cpp" "${CMAKE_CURRENT_LIST_DIR}/extras/Projucer/Source/Project Saving/jucer_ResourceFile.cpp" "${CMAKE_CURRENT_LIST_DIR}/extras/Projucer/Source/Utility/jucer_CodeHelpers.cpp" "${CMAKE_CURRENT_LIST_DIR}/extras/Projucer/Source/Utility/jucer_FileHelpers.cpp" "${CMAKE_CURRENT_LIST_DIR}/extras/Projucer/Source/Utility/jucer_MiscUtilities.cpp" "${CMAKE_CURRENT_LIST_DIR}/modules/juce_gui_extra/juce_gui_extra.cpp" ) set_target_properties(BinaryDataBuilder PROPERTIES OUTPUT_NAME BinaryDataBuilder-0.3.1) target_link_libraries(BinaryDataBuilder PRIVATE tools_juce_core) if(built_by_Reprojucer) install(TARGETS BinaryDataBuilder DESTINATION ".") else() install(TARGETS BinaryDataBuilder DESTINATION "FRUT/cmake/bin") endif() ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Project/jucer_Project.h ================================================ // Copyright (C) 2016-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once class Project { public: Project(const String& outputDir, const String& uid) : binaryDataFilesOuputDir{File::getCurrentWorkingDirectory().getChildFile(outputDir)} , projectUID{uid} { } const String& getProjectUID() const { return projectUID; } File getBinaryDataCppFile(int index) const { if (index > 0) { return binaryDataFilesOuputDir.getChildFile("BinaryData" + String{index + 1} + ".cpp"); } return binaryDataFilesOuputDir.getChildFile("BinaryData.cpp"); } File getBinaryDataHeaderFile() const { return binaryDataFilesOuputDir.getChildFile("BinaryData.h"); } private: const File binaryDataFilesOuputDir; const String projectUID; }; ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Project Saving/jucer_ResourceFile.cpp ================================================ // Copyright (C) 2017-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 30-97, 100-110, 114-128, 132-151, 154-161, 165-173, 177-244, 247-252, 255-271, and 275-289 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Project%20Saving/jucer_ResourceFile.cpp // Lines 292-316, 320-326, 330-344, and 348-365 of this file were copied from // https://github.com/juce-framework/JUCE/blob/5.0.0/extras/Projucer/Source/Project%20Saving/jucer_ResourceFile.cpp // Lines 368-392, 396-402, 406-420, 424-448, 452-458, 462-470, and 474-559 of this file were copied from // https://github.com/juce-framework/JUCE/blob/5.3.2/extras/Projucer/Source/ProjectSaving/jucer_ResourceFile.cpp /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #include "../jucer_Headers.h" #include "jucer_ResourceFile.h" static const char* resourceFileIdentifierString = "JUCER_BINARY_RESOURCE"; //============================================================================== ResourceFile::ResourceFile (Project& p) : project (p), className ("BinaryData") { } //============================================================================== void ResourceFile::setClassName (const String& name) { className = name; } void ResourceFile::addFile (const File& file) { files.add (file); const String variableNameRoot (CodeHelpers::makeBinaryDataIdentifierName (file)); String variableName (variableNameRoot); int suffix = 2; while (variableNames.contains (variableName)) variableName = variableNameRoot + String (suffix++); variableNames.add (variableName); } static String getComment() { String comment; comment << newLine << newLine << " This is an auto-generated file: Any edits you make may be overwritten!" << newLine << newLine << "*/" << newLine << newLine; return comment; } template Result ResourceFile::writeHeader (MemoryOutputStream& header) { const String headerGuard ("BINARYDATA_H_" + String (project.getProjectUID().hashCode() & 0x7ffffff) + "_INCLUDED"); header << "/* =========================================================================================" << getComment() << "#ifndef " << headerGuard << newLine << "#define " << headerGuard << newLine << newLine << "namespace " << className << newLine << "{" << newLine; // bool containsAnyImages = false; for (int i = 0; i < files.size(); ++i) { const File& file = files.getReference(i); if (! file.existsAsFile()) return Result::fail ("Can't open resource file: " + file.getFullPathName()); const int64 dataSize = file.getSize(); const String variableName (variableNames[i]); FileInputStream fileStream (file); if (fileStream.openedOk()) { // containsAnyImages = containsAnyImages // || (ImageFileFormat::findImageFormatForStream (fileStream) != nullptr); header << " extern const char* " << variableName << ";" << newLine; header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine; } } header << " // Points to the start of a list of resource names." << newLine << " extern const char* namedResourceList[];" << newLine << newLine << " // Number of elements in the namedResourceList array." << newLine << " const int namedResourceListSize = " << files.size() << ";" << 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) throw();" << newLine << "}" << newLine << newLine << "#endif" << newLine; return Result::ok(); } template Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize) { const bool isFirstFile = (i == 0); cpp << "/* ==================================== " << resourceFileIdentifierString << " ====================================" << getComment() << "namespace " << className << newLine << "{" << newLine; // bool containsAnyImages = false; while (i < files.size()) { const File& file = files.getReference(i); const String variableName (variableNames[i]); FileInputStream fileStream (file); if (fileStream.openedOk()) { // containsAnyImages = containsAnyImages // || (ImageFileFormat::findImageFormatForStream (fileStream) != nullptr); const String 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*, int&) throw();" << newLine << "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw()" << newLine << "{" << newLine; StringArray returnCodes; for (int j = 0; j < files.size(); ++j) { const File& file = files.getReference(j); const int64 dataSize = file.getSize(); returnCodes.add ("numBytes = " + String (dataSize) + "; return " + variableNames[j] + ";"); } CodeHelpers::createStringMatcher (cpp, "resourceNameUTF8", variableNames, returnCodes, 4); cpp << " numBytes = 0;" << newLine << " return 0;" << newLine << "}" << newLine << newLine << "const char* namedResourceList[] =" << newLine << "{" << newLine; for (int j = 0; j < files.size(); ++j) cpp << " " << variableNames[j].quoted() << (j < files.size() - 1 ? "," : "") << newLine; cpp << "};" << newLine; } cpp << newLine << "}" << newLine; return Result::ok(); } template Result ResourceFile::write (Array& filesCreated, const int maxFileSize) { const File headerFile (project.getBinaryDataHeaderFile()); { MemoryOutputStream mo; Result 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 (;;) { File cpp (project.getBinaryDataCppFile (fileIndex)); MemoryOutputStream mo; Result 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(); } /* ============================================================================== 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. By using JUCE, you agree to the terms of both the JUCE 5 End-User License Agreement and JUCE 5 Privacy Policy (both updated and effective as of the 27th April 2017). End User License Agreement: www.juce.com/juce-5-licence Privacy Policy: www.juce.com/juce-5-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ template <> Result ResourceFile::writeHeader (MemoryOutputStream& header) { header << "/* =========================================================================================" << getComment() << "#pragma once" << newLine << newLine << "namespace " << className << newLine << "{" << newLine; // bool containsAnyImages = false; for (int i = 0; i < files.size(); ++i) { const File& file = files.getReference(i); if (! file.existsAsFile()) return Result::fail ("Can't open resource file: " + file.getFullPathName()); const int64 dataSize = file.getSize(); const String variableName (variableNames[i]); FileInputStream fileStream (file); if (fileStream.openedOk()) { // containsAnyImages = containsAnyImages // || (ImageFileFormat::findImageFormatForStream (fileStream) != nullptr); header << " extern const char* " << variableName << ";" << newLine; header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine; } } header << " // Points to the start of a list of resource names." << newLine << " extern const char* namedResourceList[];" << newLine << newLine << " // Number of elements in the namedResourceList array." << newLine << " const int namedResourceListSize = " << files.size() << ";" << 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) throw();" << newLine << "}" << newLine; return Result::ok(); } /* ============================================================================== 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. By using JUCE, you agree to the terms of both the JUCE 5 End-User License Agreement and JUCE 5 Privacy Policy (both updated and effective as of the 27th April 2017). End User License Agreement: www.juce.com/juce-5-licence Privacy Policy: www.juce.com/juce-5-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ template <> Result ResourceFile::writeHeader (MemoryOutputStream& header) { header << "/* =========================================================================================" << getComment() << "#pragma once" << newLine << newLine << "namespace " << className << newLine << "{" << newLine; // bool containsAnyImages = false; 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()) { // containsAnyImages = containsAnyImages // || (ImageFileFormat::findImageFormatForStream (fileStream) != nullptr); 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(); } template <> Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize) { bool isFirstFile = (i == 0); cpp << "/* ==================================== " << resourceFileIdentifierString << " ====================================" << getComment() << "namespace " << className << newLine << "{" << newLine; // bool containsAnyImages = false; while (i < files.size()) { auto& file = files.getReference(i); auto variableName = variableNames[i]; FileInputStream fileStream (file); if (fileStream.openedOk()) { // containsAnyImages = containsAnyImages // || (ImageFileFormat::findImageFormatForStream (fileStream) != nullptr); 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(); } template Result ResourceFile::write(Array&, const int); template Result ResourceFile::write(Array&, const int); template Result ResourceFile::write(Array&, const int); ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Project Saving/jucer_ResourceFile.h ================================================ // Copyright (C) 2017-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-51, 62-72, 75-82, 85, and 87-91 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Project%20Saving/jucer_ResourceFile.h /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #ifndef JUCER_RESOURCEFILE_H_INCLUDED #define JUCER_RESOURCEFILE_H_INCLUDED #include "../Project/jucer_Project.h" enum class ProjucerVersion { v4_2_0, v5_0_0, v5_3_1, }; //============================================================================== class ResourceFile { public: //============================================================================== ResourceFile (Project& project); //============================================================================== void setClassName (const String& className); void addFile (const File& file); template Result write (Array& filesCreated, int maxFileSize); //============================================================================== private: Array files; StringArray variableNames; Project& project; String className; template Result writeHeader (MemoryOutputStream&); template Result writeCpp (MemoryOutputStream&, const File& headerFile, int& index, int maxFileSize); }; #endif // JUCER_RESOURCEFILE_H_INCLUDED ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_CodeHelpers.cpp ================================================ // Copyright (C) 2017-2018 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-243 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_CodeHelpers.cpp /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #include "../jucer_Headers.h" #include "jucer_CodeHelpers.h" //============================================================================== namespace CodeHelpers { String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates) { 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 += ":"; StringArray words; words.addTokens (s.retainCharacters (allowedChars), false); words.trim(); String 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 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; const unsigned char* 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) { const unsigned int 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) { const int 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) { const char* 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;) { const unsigned int 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()); const String indent (String::repeatedString (" ", indentLevel)); const unsigned int hashMultiplier = findBestHashMultiplier (strings); out << indent << "unsigned int hash = 0;" << newLine << indent << "if (" << utf8PointerVariable << " != 0)" << 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; } } ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_CodeHelpers.h ================================================ // Copyright (C) 2017-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-66 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_CodeHelpers.h /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #ifndef JUCER_CODEHELPERS_H_INCLUDED #define JUCER_CODEHELPERS_H_INCLUDED //============================================================================== namespace CodeHelpers { String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates); String makeBinaryDataIdentifierName (const File& file); void writeDataAsCppLiteral (const MemoryBlock& data, OutputStream& out, bool breakAtNewLines, bool allowStringBreaks); void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, const StringArray& strings, const StringArray& codeToExecute, const int indentLevel); } #endif // JUCER_CODEHELPERS_H_INCLUDED ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_FileHelpers.cpp ================================================ // Copyright (C) 2017-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-87 and 89-108 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_FileHelpers.cpp /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #include "../jucer_Headers.h" //============================================================================== namespace FileHelpers { static int64 calculateMemoryHashCode (const void* data, const size_t numBytes) { int64 t = 0; for (size_t i = 0; i < numBytes; ++i) t = t * 65599 + static_cast (data)[i]; return t; } int64 calculateStreamHashCode (InputStream& in) { int64 t = 0; const int bufferSize = 4096; HeapBlock buffer; buffer.malloc (bufferSize); for (;;) { const int num = in.read (buffer, bufferSize); if (num <= 0) break; for (int i = 0; i < num; ++i) t = t * 65599 + buffer[i]; } return t; } int64 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()); } } ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_FileHelpers.h ================================================ // Copyright (C) 2017-2018 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-63 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_FileHelpers.h /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #ifndef JUCER_FILEHELPERS_H_INCLUDED #define JUCER_FILEHELPERS_H_INCLUDED //============================================================================== namespace FileHelpers { int64 calculateStreamHashCode (InputStream& stream); int64 calculateFileHashCode (const File& file); bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes); bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData); } #endif // JUCER_FILEHELPERS_H_INCLUDED ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_MiscUtilities.cpp ================================================ // Copyright (C) 2017-2018 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-54 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_MiscUtilities.cpp /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #include "../jucer_Headers.h" //============================================================================== String hexString8Digits (int value) { return String::toHexString (value).paddedLeft ('0', 8); } ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/Utility/jucer_MiscUtilities.h ================================================ // Copyright (C) 2017-2018 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . // clang-format off // Lines 24-55 of this file were copied from // https://github.com/juce-framework/JUCE/blob/4.2.0/extras/Projucer/Source/Utility/jucer_MiscUtilities.h /* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #ifndef JUCER_MISCUTILITIES_H_INCLUDED #define JUCER_MISCUTILITIES_H_INCLUDED String hexString8Digits (int value); #endif // JUCER_MISCUTILITIES_H_INCLUDED ================================================ FILE: cmake/tools/BinaryDataBuilder/extras/Projucer/Source/jucer_Headers.h ================================================ // Copyright (C) 2017-2019 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #pragma once #include "../../../modules/juce_gui_extra/juce_gui_extra.h" #include using namespace juce; #include "Utility/jucer_CodeHelpers.h" #include "Utility/jucer_FileHelpers.h" #include "Utility/jucer_MiscUtilities.h" ================================================ FILE: cmake/tools/BinaryDataBuilder/main.cpp ================================================ // Copyright (C) 2016-2020 Alain Martin // // This file is part of FRUT. // // FRUT is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // FRUT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with FRUT. If not, see . #include "extras/Projucer/Source/jucer_Headers.h" #include "extras/Projucer/Source/Project Saving/jucer_ResourceFile.h" #include #include #include #include #include #include int main(int argc, char* argv[]) { if (argc < 5) { std::cerr << "usage: BinaryDataBuilder" << " " << " " << " " << " " << " " << " ..." << std::endl; return 1; } const std::vector args{argv, argv + argc}; using Version = std::tuple; const auto jucerVersion = [&args]() { if (args.at(1) == "latest") { return Version{5, 3, 1}; } const auto versionTokens = StringArray::fromTokens(String{args.at(1)}, ".", {}); if (versionTokens.size() != 3) { std::cerr << "Invalid Projucer version" << std::endl; std::exit(1); } try { return Version{std::stoi(versionTokens[0].toStdString()), std::stoi(versionTokens[1].toStdString()), std::stoi(versionTokens[2].toStdString())}; } catch (const std::invalid_argument&) { std::cerr << "Invalid Projucer version" << std::endl; std::exit(1); } }(); Project project{args.at(2), args.at(3)}; const auto maxSize = [&args]() { try { return std::stoi(args.at(4)); } catch (const std::invalid_argument&) { std::cerr << "Invalid size limit" << std::endl; std::exit(1); } }(); ResourceFile resourceFile{project}; resourceFile.setClassName(args.at(5)); for (auto i = 6u; i < args.size(); ++i) { resourceFile.addFile(File{args.at(i)}); } Array binaryDataFiles; const auto result = jucerVersion < Version{5, 0, 0} ? resourceFile.write(binaryDataFiles, maxSize) : jucerVersion < Version{5, 3, 1} ? resourceFile.write
-G Xcode -DCMAKE_SYSTEM_NAME=iOS