migrating to the latest JUCE version

This commit is contained in:
2022-11-04 23:11:33 +01:00
committed by Nikolai Rodionov
parent 4257a0f8ba
commit faf8f18333
2796 changed files with 888518 additions and 784244 deletions

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see
@ -29,7 +29,19 @@ function(_juce_create_atomic_target target_name)
return()
endif()
set(test_file_contents
set(test_atomic_with_is_lock_free_file_contents
[[
#include <atomic>
int main (int argc, char** argv)
{
std::atomic<long long> ll { static_cast<long long> (argc) };
ll ^= static_cast<long long> (ll.is_lock_free());
return static_cast<int> (ll);
}
]])
set(test_simple_atomic_file_contents
[[
#include <atomic>
@ -47,7 +59,7 @@ function(_juce_create_atomic_target target_name)
string(RANDOM LENGTH 16 random_dir_string)
set(test_bindir "${CMAKE_CURRENT_BINARY_DIR}/check_atomic_dir_${random_dir_string}")
file(WRITE "${test_file_name}" "${test_file_contents}")
file(WRITE "${test_file_name}" "${test_atomic_with_is_lock_free_file_contents}")
try_compile(compile_result "${test_bindir}" "${test_file_name}"
OUTPUT_VARIABLE test_build_output_0
@ -64,15 +76,37 @@ function(_juce_create_atomic_target target_name)
CXX_EXTENSIONS FALSE)
if (NOT compile_result)
message(FATAL_ERROR
"First build output:\n"
"${test_build_output_0}"
"\n\nSecond build output:\n"
"${test_build_output_1}"
"\n\nJUCE requires support for std::atomic, but this system cannot "
"successfully compile a program which uses std::atomic. "
"You may need to install a dedicated libatomic package using your "
"system's package manager.")
file(WRITE "${test_file_name}" "${test_simple_atomic_file_contents}")
try_compile(compile_result "${test_bindir}" "${test_file_name}"
OUTPUT_VARIABLE test_build_output_2
LINK_LIBRARIES atomic
CXX_STANDARD 14
CXX_STANDARD_REQUIRED TRUE
CXX_EXTENSIONS FALSE)
if (NOT compile_result)
message(FATAL_ERROR
"First build output:\n"
"${test_build_output_0}"
"\n\nSecond build output:\n"
"${test_build_output_1}"
"\n\nThird build output:\n"
"${test_build_output_2}"
"\n\nJUCE requires support for std::atomic, but this system cannot "
"successfully compile a program which uses std::atomic. "
"You may need to install a dedicated libatomic package using your "
"system's package manager.")
else()
message(WARNING
"First build output:\n"
"${test_build_output_0}"
"\n\nSecond build output:\n"
"${test_build_output_1}"
"\n\nIf you are seeing this warning it means that the libatomic library"
"on this system doesn't support is_lock_free."
"Please let the JUCE team know.")
endif()
endif()
target_link_libraries("${target_name}" INTERFACE atomic)

View File

@ -20,6 +20,8 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/LV2_HELPER.cmake")
if(NOT TARGET juce::juceaide)
add_executable(juce::juceaide IMPORTED)
set_target_properties(juce::juceaide PROPERTIES

View File

@ -1,3 +1,26 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-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.
#
# ==============================================================================
add_library(juce_recommended_warning_flags INTERFACE)
add_library(juce::juce_recommended_warning_flags ALIAS juce_recommended_warning_flags)
@ -9,19 +32,21 @@ elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQU
-Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare
-Wint-conversion -Wconditional-uninitialized -Wconstant-conversion
-Wsign-conversion -Wbool-conversion -Wextra-semi -Wunreachable-code
-Wcast-align -Wshift-sign-overflow -Wno-missing-field-initializers
-Wcast-align -Wshift-sign-overflow -Wmissing-prototypes
-Wnullable-to-nonnull-conversion -Wno-ignored-qualifiers -Wswitch-enum
-Wpedantic
-Wpedantic -Wdeprecated
$<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:OBJCXX>>:
-Wzero-as-null-pointer-constant -Wunused-private-field
-Woverloaded-virtual -Wreorder
-Winconsistent-missing-destructor-override>)
-Winconsistent-missing-destructor-override>
$<$<OR:$<COMPILE_LANGUAGE:OBJC>,$<COMPILE_LANGUAGE:OBJCXX>>:
-Wunguarded-availability -Wunguarded-availability-new>)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(juce_recommended_warning_flags INTERFACE
-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wuninitialized
-Wunused-parameter -Wsign-compare -Wsign-conversion -Wunreachable-code
-Wcast-align -Wno-implicit-fallthrough -Wno-maybe-uninitialized
-Wno-missing-field-initializers -Wno-ignored-qualifiers -Wswitch-enum
-Wno-ignored-qualifiers -Wswitch-enum
-Wredundant-decls -Wno-strict-overflow -Wshadow
$<$<COMPILE_LANGUAGE:CXX>:
-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant>)
@ -53,9 +78,9 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") OR (CMAKE_CXX_COMPILER_FRONTEND_VARIA
$<$<CONFIG:Release>:$<IF:$<STREQUAL:"${CMAKE_CXX_COMPILER_ID}","MSVC">,-GL,-flto>>)
target_link_libraries(juce_recommended_lto_flags INTERFACE
$<$<CONFIG:Release>:$<$<STREQUAL:"${CMAKE_CXX_COMPILER_ID}","MSVC">:-LTCG>>)
elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
elseif((NOT MINGW) AND ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")))
target_compile_options(juce_recommended_lto_flags INTERFACE $<$<CONFIG:Release>:-flto>)
target_link_libraries(juce_recommended_lto_flags INTERFACE $<$<CONFIG:Release>:-flto>)
endif()

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see
@ -83,8 +83,10 @@ endfunction()
macro(_juce_make_absolute path)
if(NOT IS_ABSOLUTE "${${path}}")
get_filename_component("${path}" "${${path}}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
get_filename_component(${path} "${${path}}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
endif()
string(REGEX REPLACE "\\\\" "/" ${path} "${${path}}")
endmacro()
macro(_juce_make_absolute_and_check path)
@ -120,23 +122,23 @@ function(_juce_extract_metadata_block delim_str file_with_block out_dict)
foreach(line IN LISTS module_header_contents)
if(NOT append)
if(line MATCHES " *BEGIN_${delim_str} *")
if(line MATCHES "[\t ]*BEGIN_${delim_str}[\t ]*")
set(append YES)
endif()
continue()
endif()
if(append AND (line MATCHES " *END_${delim_str} *"))
if(append AND (line MATCHES "[\t ]*END_${delim_str}[\t ]*"))
break()
endif()
if(line MATCHES "^ *([a-zA-Z]+):")
if(line MATCHES "^[\t ]*([a-zA-Z]+):")
set(last_written_key "${CMAKE_MATCH_1}")
endif()
string(REGEX REPLACE "^ *${last_written_key}: *" "" line "${line}")
string(REGEX REPLACE "[ ,]+" ";" line "${line}")
string(REGEX REPLACE "^[\t ]*${last_written_key}:[\t ]*" "" line "${line}")
string(REGEX REPLACE "[\t ,]+" ";" line "${line}")
set_property(TARGET ${target_name} APPEND PROPERTY
"INTERFACE_JUCE_${last_written_key}" "${line}")
@ -234,7 +236,7 @@ endfunction()
# ==================================================================================================
function(_juce_get_all_plugin_kinds out)
set(${out} AU AUv3 AAX Standalone Unity VST VST3 PARENT_SCOPE)
set(${out} AU AUv3 AAX LV2 Standalone Unity VST VST3 PARENT_SCOPE)
endfunction()
function(_juce_get_platform_plugin_kinds out)
@ -249,7 +251,11 @@ function(_juce_get_platform_plugin_kinds out)
endif()
if(NOT CMAKE_SYSTEM_NAME STREQUAL "iOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
list(APPEND result AAX Unity VST VST3)
list(APPEND result Unity VST VST3 LV2)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR CMAKE_SYSTEM_NAME STREQUAL "Windows")
list(APPEND result AAX)
endif()
set(${out} ${result} PARENT_SCOPE)
@ -272,22 +278,29 @@ endfunction()
# ==================================================================================================
# Takes a target, a link visibility, and a variable-length list of framework
# names. On macOS, finds the requested frameworks using `find_library` and
# links them. On iOS, links directly with `-framework Name`.
# Takes a target, a link visibility, if it should be a weak link, and a variable-length list of
# framework names. On macOS, for non-weak links, this finds the requested frameworks using
# `find_library`.
function(_juce_link_frameworks target visibility)
foreach(framework IN LISTS ARGN)
set(options WEAK)
cmake_parse_arguments(JUCE_LINK_FRAMEWORKS "${options}" "" "" ${ARGN})
foreach(framework IN LISTS JUCE_LINK_FRAMEWORKS_UNPARSED_ARGUMENTS)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
find_library("juce_found_${framework}" "${framework}" REQUIRED)
target_link_libraries("${target}" "${visibility}" "${juce_found_${framework}}")
if(JUCE_LINK_FRAMEWORKS_WEAK)
set(framework_flags "-weak_framework ${framework}")
else()
find_library("juce_found_${framework}" "${framework}" REQUIRED)
set(framework_flags "${juce_found_${framework}}")
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
# CoreServices is only available on iOS 12+, we must link it weakly on earlier platforms
if((framework STREQUAL "CoreServices") AND (CMAKE_OSX_DEPLOYMENT_TARGET LESS 12.0))
if(JUCE_LINK_FRAMEWORKS_WEAK OR ((framework STREQUAL "CoreServices") AND (CMAKE_OSX_DEPLOYMENT_TARGET LESS 12.0)))
set(framework_flags "-weak_framework ${framework}")
else()
set(framework_flags "-framework ${framework}")
endif()
endif()
if(NOT framework_flags STREQUAL "")
target_link_libraries("${target}" "${visibility}" "${framework_flags}")
endif()
endforeach()
@ -398,6 +411,11 @@ endfunction()
# ==================================================================================================
function(_juce_remove_empty_list_elements arg)
list(FILTER ${arg} EXCLUDE REGEX "^$")
set(${arg} ${${arg}} PARENT_SCOPE)
endfunction()
function(juce_add_module module_path)
set(one_value_args INSTALL_PATH ALIAS_NAMESPACE)
cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "" ${ARGN})
@ -484,8 +502,30 @@ function(juce_add_module module_path)
target_link_libraries(juce_audio_processors INTERFACE juce_vst3_headers)
add_library(juce_lilv_headers INTERFACE)
set(lv2_base_path "${base_path}/juce_audio_processors/format_types/LV2_SDK")
target_include_directories(juce_lilv_headers INTERFACE
"${lv2_base_path}"
"${lv2_base_path}/lv2"
"${lv2_base_path}/serd"
"${lv2_base_path}/sord"
"${lv2_base_path}/sord/src"
"${lv2_base_path}/sratom"
"${lv2_base_path}/lilv"
"${lv2_base_path}/lilv/src")
target_link_libraries(juce_audio_processors INTERFACE juce_lilv_headers)
add_library(juce_ara_headers INTERFACE)
target_include_directories(juce_ara_headers INTERFACE
"$<$<TARGET_EXISTS:juce_ara_sdk>:$<TARGET_PROPERTY:juce_ara_sdk,INTERFACE_INCLUDE_DIRECTORIES>>")
target_link_libraries(juce_audio_processors INTERFACE juce_ara_headers)
if(JUCE_ARG_ALIAS_NAMESPACE)
add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_vst3_headers ALIAS juce_vst3_headers)
add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_lilv_headers ALIAS juce_lilv_headers)
add_library(${JUCE_ARG_ALIAS_NAMESPACE}::juce_ara_headers ALIAS juce_ara_headers)
endif()
endif()
@ -497,6 +537,25 @@ function(juce_add_module module_path)
target_compile_definitions(${module_name} INTERFACE LINUX=1)
endif()
if((${module_name} STREQUAL "juce_audio_devices") AND (CMAKE_SYSTEM_NAME STREQUAL "Android"))
add_subdirectory("${module_path}/native/oboe")
target_link_libraries(${module_name} INTERFACE oboe)
endif()
if((${module_name} STREQUAL "juce_opengl") AND (CMAKE_SYSTEM_NAME STREQUAL "Android"))
set(platform_supports_gl3 0)
if(CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 18)
set(platform_supports_gl3 1)
endif()
if(platform_supports_gl3)
target_compile_definitions(${module_name} INTERFACE JUCE_ANDROID_GL_ES_VERSION_3_0=1)
endif()
target_link_libraries(${module_name} INTERFACE EGL $<IF:${platform_supports_gl3},GLESv3,GLESv2>)
endif()
_juce_extract_metadata_block(JUCE_MODULE_DECLARATION "${module_path}/${module_header_name}" metadata_dict)
_juce_get_metadata("${metadata_dict}" minimumCppStandard module_cpp_standard)
@ -510,26 +569,34 @@ function(juce_add_module module_path)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
_juce_get_metadata("${metadata_dict}" OSXFrameworks module_osxframeworks)
_juce_remove_empty_list_elements(module_osxframeworks)
foreach(module_framework IN LISTS module_osxframeworks)
if(module_framework STREQUAL "")
continue()
endif()
_juce_link_frameworks("${module_name}" INTERFACE "${module_framework}")
endforeach()
_juce_get_metadata("${metadata_dict}" WeakOSXFrameworks module_weakosxframeworks)
_juce_remove_empty_list_elements(module_weakosxframeworks)
foreach(module_framework IN LISTS module_weakosxframeworks)
_juce_link_frameworks("${module_name}" INTERFACE WEAK "${module_framework}")
endforeach()
_juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" OSXLibs)
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
_juce_get_metadata("${metadata_dict}" iOSFrameworks module_iosframeworks)
_juce_remove_empty_list_elements(module_iosframeworks)
foreach(module_framework IN LISTS module_iosframeworks)
if(module_framework STREQUAL "")
continue()
endif()
_juce_link_frameworks("${module_name}" INTERFACE "${module_framework}")
endforeach()
_juce_get_metadata("${metadata_dict}" WeakiOSFrameworks module_weakiosframeworks)
_juce_remove_empty_list_elements(module_weakiosframeworks)
foreach(module_framework IN LISTS module_weakiosframeworks)
_juce_link_frameworks("${module_name}" INTERFACE WEAK "${module_framework}")
endforeach()
_juce_link_libs_from_metadata("${module_name}" "${metadata_dict}" iOSLibs)
elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
_juce_get_metadata("${metadata_dict}" linuxPackages module_linuxpackages)
@ -590,3 +657,18 @@ function(juce_add_modules)
endforeach()
endfunction()
# When source groups are enabled, this function sets the HEADER_FILE_ONLY property on any module
# source files that should not be built. This is called automatically by the juce_add_* functions.
function(_juce_fixup_module_source_groups)
if(JUCE_ENABLE_MODULE_SOURCE_GROUPS)
get_property(all_modules GLOBAL PROPERTY _juce_module_names)
foreach(module_name IN LISTS all_modules)
get_target_property(path ${module_name} INTERFACE_JUCE_MODULE_PATH)
get_target_property(header_files ${module_name} INTERFACE_JUCE_MODULE_HEADERS)
get_target_property(source_files ${module_name} INTERFACE_JUCE_MODULE_SOURCES)
source_group(TREE ${path} PREFIX "JUCE Modules" FILES ${header_files} ${source_files})
set_source_files_properties(${header_files} PROPERTIES HEADER_FILE_ONLY TRUE)
endforeach()
endif()
endfunction()

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see
@ -75,6 +75,10 @@ define_property(TARGET PROPERTY JUCE_UNITY_COPY_DIR INHERITED
BRIEF_DOCS "Install location for Unity plugins"
FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
define_property(TARGET PROPERTY JUCE_LV2_COPY_DIR INHERITED
BRIEF_DOCS "Install location for LV2 plugins"
FULL_DOCS "This is where the plugin will be copied if plugin copying is enabled")
define_property(TARGET PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD INHERITED
BRIEF_DOCS "Whether or not plugins should be copied after building"
FULL_DOCS "Whether or not plugins should be copied after building")
@ -97,10 +101,12 @@ endif()
function(_juce_set_default_properties)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST")
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3")
set_property(GLOBAL PROPERTY JUCE_AU_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components")
set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "/Library/Application Support/Avid/Audio/Plug-Ins")
set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/LV2")
set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST")
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3")
set_property(GLOBAL PROPERTY JUCE_AU_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components")
set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Unity")
set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "/Library/Application Support/Avid/Audio/Plug-Ins")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{ProgramW6432}/Steinberg/Vstplugins")
@ -110,11 +116,15 @@ function(_juce_set_default_properties)
set(prefix "$ENV{CommonProgramFiles\(x86\)}")
endif()
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "${prefix}/VST3")
set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "${prefix}/Avid/Audio/Plug-Ins")
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "${prefix}/VST3")
set_property(GLOBAL PROPERTY JUCE_AAX_COPY_DIR "${prefix}/Avid/Audio/Plug-Ins")
set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{APPDATA}/LV2")
set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{APPDATA}/Unity")
elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/.vst")
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/.vst3")
set_property(GLOBAL PROPERTY JUCE_LV2_COPY_DIR "$ENV{HOME}/.lv2")
set_property(GLOBAL PROPERTY JUCE_VST_COPY_DIR "$ENV{HOME}/.vst")
set_property(GLOBAL PROPERTY JUCE_VST3_COPY_DIR "$ENV{HOME}/.vst3")
set_property(GLOBAL PROPERTY JUCE_UNITY_COPY_DIR "$ENV{HOME}/.unity")
endif()
endfunction()
@ -312,12 +322,17 @@ function(_juce_write_configure_time_info target)
_juce_append_target_property(file_content PLUGIN_AU_MAIN_TYPE ${target} JUCE_AU_MAIN_TYPE_CODE)
_juce_append_target_property(file_content IS_AU_SANDBOX_SAFE ${target} JUCE_AU_SANDBOX_SAFE)
_juce_append_target_property(file_content IS_PLUGIN_SYNTH ${target} JUCE_IS_SYNTH)
_juce_append_target_property(file_content IS_PLUGIN_ARA_EFFECT ${target} JUCE_IS_ARA_EFFECT)
_juce_append_target_property(file_content SUPPRESS_AU_PLIST_RESOURCE_USAGE ${target} JUCE_SUPPRESS_AU_PLIST_RESOURCE_USAGE)
_juce_append_target_property(file_content HARDENED_RUNTIME_ENABLED ${target} JUCE_HARDENED_RUNTIME_ENABLED)
_juce_append_target_property(file_content APP_SANDBOX_ENABLED ${target} JUCE_APP_SANDBOX_ENABLED)
_juce_append_target_property(file_content APP_SANDBOX_INHERIT ${target} JUCE_APP_SANDBOX_INHERIT)
_juce_append_target_property(file_content HARDENED_RUNTIME_OPTIONS ${target} JUCE_HARDENED_RUNTIME_OPTIONS)
_juce_append_target_property(file_content APP_SANDBOX_OPTIONS ${target} JUCE_APP_SANDBOX_OPTIONS)
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RO)
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RW)
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RO)
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RW)
_juce_append_target_property(file_content APP_GROUPS_ENABLED ${target} JUCE_APP_GROUPS_ENABLED)
_juce_append_target_property(file_content APP_GROUP_IDS ${target} JUCE_APP_GROUP_IDS)
_juce_append_target_property(file_content IS_PLUGIN ${target} JUCE_IS_PLUGIN)
@ -451,7 +466,7 @@ function(_juce_to_char_literal str out_var help_text)
string(LENGTH "${str}" string_length)
if(NOT "${string_length}" EQUAL "4")
message(FATAL_ERROR "The ${help_text} code must contain exactly four characters, but it was set to '${str}'")
message(WARNING "The ${help_text} code must contain exactly four characters, but it was set to '${str}'")
endif()
# Round-tripping through a file is the simplest way to convert a string to hex...
@ -463,7 +478,8 @@ function(_juce_to_char_literal str out_var help_text)
file(READ "${scratch_file}" four_chars_hex HEX)
file(REMOVE "${scratch_file}")
set(${out_var} ${four_chars_hex} PARENT_SCOPE)
string(SUBSTRING "${four_chars_hex}00000000" 0 8 four_chars_hex)
set(${out_var} "${four_chars_hex}" PARENT_SCOPE)
endfunction()
# ==================================================================================================
@ -501,10 +517,13 @@ function(_juce_execute_juceaide)
message(FATAL_ERROR "juceaide was imported, but it doesn't exist!")
endif()
execute_process(COMMAND "${juceaide_location}" ${ARGN} RESULT_VARIABLE result_variable)
execute_process(COMMAND "${juceaide_location}" ${ARGN}
RESULT_VARIABLE result_variable
OUTPUT_VARIABLE output
ERROR_VARIABLE output)
if(result_variable)
message(FATAL_ERROR "Running juceaide failed")
message(FATAL_ERROR "Running juceaide failed:\n${output}")
endif()
endfunction()
@ -855,7 +874,15 @@ function(juce_enable_copy_plugin_step shared_code_target)
get_target_property(source "${target}" JUCE_PLUGIN_ARTEFACT_FILE)
if(source)
get_target_property(dest "${target}" JUCE_PLUGIN_COPY_DIR)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
add_custom_command(TARGET ${target} POST_BUILD
COMMAND "${CMAKE_COMMAND}"
"-Dsrc=${source}"
"-P" "${JUCE_CMAKE_UTILS_DIR}/checkBundleSigning.cmake"
VERBATIM)
endif()
get_target_property(dest "${target}" JUCE_PLUGIN_COPY_DIR)
if(dest)
_juce_copy_dir("${target}" "${source}" "$<GENEX_EVAL:${dest}>")
@ -979,6 +1006,29 @@ function(_juce_set_plugin_target_properties shared_code_target kind)
"${script_file}"
JUCE_UNITY_COPY_DIR)
endif()
elseif(kind STREQUAL "LV2")
set_target_properties(${target_name} PROPERTIES BUNDLE FALSE)
get_target_property(JUCE_LV2URI "${shared_code_target}" JUCE_LV2URI)
if(NOT JUCE_LV2URI MATCHES "https?://.*")
message(WARNING
"LV2URI should be well-formed with an 'http' prefix. "
"Check the LV2URI argument to juce_add_plugin.")
endif()
set(source_header "${JUCE_CMAKE_UTILS_DIR}/JuceLV2Defines.h.in")
get_target_property(juce_library_code "${shared_code_target}" JUCE_GENERATED_SOURCES_DIRECTORY)
configure_file("${source_header}" "${juce_library_code}/JuceLV2Defines.h")
set(output_path "${products_folder}/${product_name}.lv2")
set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_path}")
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND juce::juce_lv2_helper "$<TARGET_FILE:${target_name}>"
VERBATIM)
_juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_LV2_COPY_DIR)
endif()
endfunction()
@ -1004,6 +1054,8 @@ function(_juce_get_plugin_kind_name kind out_var)
set(${out_var} "AUv3 AppExtension" PARENT_SCOPE)
elseif(kind STREQUAL "AAX")
set(${out_var} "AAX" PARENT_SCOPE)
elseif(kind STREQUAL "LV2")
set(${out_var} "LV2" PARENT_SCOPE)
elseif(kind STREQUAL "Standalone")
set(${out_var} "Standalone Plugin" PARENT_SCOPE)
elseif(kind STREQUAL "Unity")
@ -1064,7 +1116,10 @@ function(_juce_link_plugin_wrapper shared_code_target kind)
add_dependencies(${shared_code_target}_All ${target_name})
_juce_configure_bundle(${shared_code_target} ${target_name})
if(NOT kind STREQUAL "LV2")
_juce_configure_bundle(${shared_code_target} ${target_name})
endif()
_juce_set_plugin_target_properties(${shared_code_target} ${kind})
endfunction()
@ -1183,7 +1238,13 @@ function(_juce_configure_plugin_targets target)
JucePlugin_AAXDisableBypass=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_BYPASS>>
JucePlugin_AAXDisableMultiMono=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_DISABLE_AAX_MULTI_MONO>>
JucePlugin_VSTNumMidiInputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_INS>
JucePlugin_VSTNumMidiOutputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_OUTS>)
JucePlugin_VSTNumMidiOutputs=$<TARGET_PROPERTY:${target},JUCE_VST_NUM_MIDI_OUTS>
JucePlugin_Enable_ARA=$<BOOL:$<TARGET_PROPERTY:${target},JUCE_IS_ARA_EFFECT>>
JucePlugin_ARAFactoryID=$<TARGET_PROPERTY:${target},JUCE_ARA_FACTORY_ID>
JucePlugin_ARADocumentArchiveID=$<TARGET_PROPERTY:${target},JUCE_ARA_DOCUMENT_ARCHIVE_ID>
JucePlugin_ARACompatibleArchiveIDs=$<TARGET_PROPERTY:${target},JUCE_ARA_COMPATIBLE_ARCHIVE_IDS>
JucePlugin_ARAContentTypes=$<TARGET_PROPERTY:${target},JUCE_ARA_ANALYSIS_TYPES>
JucePlugin_ARATransformationFlags=$<TARGET_PROPERTY:${target},JUCE_ARA_TRANSFORMATION_FLAGS>)
set_target_properties(${target} PROPERTIES
POSITION_INDEPENDENT_CODE TRUE
@ -1283,10 +1344,11 @@ function(_juce_set_fallback_properties target)
_juce_set_property_if_not_set(${target} BUILD_VERSION "${final_version}")
get_target_property(custom_xcassets ${target} JUCE_CUSTOM_XCASSETS_FOLDER)
get_target_property(custom_storyboard ${target} JUCE_LAUNCH_STORYBOARD_FILE)
set(needs_storyboard TRUE)
if(custom_xcassets)
if((NOT custom_storyboard) AND custom_xcassets AND (EXISTS "${custom_xcassets}/LaunchImage.launchimage"))
set(needs_storyboard FALSE)
endif()
@ -1458,6 +1520,90 @@ function(_juce_set_fallback_properties target)
if(NOT aax_category_int STREQUAL "")
set_target_properties(${target} PROPERTIES JUCE_AAX_CATEGORY ${aax_category_int})
endif()
# Ensure this matches the Projucer implementation
get_target_property(company_website ${target} JUCE_COMPANY_WEBSITE)
get_target_property(plugin_name ${target} JUCE_PLUGIN_NAME)
string(MAKE_C_IDENTIFIER "${plugin_name}" plugin_name_sanitised)
_juce_set_property_if_not_set(${target} LV2URI "${company_website}/plugins/${plugin_name_sanitised}")
# ARA configuration
# Analysis types
set(ara_analysis_type_strings
kARAContentTypeNotes
kARAContentTypeTempoEntries
kARAContentTypeBarSignatures
kARAContentTypeStaticTuning
kARAContentTypeKeySignatures
kARAContentTypeSheetChords)
get_target_property(actual_ara_analysis_types ${target} JUCE_ARA_ANALYSIS_TYPES)
set(ara_analysis_types_int "")
foreach(category_string IN LISTS actual_ara_analysis_types)
list(FIND ara_analysis_type_strings ${category_string} ara_index)
if(ara_index GREATER_EQUAL 0)
set(ara_analysis_types_bit "1 << ${ara_index}")
if(ara_analysis_types_int STREQUAL "")
set(ara_analysis_types_int 0)
endif()
math(EXPR ara_analysis_types_int "${ara_analysis_types_int} | (${ara_analysis_types_bit})")
endif()
endforeach()
if(NOT ara_analysis_types_int STREQUAL "")
set_target_properties(${target} PROPERTIES JUCE_ARA_ANALYSIS_TYPES ${ara_analysis_types_int})
endif()
_juce_set_property_if_not_set(${target} ARA_ANALYSIS_TYPES 0)
# Transformation flags
set(ara_transformation_flags_strings
kARAPlaybackTransformationNoChanges
kARAPlaybackTransformationTimestretch
kARAPlaybackTransformationTimestretchReflectingTempo
kARAPlaybackTransformationContentBasedFadeAtTail
kARAPlaybackTransformationContentBasedFadeAtHead)
set(default_ara_transformation_flags kARAPlaybackTransformationNoChanges)
_juce_set_property_if_not_set(${target} ARA_TRANSFORMATION_FLAGS ${default_ara_transformation_flags})
get_target_property(actual_ara_transformation_flags ${target} JUCE_ARA_TRANSFORMATION_FLAGS)
set(ara_transformation_flags_int "")
foreach(transformation_string IN LISTS actual_ara_transformation_flags)
list(FIND ara_transformation_flags_strings ${transformation_string} ara_transformation_index)
if(ara_transformation_index GREATER_EQUAL 0)
if(ara_transformation_index EQUAL 0)
set(ara_transformation_bit 0)
else()
set(ara_transformation_bit "1 << (${ara_transformation_index} - 1)")
endif()
if(ara_transformation_flags_int STREQUAL "")
set(ara_transformation_flags_int 0)
endif()
math(EXPR ara_transformation_flags_int "${ara_transformation_flags_int} | (${ara_transformation_bit})")
endif()
endforeach()
if(NOT ara_transformation_flags_int STREQUAL "")
set_target_properties(${target} PROPERTIES JUCE_ARA_TRANSFORMATION_FLAGS ${ara_transformation_flags_int})
endif()
_juce_set_property_if_not_set(${target} IS_ARA_EFFECT FALSE)
get_target_property(final_bundle_id ${target} JUCE_BUNDLE_ID)
_juce_set_property_if_not_set(${target} ARA_FACTORY_ID "\"${final_bundle_id}.arafactory.${final_version}\"")
_juce_set_property_if_not_set(${target} ARA_DOCUMENT_ARCHIVE_ID "\"${final_bundle_id}.aradocumentarchive.1\"")
_juce_set_property_if_not_set(${target} ARA_COMPATIBLE_ARCHIVE_IDS "\"\"")
endfunction()
# ==================================================================================================
@ -1524,6 +1670,10 @@ function(_juce_initialise_target target)
SUPPRESS_AU_PLIST_RESOURCE_USAGE
PLUGINHOST_AU # Set this true if you want to host AU plugins
USE_LEGACY_COMPATIBILITY_PLUGIN_CODE
LV2URI
IS_ARA_EFFECT
ARA_FACTORY_ID
ARA_DOCUMENT_ARCHIVE_ID
VST_COPY_DIR
VST3_COPY_DIR
@ -1537,11 +1687,18 @@ function(_juce_initialise_target target)
VST3_CATEGORIES
HARDENED_RUNTIME_OPTIONS
APP_SANDBOX_OPTIONS
APP_SANDBOX_FILE_ACCESS_HOME_RO
APP_SANDBOX_FILE_ACCESS_HOME_RW
APP_SANDBOX_FILE_ACCESS_ABS_RO
APP_SANDBOX_FILE_ACCESS_ABS_RW
DOCUMENT_EXTENSIONS
AAX_CATEGORY
IPHONE_SCREEN_ORIENTATIONS # iOS only
IPAD_SCREEN_ORIENTATIONS # iOS only
APP_GROUP_IDS) # iOS only
APP_GROUP_IDS # iOS only
ARA_COMPATIBLE_ARCHIVE_IDS
ARA_ANALYSIS_TYPES
ARA_TRANSFORMATION_FLAGS)
cmake_parse_arguments(JUCE_ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
@ -1611,18 +1768,7 @@ function(_juce_initialise_target target)
_juce_write_generate_time_info(${target})
_juce_link_optional_libraries(${target})
if(JUCE_ENABLE_MODULE_SOURCE_GROUPS)
get_property(all_modules GLOBAL PROPERTY _juce_module_names)
foreach(module_name IN LISTS all_modules)
get_target_property(path ${module_name} INTERFACE_JUCE_MODULE_PATH)
get_target_property(header_files ${module_name} INTERFACE_JUCE_MODULE_HEADERS)
get_target_property(source_files ${module_name} INTERFACE_JUCE_MODULE_SOURCES)
source_group(TREE ${path} PREFIX "JUCE Modules" FILES ${header_files} ${source_files})
set_source_files_properties(${header_files} PROPERTIES HEADER_FILE_ONLY TRUE)
endforeach()
endif()
_juce_fixup_module_source_groups()
endfunction()
# ==================================================================================================
@ -1746,27 +1892,49 @@ function(juce_add_pip header)
NEEDS_STORE_KIT TRUE)
endif()
if("JUCE_PLUGINHOST_AU=1" IN_LIST pip_moduleflags)
list(APPEND extra_target_args PLUGINHOST_AU TRUE)
endif()
if(pip_kind STREQUAL "AudioProcessor")
set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in")
_juce_get_metadata("${metadata_dict}" documentControllerClass JUCE_PIP_DOCUMENTCONTROLLER_CLASS)
# We add AAX/VST2 targets too, if the user has set up those SDKs
if(JUCE_PIP_DOCUMENTCONTROLLER_CLASS)
if(NOT TARGET juce_ara_sdk)
message(WARNING
"${header} specifies a documentControllerClass, but the ARA SDK could not be located. "
"Use juce_set_ara_sdk_path to specify the ARA SDK location. "
"This PIP will not be configured.")
endif()
set(extra_formats)
set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessorWithARA.cpp.in")
if(TARGET juce_aax_sdk)
list(APPEND extra_formats AAX)
juce_add_plugin(${JUCE_PIP_NAME}
FORMATS AU VST3
IS_ARA_EFFECT TRUE
${extra_target_args})
else()
set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPAudioProcessor.cpp.in")
# We add AAX/VST2 targets too, if the user has set up those SDKs
set(extra_formats)
if(TARGET juce_aax_sdk)
list(APPEND extra_formats AAX)
endif()
if(TARGET juce_vst2_sdk)
list(APPEND extra_formats VST)
endif()
# Standalone plugins might want to access the mic
list(APPEND extra_target_args MICROPHONE_PERMISSION_ENABLED TRUE)
juce_add_plugin(${JUCE_PIP_NAME}
FORMATS AU AUv3 LV2 Standalone Unity VST3 ${extra_formats}
${extra_target_args})
endif()
if(TARGET juce_vst2_sdk)
list(APPEND extra_formats VST)
endif()
# Standalone plugins might want to access the mic
list(APPEND extra_target_args MICROPHONE_PERMISSION_ENABLED TRUE)
juce_add_plugin(${JUCE_PIP_NAME}
FORMATS AU AUv3 VST3 Unity Standalone ${extra_formats}
${extra_target_args})
elseif(pip_kind STREQUAL "Component")
set(source_main "${JUCE_CMAKE_UTILS_DIR}/PIPComponent.cpp.in")
juce_add_gui_app(${JUCE_PIP_NAME} ${extra_target_args})
@ -1918,6 +2086,22 @@ function(juce_set_vst3_sdk_path path)
target_include_directories(juce_vst3_sdk INTERFACE "${path}")
endfunction()
function(juce_set_ara_sdk_path path)
if(TARGET juce_ara_sdk)
message(FATAL_ERROR "juce_set_ara_sdk_path should only be called once")
endif()
_juce_make_absolute(path)
if(NOT EXISTS "${path}")
message(FATAL_ERROR "Could not find ARA SDK at the specified path: ${path}")
endif()
add_library(juce_ara_sdk INTERFACE IMPORTED GLOBAL)
target_include_directories(juce_ara_sdk INTERFACE "${path}")
endfunction()
# ==================================================================================================
function(juce_disable_default_flags)

View File

@ -0,0 +1,5 @@
#pragma once
#ifndef JucePlugin_LV2URI
#define JucePlugin_LV2URI "${JUCE_LV2URI}"
#endif

View File

@ -0,0 +1,23 @@
/*
==============================================================================
This file was auto-generated and contains the startup code for a PIP.
==============================================================================
*/
#include <JuceHeader.h>
#include "${JUCE_PIP_HEADER}"
//==============================================================================
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new ${JUCE_PIP_MAIN_CLASS}();
}
#if JucePlugin_Enable_ARA
const ARA::ARAFactory* JUCE_CALLTYPE createARAFactory()
{
return juce::ARADocumentControllerSpecialisation::createARAFactory<${JUCE_PIP_DOCUMENTCONTROLLER_CLASS}>();
}
#endif

View File

@ -0,0 +1,37 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-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.
#
# ==============================================================================
find_program(JUCE_XCRUN xcrun)
if(NOT JUCE_XCRUN)
return()
endif()
execute_process(
COMMAND "${JUCE_XCRUN}" codesign --verify "${src}"
RESULT_VARIABLE result)
if(result)
message(STATUS "Replacing invalid signature with ad-hoc signature")
execute_process(COMMAND "${JUCE_XCRUN}" codesign -s - "${src}")
endif()

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see

View File

@ -1,57 +1,82 @@
#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
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
#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

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see

View File

@ -1,47 +1,47 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
#ifdef JUCE_BUILD_TOOLS_H_INCLUDED
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of JUCE cpp file"
#endif
#include "juce_build_tools.h"
#include <numeric>
#include "utils/juce_CppTokeniserFunctions.cpp"
#include "utils/juce_BuildHelperFunctions.cpp"
#include "utils/juce_BinaryResourceFile.cpp"
#include "utils/juce_Icons.cpp"
#include "utils/juce_PlistOptions.cpp"
#include "utils/juce_ResourceFileHelpers.cpp"
#include "utils/juce_ResourceRc.cpp"
#include "utils/juce_VersionNumbers.cpp"
#include "utils/juce_Entitlements.cpp"
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
#ifdef JUCE_BUILD_TOOLS_H_INCLUDED
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of JUCE cpp file"
#endif
#include "juce_build_tools.h"
#include <numeric>
#include "utils/juce_CppTokeniserFunctions.cpp"
#include "utils/juce_BuildHelperFunctions.cpp"
#include "utils/juce_BinaryResourceFile.cpp"
#include "utils/juce_Icons.cpp"
#include "utils/juce_PlistOptions.cpp"
#include "utils/juce_ResourceFileHelpers.cpp"
#include "utils/juce_ResourceRc.cpp"
#include "utils/juce_VersionNumbers.cpp"
#include "utils/juce_Entitlements.cpp"

View File

@ -1,67 +1,67 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.md file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_build_tools
vendor: juce
version: 6.1.2
name: JUCE Build Tools
description: Classes for generating intermediate files for JUCE projects.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_gui_basics
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
// This module is shared by juceaide and the Projucer, but should not be
// considered 'public'. That is, its API, functionality, and contents (and
// existence!) may change between releases without warning.
#pragma once
#define JUCE_BUILD_TOOLS_H_INCLUDED
#include <juce_gui_basics/juce_gui_basics.h>
#include "utils/juce_ProjectType.h"
#include "utils/juce_BuildHelperFunctions.h"
#include "utils/juce_BinaryResourceFile.h"
#include "utils/juce_RelativePath.h"
#include "utils/juce_Icons.h"
#include "utils/juce_PlistOptions.h"
#include "utils/juce_ResourceFileHelpers.h"
#include "utils/juce_ResourceRc.h"
#include "utils/juce_VersionNumbers.h"
#include "utils/juce_Entitlements.h"
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
/*******************************************************************************
The block below describes the properties of this module, and is read by
the Projucer to automatically generate project code that uses it.
For details about the syntax and how to create or use a module, see the
JUCE Module Format.md file.
BEGIN_JUCE_MODULE_DECLARATION
ID: juce_build_tools
vendor: juce
version: 7.0.2
name: JUCE Build Tools
description: Classes for generating intermediate files for JUCE projects.
website: http://www.juce.com/juce
license: GPL/Commercial
dependencies: juce_gui_basics
END_JUCE_MODULE_DECLARATION
*******************************************************************************/
// This module is shared by juceaide and the Projucer, but should not be
// considered 'public'. That is, its API, functionality, and contents (and
// existence!) may change between releases without warning.
#pragma once
#define JUCE_BUILD_TOOLS_H_INCLUDED
#include <juce_gui_basics/juce_gui_basics.h>
#include "utils/juce_ProjectType.h"
#include "utils/juce_BuildHelperFunctions.h"
#include "utils/juce_BinaryResourceFile.h"
#include "utils/juce_RelativePath.h"
#include "utils/juce_Icons.h"
#include "utils/juce_PlistOptions.h"
#include "utils/juce_ResourceFileHelpers.h"
#include "utils/juce_ResourceRc.h"
#include "utils/juce_VersionNumbers.h"
#include "utils/juce_Entitlements.h"

View File

@ -1,289 +1,289 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static const char* resourceFileIdentifierString = "JUCER_BINARY_RESOURCE";
//==============================================================================
void ResourceFile::setClassName (const String& name)
{
className = name;
}
void ResourceFile::addFile (const File& file)
{
files.add (file);
auto variableNameRoot = makeBinaryDataIdentifierName (file);
auto variableName = variableNameRoot;
int suffix = 2;
while (variableNames.contains (variableName))
variableName = variableNameRoot + String (suffix++);
variableNames.add (variableName);
}
String ResourceFile::getDataVariableFor (const File& file) const
{
const auto index = files.indexOf (file);
jassert (index >= 0);
return variableNames[index];
}
String ResourceFile::getSizeVariableFor (const File& file) const
{
return getDataVariableFor (file) + "Size";
}
int64 ResourceFile::getTotalDataSize() const
{
return std::accumulate (files.begin(),
files.end(),
int64 { 0 },
[] (int64 acc, const File& f) { return acc + f.getSize(); });
}
static void writeComment (MemoryOutputStream& mo)
{
mo << newLine << newLine
<< " This is an auto-generated file: Any edits you make may be overwritten!" << newLine
<< newLine
<< "*/" << newLine
<< newLine;
}
Result ResourceFile::writeHeader (MemoryOutputStream& header)
{
header << "/* =========================================================================================";
writeComment (header);
header << "#pragma once" << newLine
<< newLine
<< "namespace " << className << newLine
<< "{" << newLine;
for (int i = 0; i < files.size(); ++i)
{
auto& file = files.getReference(i);
if (! file.existsAsFile())
return Result::fail ("Can't open resource file: " + file.getFullPathName());
auto dataSize = file.getSize();
auto variableName = variableNames[i];
FileInputStream fileStream (file);
if (fileStream.openedOk())
{
header << " extern const char* " << variableName << ";" << newLine;
header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine;
}
}
header << " // Number of elements in the namedResourceList and originalFileNames arrays." << newLine
<< " const int namedResourceListSize = " << files.size() << ";" << newLine
<< newLine
<< " // Points to the start of a list of resource names." << newLine
<< " extern const char* namedResourceList[];" << newLine
<< newLine
<< " // Points to the start of a list of resource filenames." << newLine
<< " extern const char* originalFilenames[];" << newLine
<< newLine
<< " // If you provide the name of one of the binary resource variables above, this function will" << newLine
<< " // return the corresponding data and its size (or a null pointer if the name isn't found)." << newLine
<< " const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes);" << newLine
<< newLine
<< " // If you provide the name of one of the binary resource variables above, this function will" << newLine
<< " // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found)." << newLine
<< " const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine
<< "}" << newLine;
return Result::ok();
}
Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize)
{
bool isFirstFile = (i == 0);
cpp << "/* ==================================== " << resourceFileIdentifierString << " ====================================";
writeComment (cpp);
cpp << "namespace " << className << newLine
<< "{" << newLine;
while (i < files.size())
{
auto& file = files.getReference(i);
auto variableName = variableNames[i];
FileInputStream fileStream (file);
if (fileStream.openedOk())
{
auto tempVariable = "temp_binary_data_" + String (i);
cpp << newLine << "//================== " << file.getFileName() << " ==================" << newLine
<< "static const unsigned char " << tempVariable << "[] =" << newLine;
{
MemoryBlock data;
fileStream.readIntoMemoryBlock (data);
writeDataAsCppLiteral (data, cpp, true, true);
}
cpp << newLine << newLine
<< "const char* " << variableName << " = (const char*) " << tempVariable << ";" << newLine;
}
++i;
if (cpp.getPosition() > maxFileSize)
break;
}
if (isFirstFile)
{
if (i < files.size())
{
cpp << newLine
<< "}" << newLine
<< newLine
<< "#include \"" << headerFile.getFileName() << "\"" << newLine
<< newLine
<< "namespace " << className << newLine
<< "{";
}
cpp << newLine
<< newLine
<< "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes);" << newLine
<< "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)" << newLine
<< "{" << newLine;
StringArray returnCodes;
for (auto& file : files)
{
auto dataSize = file.getSize();
returnCodes.add ("numBytes = " + String (dataSize) + "; return " + variableNames[files.indexOf (file)] + ";");
}
createStringMatcher (cpp, "resourceNameUTF8", variableNames, returnCodes, 4);
cpp << " numBytes = 0;" << newLine
<< " return nullptr;" << newLine
<< "}" << newLine
<< newLine;
cpp << "const char* namedResourceList[] =" << newLine
<< "{" << newLine;
for (int j = 0; j < files.size(); ++j)
cpp << " " << variableNames[j].quoted() << (j < files.size() - 1 ? "," : "") << newLine;
cpp << "};" << newLine << newLine;
cpp << "const char* originalFilenames[] =" << newLine
<< "{" << newLine;
for (auto& f : files)
cpp << " " << f.getFileName().quoted() << (files.indexOf (f) < files.size() - 1 ? "," : "") << newLine;
cpp << "};" << newLine << newLine;
cpp << "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine
<< "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8)" << newLine
<< "{" << newLine
<< " for (unsigned int i = 0; i < (sizeof (namedResourceList) / sizeof (namedResourceList[0])); ++i)" << newLine
<< " {" << newLine
<< " if (namedResourceList[i] == resourceNameUTF8)" << newLine
<< " return originalFilenames[i];" << newLine
<< " }" << newLine
<< newLine
<< " return nullptr;" << newLine
<< "}" << newLine
<< newLine;
}
cpp << "}" << newLine;
return Result::ok();
}
ResourceFile::WriteResult ResourceFile::write (int maxFileSize,
String projectLineFeed,
File headerFile,
std::function<File (int)> getCppFile)
{
Array<File> filesCreated;
{
MemoryOutputStream mo;
mo.setNewLineString (projectLineFeed);
auto r = writeHeader (mo);
if (r.failed())
return { r, {} };
if (! overwriteFileWithNewDataIfDifferent (headerFile, mo))
return { Result::fail ("Can't write to file: " + headerFile.getFullPathName()), {} };
filesCreated.add (headerFile);
}
int i = 0;
int fileIndex = 0;
for (;;)
{
auto cpp = getCppFile (fileIndex);
MemoryOutputStream mo;
mo.setNewLineString (projectLineFeed);
auto r = writeCpp (mo, headerFile, i, maxFileSize);
if (r.failed())
return { r, std::move (filesCreated) };
if (! overwriteFileWithNewDataIfDifferent (cpp, mo))
return { Result::fail ("Can't write to file: " + cpp.getFullPathName()), std::move (filesCreated) };
filesCreated.add (cpp);
++fileIndex;
if (i >= files.size())
break;
}
return { Result::ok(), std::move (filesCreated) };
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static const char* resourceFileIdentifierString = "JUCER_BINARY_RESOURCE";
//==============================================================================
void ResourceFile::setClassName (const String& name)
{
className = name;
}
void ResourceFile::addFile (const File& file)
{
files.add (file);
auto variableNameRoot = makeBinaryDataIdentifierName (file);
auto variableName = variableNameRoot;
int suffix = 2;
while (variableNames.contains (variableName))
variableName = variableNameRoot + String (suffix++);
variableNames.add (variableName);
}
String ResourceFile::getDataVariableFor (const File& file) const
{
const auto index = files.indexOf (file);
jassert (index >= 0);
return variableNames[index];
}
String ResourceFile::getSizeVariableFor (const File& file) const
{
return getDataVariableFor (file) + "Size";
}
int64 ResourceFile::getTotalDataSize() const
{
return std::accumulate (files.begin(),
files.end(),
int64 { 0 },
[] (int64 acc, const File& f) { return acc + f.getSize(); });
}
static void writeComment (MemoryOutputStream& mo)
{
mo << newLine << newLine
<< " This is an auto-generated file: Any edits you make may be overwritten!" << newLine
<< newLine
<< "*/" << newLine
<< newLine;
}
Result ResourceFile::writeHeader (MemoryOutputStream& header)
{
header << "/* =========================================================================================";
writeComment (header);
header << "#pragma once" << newLine
<< newLine
<< "namespace " << className << newLine
<< "{" << newLine;
for (int i = 0; i < files.size(); ++i)
{
auto& file = files.getReference(i);
if (! file.existsAsFile())
return Result::fail ("Can't open resource file: " + file.getFullPathName());
auto dataSize = file.getSize();
auto variableName = variableNames[i];
FileInputStream fileStream (file);
if (fileStream.openedOk())
{
header << " extern const char* " << variableName << ";" << newLine;
header << " const int " << variableName << "Size = " << (int) dataSize << ";" << newLine << newLine;
}
}
header << " // Number of elements in the namedResourceList and originalFileNames arrays." << newLine
<< " const int namedResourceListSize = " << files.size() << ";" << newLine
<< newLine
<< " // Points to the start of a list of resource names." << newLine
<< " extern const char* namedResourceList[];" << newLine
<< newLine
<< " // Points to the start of a list of resource filenames." << newLine
<< " extern const char* originalFilenames[];" << newLine
<< newLine
<< " // If you provide the name of one of the binary resource variables above, this function will" << newLine
<< " // return the corresponding data and its size (or a null pointer if the name isn't found)." << newLine
<< " const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes);" << newLine
<< newLine
<< " // If you provide the name of one of the binary resource variables above, this function will" << newLine
<< " // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found)." << newLine
<< " const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine
<< "}" << newLine;
return Result::ok();
}
Result ResourceFile::writeCpp (MemoryOutputStream& cpp, const File& headerFile, int& i, const int maxFileSize)
{
bool isFirstFile = (i == 0);
cpp << "/* ==================================== " << resourceFileIdentifierString << " ====================================";
writeComment (cpp);
cpp << "#include <cstring>" << newLine
<< newLine
<< "namespace " << className << newLine
<< "{" << newLine;
while (i < files.size())
{
auto& file = files.getReference(i);
auto variableName = variableNames[i];
FileInputStream fileStream (file);
if (fileStream.openedOk())
{
auto tempVariable = "temp_binary_data_" + String (i);
cpp << newLine << "//================== " << file.getFileName() << " ==================" << newLine
<< "static const unsigned char " << tempVariable << "[] =" << newLine;
{
MemoryBlock data;
fileStream.readIntoMemoryBlock (data);
writeDataAsCppLiteral (data, cpp, true, true);
}
cpp << newLine << newLine
<< "const char* " << variableName << " = (const char*) " << tempVariable << ";" << newLine;
}
++i;
if (cpp.getPosition() > maxFileSize)
break;
}
if (isFirstFile)
{
if (i < files.size())
{
cpp << newLine
<< "}" << newLine
<< newLine
<< "#include \"" << headerFile.getFileName() << "\"" << newLine
<< newLine
<< "namespace " << className << newLine
<< "{";
}
cpp << newLine
<< newLine
<< "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes);" << newLine
<< "const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)" << newLine
<< "{" << newLine;
StringArray returnCodes;
for (auto& file : files)
{
auto dataSize = file.getSize();
returnCodes.add ("numBytes = " + String (dataSize) + "; return " + variableNames[files.indexOf (file)] + ";");
}
createStringMatcher (cpp, "resourceNameUTF8", variableNames, returnCodes, 4);
cpp << " numBytes = 0;" << newLine
<< " return nullptr;" << newLine
<< "}" << newLine
<< newLine;
cpp << "const char* namedResourceList[] =" << newLine
<< "{" << newLine;
for (int j = 0; j < files.size(); ++j)
cpp << " " << variableNames[j].quoted() << (j < files.size() - 1 ? "," : "") << newLine;
cpp << "};" << newLine << newLine;
cpp << "const char* originalFilenames[] =" << newLine
<< "{" << newLine;
for (auto& f : files)
cpp << " " << f.getFileName().quoted() << (files.indexOf (f) < files.size() - 1 ? "," : "") << newLine;
cpp << "};" << newLine << newLine;
cpp << "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8);" << newLine
<< "const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8)" << newLine
<< "{" << newLine
<< " for (unsigned int i = 0; i < (sizeof (namedResourceList) / sizeof (namedResourceList[0])); ++i)" << newLine
<< " if (strcmp (namedResourceList[i], resourceNameUTF8) == 0)" << newLine
<< " return originalFilenames[i];" << newLine
<< newLine
<< " return nullptr;" << newLine
<< "}" << newLine
<< newLine;
}
cpp << "}" << newLine;
return Result::ok();
}
ResourceFile::WriteResult ResourceFile::write (int maxFileSize,
String projectLineFeed,
File headerFile,
std::function<File (int)> getCppFile)
{
Array<File> filesCreated;
{
MemoryOutputStream mo;
mo.setNewLineString (projectLineFeed);
auto r = writeHeader (mo);
if (r.failed())
return { r, {} };
if (! overwriteFileWithNewDataIfDifferent (headerFile, mo))
return { Result::fail ("Can't write to file: " + headerFile.getFullPathName()), {} };
filesCreated.add (headerFile);
}
int i = 0;
int fileIndex = 0;
for (;;)
{
auto cpp = getCppFile (fileIndex);
MemoryOutputStream mo;
mo.setNewLineString (projectLineFeed);
auto r = writeCpp (mo, headerFile, i, maxFileSize);
if (r.failed())
return { r, std::move (filesCreated) };
if (! overwriteFileWithNewDataIfDifferent (cpp, mo))
return { Result::fail ("Can't write to file: " + cpp.getFullPathName()), std::move (filesCreated) };
filesCreated.add (cpp);
++fileIndex;
if (i >= files.size())
break;
}
return { Result::ok(), std::move (filesCreated) };
}
}
}

View File

@ -1,74 +1,74 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class ResourceFile
{
public:
ResourceFile() = default;
void setClassName (const String& className);
String getClassName() const { return className; }
void addFile (const File& file);
String getDataVariableFor (const File& file) const;
String getSizeVariableFor (const File& file) const;
int getNumFiles() const { return files.size (); }
const File& getFile (int index) const { return files.getReference (index); }
int64 getTotalDataSize() const;
struct WriteResult
{
Result result;
Array<File> filesCreated;
};
WriteResult write (int maxFileSize,
String projectLineFeed,
File headerFile,
std::function<File (int)> getCppFile);
private:
Array<File> files;
StringArray variableNames;
String className { "BinaryData" };
Result writeHeader (MemoryOutputStream&);
Result writeCpp (MemoryOutputStream&, const File&, int&, int);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResourceFile)
};
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class ResourceFile
{
public:
ResourceFile() = default;
void setClassName (const String& className);
String getClassName() const { return className; }
void addFile (const File& file);
String getDataVariableFor (const File& file) const;
String getSizeVariableFor (const File& file) const;
int getNumFiles() const { return files.size (); }
const File& getFile (int index) const { return files.getReference (index); }
int64 getTotalDataSize() const;
struct WriteResult
{
Result result;
Array<File> filesCreated;
};
WriteResult write (int maxFileSize,
String projectLineFeed,
File headerFile,
std::function<File (int)> getCppFile);
private:
Array<File> files;
StringArray variableNames;
String className { "BinaryData" };
Result writeHeader (MemoryOutputStream&);
Result writeCpp (MemoryOutputStream&, const File&, int&, int);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResourceFile)
};
}
}

View File

@ -1,355 +1,357 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData)
{
if (! overwriteFileWithNewDataIfDifferent (file, newData))
throw SaveError (file);
}
void overwriteFileIfDifferentOrThrow (const File& file, const String& newData)
{
if (! overwriteFileWithNewDataIfDifferent (file, newData))
throw SaveError (file);
}
String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString)
{
for (int i = 0; i < definitions.size(); ++i)
{
const String key (definitions.getAllKeys()[i]);
const String value (definitions.getAllValues()[i]);
sourceString = sourceString.replace ("${" + key + "}", value);
}
return sourceString;
}
String getXcodePackageType (ProjectType::Target::Type type)
{
using Type = ProjectType::Target::Type;
switch (type)
{
case Type::GUIApp:
case Type::StandalonePlugIn:
return "APPL";
case Type::VSTPlugIn:
case Type::VST3PlugIn:
case Type::AudioUnitPlugIn:
case Type::UnityPlugIn:
return "BNDL";
case Type::AudioUnitv3PlugIn:
return "XPC!";
case Type::AAXPlugIn:
case Type::RTASPlugIn:
return "TDMw";
case Type::ConsoleApp:
case Type::StaticLibrary:
case Type::DynamicLibrary:
case Type::SharedCodeTarget:
case Type::AggregateTarget:
case Type::unspecified:
default:
return {};
}
}
String getXcodeBundleSignature (ProjectType::Target::Type type)
{
using Type = ProjectType::Target::Type;
switch (type)
{
case Type::GUIApp:
case Type::VSTPlugIn:
case Type::VST3PlugIn:
case Type::AudioUnitPlugIn:
case Type::StandalonePlugIn:
case Type::AudioUnitv3PlugIn:
case Type::UnityPlugIn:
return "????";
case Type::AAXPlugIn:
case Type::RTASPlugIn:
return "PTul";
case Type::ConsoleApp:
case Type::StaticLibrary:
case Type::DynamicLibrary:
case Type::SharedCodeTarget:
case Type::AggregateTarget:
case Type::unspecified:
default:
return {};
}
}
static unsigned int calculateHash (const String& s, const unsigned int hashMultiplier)
{
auto t = s.toUTF8();
unsigned int hash = 0;
while (*t != 0)
hash = hashMultiplier * hash + (unsigned int) *t++;
return hash;
}
static unsigned int findBestHashMultiplier (const StringArray& strings)
{
unsigned int v = 31;
for (;;)
{
SortedSet<unsigned int> hashes;
bool collision = false;
for (int i = strings.size(); --i >= 0;)
{
auto hash = calculateHash (strings[i], v);
if (hashes.contains (hash))
{
collision = true;
break;
}
hashes.add (hash);
}
if (! collision)
break;
v += 2;
}
return v;
}
String makeValidIdentifier (String s, bool makeCamelCase, bool removeColons, bool allowTemplates, bool allowAsterisks)
{
if (s.isEmpty())
return "unknown";
if (removeColons)
s = s.replaceCharacters (".,;:/@", "______");
else
s = s.replaceCharacters (".,;/@", "_____");
for (int i = s.length(); --i > 0;)
if (CharacterFunctions::isLetter (s[i])
&& CharacterFunctions::isLetter (s[i - 1])
&& CharacterFunctions::isUpperCase (s[i])
&& ! CharacterFunctions::isUpperCase (s[i - 1]))
s = s.substring (0, i) + " " + s.substring (i);
String allowedChars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789");
if (allowTemplates)
allowedChars += "<>";
if (! removeColons)
allowedChars += ":";
if (allowAsterisks)
allowedChars += "*";
StringArray words;
words.addTokens (s.retainCharacters (allowedChars), false);
words.trim();
auto n = words[0];
if (makeCamelCase)
n = n.toLowerCase();
for (int i = 1; i < words.size(); ++i)
{
if (makeCamelCase && words[i].length() > 1)
n << words[i].substring (0, 1).toUpperCase()
<< words[i].substring (1).toLowerCase();
else
n << words[i];
}
if (CharacterFunctions::isDigit (n[0]))
n = "_" + n;
if (isReservedKeyword (n))
n << '_';
return n;
}
String makeBinaryDataIdentifierName (const File& file)
{
return makeValidIdentifier (file.getFileName()
.replaceCharacters (" .", "__")
.retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"),
false, true, false);
}
void writeDataAsCppLiteral (const MemoryBlock& mb, OutputStream& out,
bool breakAtNewLines, bool allowStringBreaks)
{
const int maxCharsOnLine = 250;
auto data = (const unsigned char*) mb.getData();
int charsOnLine = 0;
bool canUseStringLiteral = mb.getSize() < 32768; // MS compilers can't handle big string literals..
if (canUseStringLiteral)
{
unsigned int numEscaped = 0;
for (size_t i = 0; i < mb.getSize(); ++i)
{
auto num = (unsigned int) data[i];
if (! ((num >= 32 && num < 127) || num == '\t' || num == '\r' || num == '\n'))
{
if (++numEscaped > mb.getSize() / 4)
{
canUseStringLiteral = false;
break;
}
}
}
}
if (! canUseStringLiteral)
{
out << "{ ";
for (size_t i = 0; i < mb.getSize(); ++i)
{
auto num = (int) (unsigned int) data[i];
out << num << ',';
charsOnLine += 2;
if (num >= 10)
{
++charsOnLine;
if (num >= 100)
++charsOnLine;
}
if (charsOnLine >= maxCharsOnLine)
{
charsOnLine = 0;
out << newLine;
}
}
out << "0,0 };";
}
else
{
out << "\"";
writeEscapeChars (out, (const char*) data, (int) mb.getSize(),
maxCharsOnLine, breakAtNewLines, false, allowStringBreaks);
out << "\";";
}
}
void createStringMatcher (OutputStream& out, const String& utf8PointerVariable,
const StringArray& strings, const StringArray& codeToExecute, const int indentLevel)
{
jassert (strings.size() == codeToExecute.size());
auto indent = String::repeatedString (" ", indentLevel);
auto hashMultiplier = findBestHashMultiplier (strings);
out << indent << "unsigned int hash = 0;" << newLine
<< newLine
<< indent << "if (" << utf8PointerVariable << " != nullptr)" << newLine
<< indent << " while (*" << utf8PointerVariable << " != 0)" << newLine
<< indent << " hash = " << (int) hashMultiplier << " * hash + (unsigned int) *" << utf8PointerVariable << "++;" << newLine
<< newLine
<< indent << "switch (hash)" << newLine
<< indent << "{" << newLine;
for (int i = 0; i < strings.size(); ++i)
{
out << indent << " case 0x" << hexString8Digits ((int) calculateHash (strings[i], hashMultiplier))
<< ": " << codeToExecute[i] << newLine;
}
out << indent << " default: break;" << newLine
<< indent << "}" << newLine << newLine;
}
String unixStylePath (const String& path) { return path.replaceCharacter ('\\', '/'); }
String windowsStylePath (const String& path) { return path.replaceCharacter ('/', '\\'); }
String currentOSStylePath (const String& path)
{
#if JUCE_WINDOWS
return windowsStylePath (path);
#else
return unixStylePath (path);
#endif
}
bool isAbsolutePath (const String& path)
{
return File::isAbsolutePath (path)
|| path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows)
|| path.startsWithChar ('$')
|| path.startsWithChar ('~')
|| (CharacterFunctions::isLetter (path[0]) && path[1] == ':')
|| path.startsWithIgnoreCase ("smb:");
}
String getRelativePathFrom (const File& file, const File& sourceFolder)
{
#if ! JUCE_WINDOWS
// On a non-windows machine, we can't know if a drive-letter path may be relative or not.
if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':')
return file.getFullPathName();
#endif
return file.getRelativePathFrom (sourceFolder);
}
void writeStreamToFile (const File& file, const std::function<void (MemoryOutputStream&)>& writer)
{
MemoryOutputStream mo;
writer (mo);
overwriteFileIfDifferentOrThrow (file, mo);
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData)
{
if (! overwriteFileWithNewDataIfDifferent (file, newData))
throw SaveError (file);
}
void overwriteFileIfDifferentOrThrow (const File& file, const String& newData)
{
if (! overwriteFileWithNewDataIfDifferent (file, newData))
throw SaveError (file);
}
String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString)
{
for (int i = 0; i < definitions.size(); ++i)
{
const String key (definitions.getAllKeys()[i]);
const String value (definitions.getAllValues()[i]);
sourceString = sourceString.replace ("${" + key + "}", value);
}
return sourceString;
}
String getXcodePackageType (ProjectType::Target::Type type)
{
using Type = ProjectType::Target::Type;
switch (type)
{
case Type::GUIApp:
case Type::StandalonePlugIn:
return "APPL";
case Type::VSTPlugIn:
case Type::VST3PlugIn:
case Type::AudioUnitPlugIn:
case Type::UnityPlugIn:
return "BNDL";
case Type::AudioUnitv3PlugIn:
return "XPC!";
case Type::AAXPlugIn:
return "TDMw";
case Type::ConsoleApp:
case Type::StaticLibrary:
case Type::DynamicLibrary:
case Type::LV2PlugIn:
case Type::LV2TurtleProgram:
case Type::SharedCodeTarget:
case Type::AggregateTarget:
case Type::unspecified:
default:
return {};
}
}
String getXcodeBundleSignature (ProjectType::Target::Type type)
{
using Type = ProjectType::Target::Type;
switch (type)
{
case Type::GUIApp:
case Type::VSTPlugIn:
case Type::VST3PlugIn:
case Type::AudioUnitPlugIn:
case Type::StandalonePlugIn:
case Type::AudioUnitv3PlugIn:
case Type::UnityPlugIn:
return "????";
case Type::AAXPlugIn:
return "PTul";
case Type::ConsoleApp:
case Type::StaticLibrary:
case Type::DynamicLibrary:
case Type::LV2PlugIn:
case Type::LV2TurtleProgram:
case Type::SharedCodeTarget:
case Type::AggregateTarget:
case Type::unspecified:
default:
return {};
}
}
static unsigned int calculateHash (const String& s, const unsigned int hashMultiplier)
{
auto t = s.toUTF8();
unsigned int hash = 0;
while (*t != 0)
hash = hashMultiplier * hash + (unsigned int) *t++;
return hash;
}
static unsigned int findBestHashMultiplier (const StringArray& strings)
{
unsigned int v = 31;
for (;;)
{
SortedSet<unsigned int> hashes;
bool collision = false;
for (int i = strings.size(); --i >= 0;)
{
auto hash = calculateHash (strings[i], v);
if (hashes.contains (hash))
{
collision = true;
break;
}
hashes.add (hash);
}
if (! collision)
break;
v += 2;
}
return v;
}
String makeValidIdentifier (String s, bool makeCamelCase, bool removeColons, bool allowTemplates, bool allowAsterisks)
{
if (s.isEmpty())
return "unknown";
if (removeColons)
s = s.replaceCharacters (".,;:/@", "______");
else
s = s.replaceCharacters (".,;/@", "_____");
for (int i = s.length(); --i > 0;)
if (CharacterFunctions::isLetter (s[i])
&& CharacterFunctions::isLetter (s[i - 1])
&& CharacterFunctions::isUpperCase (s[i])
&& ! CharacterFunctions::isUpperCase (s[i - 1]))
s = s.substring (0, i) + " " + s.substring (i);
String allowedChars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789");
if (allowTemplates)
allowedChars += "<>";
if (! removeColons)
allowedChars += ":";
if (allowAsterisks)
allowedChars += "*";
StringArray words;
words.addTokens (s.retainCharacters (allowedChars), false);
words.trim();
auto n = words[0];
if (makeCamelCase)
n = n.toLowerCase();
for (int i = 1; i < words.size(); ++i)
{
if (makeCamelCase && words[i].length() > 1)
n << words[i].substring (0, 1).toUpperCase()
<< words[i].substring (1).toLowerCase();
else
n << words[i];
}
if (CharacterFunctions::isDigit (n[0]))
n = "_" + n;
if (isReservedKeyword (n))
n << '_';
return n;
}
String makeBinaryDataIdentifierName (const File& file)
{
return makeValidIdentifier (file.getFileName()
.replaceCharacters (" .", "__")
.retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"),
false, true, false);
}
void writeDataAsCppLiteral (const MemoryBlock& mb, OutputStream& out,
bool breakAtNewLines, bool allowStringBreaks)
{
const int maxCharsOnLine = 250;
auto data = (const unsigned char*) mb.getData();
int charsOnLine = 0;
bool canUseStringLiteral = mb.getSize() < 32768; // MS compilers can't handle big string literals..
if (canUseStringLiteral)
{
unsigned int numEscaped = 0;
for (size_t i = 0; i < mb.getSize(); ++i)
{
auto num = (unsigned int) data[i];
if (! ((num >= 32 && num < 127) || num == '\t' || num == '\r' || num == '\n'))
{
if (++numEscaped > mb.getSize() / 4)
{
canUseStringLiteral = false;
break;
}
}
}
}
if (! canUseStringLiteral)
{
out << "{ ";
for (size_t i = 0; i < mb.getSize(); ++i)
{
auto num = (int) (unsigned int) data[i];
out << num << ',';
charsOnLine += 2;
if (num >= 10)
{
++charsOnLine;
if (num >= 100)
++charsOnLine;
}
if (charsOnLine >= maxCharsOnLine)
{
charsOnLine = 0;
out << newLine;
}
}
out << "0,0 };";
}
else
{
out << "\"";
writeEscapeChars (out, (const char*) data, (int) mb.getSize(),
maxCharsOnLine, breakAtNewLines, false, allowStringBreaks);
out << "\";";
}
}
void createStringMatcher (OutputStream& out, const String& utf8PointerVariable,
const StringArray& strings, const StringArray& codeToExecute, const int indentLevel)
{
jassert (strings.size() == codeToExecute.size());
auto indent = String::repeatedString (" ", indentLevel);
auto hashMultiplier = findBestHashMultiplier (strings);
out << indent << "unsigned int hash = 0;" << newLine
<< newLine
<< indent << "if (" << utf8PointerVariable << " != nullptr)" << newLine
<< indent << " while (*" << utf8PointerVariable << " != 0)" << newLine
<< indent << " hash = " << (int) hashMultiplier << " * hash + (unsigned int) *" << utf8PointerVariable << "++;" << newLine
<< newLine
<< indent << "switch (hash)" << newLine
<< indent << "{" << newLine;
for (int i = 0; i < strings.size(); ++i)
{
out << indent << " case 0x" << hexString8Digits ((int) calculateHash (strings[i], hashMultiplier))
<< ": " << codeToExecute[i] << newLine;
}
out << indent << " default: break;" << newLine
<< indent << "}" << newLine << newLine;
}
String unixStylePath (const String& path) { return path.replaceCharacter ('\\', '/'); }
String windowsStylePath (const String& path) { return path.replaceCharacter ('/', '\\'); }
String currentOSStylePath (const String& path)
{
#if JUCE_WINDOWS
return windowsStylePath (path);
#else
return unixStylePath (path);
#endif
}
bool isAbsolutePath (const String& path)
{
return File::isAbsolutePath (path)
|| path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows)
|| path.startsWithChar ('$')
|| path.startsWithChar ('~')
|| (CharacterFunctions::isLetter (path[0]) && path[1] == ':')
|| path.startsWithIgnoreCase ("smb:");
}
String getRelativePathFrom (const File& file, const File& sourceFolder)
{
#if ! JUCE_WINDOWS
// On a non-windows machine, we can't know if a drive-letter path may be relative or not.
if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':')
return file.getFullPathName();
#endif
return file.getRelativePathFrom (sourceFolder);
}
void writeStreamToFile (const File& file, const std::function<void (MemoryOutputStream&)>& writer)
{
MemoryOutputStream mo;
writer (mo);
overwriteFileIfDifferentOrThrow (file, mo);
}
}
}

View File

@ -1,86 +1,86 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData);
void overwriteFileIfDifferentOrThrow (const File& file, const String& newData);
class SaveError
{
public:
SaveError (const String& error) : message (error)
{}
SaveError (const File& fileThatFailedToWrite)
: message ("Can't write to the file: " + fileThatFailedToWrite.getFullPathName())
{}
String message;
};
String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString);
String getXcodePackageType (ProjectType::Target::Type);
String getXcodeBundleSignature (ProjectType::Target::Type);
inline String hexString8Digits (int value)
{
return String::toHexString (value).paddedLeft ('0', 8);
}
String makeValidIdentifier (String s,
bool makeCamelCase,
bool removeColons,
bool allowTemplates,
bool allowAsterisks = false);
String makeBinaryDataIdentifierName (const File& file);
void writeDataAsCppLiteral (const MemoryBlock& mb,
OutputStream& out,
bool breakAtNewLines,
bool allowStringBreaks);
void createStringMatcher (OutputStream& out,
const String& utf8PointerVariable,
const StringArray& strings,
const StringArray& codeToExecute,
const int indentLevel);
String unixStylePath (const String& path);
String windowsStylePath (const String& path);
String currentOSStylePath (const String& path);
bool isAbsolutePath (const String& path);
// A windows-aware version of File::getRelativePath()
String getRelativePathFrom (const File& file, const File& sourceFolder);
void writeStreamToFile (const File& file, const std::function<void (MemoryOutputStream&)>& writer);
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData);
void overwriteFileIfDifferentOrThrow (const File& file, const String& newData);
class SaveError
{
public:
SaveError (const String& error) : message (error)
{}
SaveError (const File& fileThatFailedToWrite)
: message ("Can't write to the file: " + fileThatFailedToWrite.getFullPathName())
{}
String message;
};
String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString);
String getXcodePackageType (ProjectType::Target::Type);
String getXcodeBundleSignature (ProjectType::Target::Type);
inline String hexString8Digits (int value)
{
return String::toHexString (value).paddedLeft ('0', 8);
}
String makeValidIdentifier (String s,
bool makeCamelCase,
bool removeColons,
bool allowTemplates,
bool allowAsterisks = false);
String makeBinaryDataIdentifierName (const File& file);
void writeDataAsCppLiteral (const MemoryBlock& mb,
OutputStream& out,
bool breakAtNewLines,
bool allowStringBreaks);
void createStringMatcher (OutputStream& out,
const String& utf8PointerVariable,
const StringArray& strings,
const StringArray& codeToExecute,
const int indentLevel);
String unixStylePath (const String& path);
String windowsStylePath (const String& path);
String currentOSStylePath (const String& path);
bool isAbsolutePath (const String& path);
// A windows-aware version of File::getRelativePath()
String getRelativePathFrom (const File& file, const File& sourceFolder);
void writeStreamToFile (const File& file, const std::function<void (MemoryOutputStream&)>& writer);
}
}

View File

@ -1,206 +1,206 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept
{
static const char* const keywords2Char[] =
{ "do", "if", "or", nullptr };
static const char* const keywords3Char[] =
{ "and", "asm", "for", "int", "new", "not", "try", "xor", nullptr };
static const char* const keywords4Char[] =
{ "auto", "bool", "case", "char", "else", "enum", "goto",
"long", "this", "true", "void", nullptr };
static const char* const keywords5Char[] =
{ "bitor", "break", "catch", "class", "compl", "const", "false", "final",
"float", "or_eq", "short", "throw", "union", "using", "while", nullptr };
static const char* const keywords6Char[] =
{ "and_eq", "bitand", "delete", "double", "export", "extern", "friend",
"import", "inline", "module", "not_eq", "public", "return", "signed",
"sizeof", "static", "struct", "switch", "typeid", "xor_eq", nullptr };
static const char* const keywords7Char[] =
{ "__cdecl", "_Pragma", "alignas", "alignof", "concept", "default",
"mutable", "nullptr", "private", "typedef", "uint8_t", "virtual",
"wchar_t", nullptr };
static const char* const keywordsOther[] =
{ "@class", "@dynamic", "@end", "@implementation", "@interface", "@public",
"@private", "@protected", "@property", "@synthesize", "__fastcall", "__stdcall",
"atomic_cancel", "atomic_commit", "atomic_noexcept", "char16_t", "char32_t",
"co_await", "co_return", "co_yield", "const_cast", "constexpr", "continue",
"decltype", "dynamic_cast", "explicit", "namespace", "noexcept", "operator", "override",
"protected", "register", "reinterpret_cast", "requires", "static_assert",
"static_cast", "synchronized", "template", "thread_local", "typename", "unsigned",
"volatile", nullptr };
const char* const* k;
switch (tokenLength)
{
case 2: k = keywords2Char; break;
case 3: k = keywords3Char; break;
case 4: k = keywords4Char; break;
case 5: k = keywords5Char; break;
case 6: k = keywords6Char; break;
case 7: k = keywords7Char; break;
default:
if (tokenLength < 2 || tokenLength > 16)
return false;
k = keywordsOther;
break;
}
for (int i = 0; k[i] != nullptr; ++i)
if (token.compare (CharPointer_ASCII (k[i])) == 0)
return true;
return false;
}
static bool isReservedKeyword (const String& token) noexcept
{
return isReservedKeyword (token.getCharPointer(), token.length());
}
//==============================================================================
/** Takes a UTF8 string and writes it to a stream using standard C++ escape sequences for any
non-ascii bytes.
Although not strictly a tokenising function, this is still a function that often comes in
handy when working with C++ code!
Note that addEscapeChars() is easier to use than this function if you're working with Strings.
@see addEscapeChars
*/
static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytesToRead,
const int maxCharsOnLine, const bool breakAtNewLines,
const bool replaceSingleQuotes, const bool allowStringBreaks)
{
int charsOnLine = 0;
bool lastWasHexEscapeCode = false;
bool trigraphDetected = false;
for (int i = 0; i < numBytesToRead || numBytesToRead < 0; ++i)
{
auto c = (unsigned char) utf8[i];
bool startNewLine = false;
switch (c)
{
case '\t': out << "\\t"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\r': out << "\\r"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\n': out << "\\n"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break;
case '\\': out << "\\\\"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\"': out << "\\\""; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '?':
if (trigraphDetected)
{
out << "\\?";
charsOnLine++;
trigraphDetected = false;
}
else
{
out << "?";
trigraphDetected = true;
}
lastWasHexEscapeCode = false;
charsOnLine++;
break;
case 0:
if (numBytesToRead < 0)
return;
out << "\\0";
lastWasHexEscapeCode = true;
trigraphDetected = false;
charsOnLine += 2;
break;
case '\'':
if (replaceSingleQuotes)
{
out << "\\\'";
lastWasHexEscapeCode = false;
trigraphDetected = false;
charsOnLine += 2;
break;
}
// deliberate fall-through...
default:
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit)
&& CharacterFunctions::getHexDigitValue (c) >= 0))
{
out << (char) c;
lastWasHexEscapeCode = false;
trigraphDetected = false;
++charsOnLine;
}
else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127)
{
out << "\"\"" << (char) c;
lastWasHexEscapeCode = false;
trigraphDetected = false;
charsOnLine += 3;
}
else
{
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c);
lastWasHexEscapeCode = true;
trigraphDetected = false;
charsOnLine += 4;
}
break;
}
if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine))
&& (numBytesToRead < 0 || i < numBytesToRead - 1))
{
charsOnLine = 0;
out << "\"" << newLine << "\"";
lastWasHexEscapeCode = false;
}
}
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static bool isReservedKeyword (String::CharPointerType token, const int tokenLength) noexcept
{
static const char* const keywords2Char[] =
{ "do", "if", "or", nullptr };
static const char* const keywords3Char[] =
{ "and", "asm", "for", "int", "new", "not", "try", "xor", nullptr };
static const char* const keywords4Char[] =
{ "auto", "bool", "case", "char", "else", "enum", "goto",
"long", "this", "true", "void", nullptr };
static const char* const keywords5Char[] =
{ "bitor", "break", "catch", "class", "compl", "const", "false", "final",
"float", "or_eq", "short", "throw", "union", "using", "while", nullptr };
static const char* const keywords6Char[] =
{ "and_eq", "bitand", "delete", "double", "export", "extern", "friend",
"import", "inline", "module", "not_eq", "public", "return", "signed",
"sizeof", "static", "struct", "switch", "typeid", "xor_eq", nullptr };
static const char* const keywords7Char[] =
{ "__cdecl", "_Pragma", "alignas", "alignof", "concept", "default",
"mutable", "nullptr", "private", "typedef", "uint8_t", "virtual",
"wchar_t", nullptr };
static const char* const keywordsOther[] =
{ "@class", "@dynamic", "@end", "@implementation", "@interface", "@public",
"@private", "@protected", "@property", "@synthesize", "__fastcall", "__stdcall",
"atomic_cancel", "atomic_commit", "atomic_noexcept", "char16_t", "char32_t",
"co_await", "co_return", "co_yield", "const_cast", "constexpr", "continue",
"decltype", "dynamic_cast", "explicit", "namespace", "noexcept", "operator", "override",
"protected", "register", "reinterpret_cast", "requires", "static_assert",
"static_cast", "synchronized", "template", "thread_local", "typename", "unsigned",
"volatile", nullptr };
const char* const* k;
switch (tokenLength)
{
case 2: k = keywords2Char; break;
case 3: k = keywords3Char; break;
case 4: k = keywords4Char; break;
case 5: k = keywords5Char; break;
case 6: k = keywords6Char; break;
case 7: k = keywords7Char; break;
default:
if (tokenLength < 2 || tokenLength > 16)
return false;
k = keywordsOther;
break;
}
for (int i = 0; k[i] != nullptr; ++i)
if (token.compare (CharPointer_ASCII (k[i])) == 0)
return true;
return false;
}
static bool isReservedKeyword (const String& token) noexcept
{
return isReservedKeyword (token.getCharPointer(), token.length());
}
//==============================================================================
/** Takes a UTF8 string and writes it to a stream using standard C++ escape sequences for any
non-ascii bytes.
Although not strictly a tokenising function, this is still a function that often comes in
handy when working with C++ code!
Note that addEscapeChars() is easier to use than this function if you're working with Strings.
@see addEscapeChars
*/
static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytesToRead,
const int maxCharsOnLine, const bool breakAtNewLines,
const bool replaceSingleQuotes, const bool allowStringBreaks)
{
int charsOnLine = 0;
bool lastWasHexEscapeCode = false;
bool trigraphDetected = false;
for (int i = 0; i < numBytesToRead || numBytesToRead < 0; ++i)
{
auto c = (unsigned char) utf8[i];
bool startNewLine = false;
switch (c)
{
case '\t': out << "\\t"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\r': out << "\\r"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\n': out << "\\n"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break;
case '\\': out << "\\\\"; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '\"': out << "\\\""; trigraphDetected = false; lastWasHexEscapeCode = false; charsOnLine += 2; break;
case '?':
if (trigraphDetected)
{
out << "\\?";
charsOnLine++;
trigraphDetected = false;
}
else
{
out << "?";
trigraphDetected = true;
}
lastWasHexEscapeCode = false;
charsOnLine++;
break;
case 0:
if (numBytesToRead < 0)
return;
out << "\\0";
lastWasHexEscapeCode = true;
trigraphDetected = false;
charsOnLine += 2;
break;
case '\'':
if (replaceSingleQuotes)
{
out << "\\\'";
lastWasHexEscapeCode = false;
trigraphDetected = false;
charsOnLine += 2;
break;
}
// deliberate fall-through...
default:
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit)
&& CharacterFunctions::getHexDigitValue (c) >= 0))
{
out << (char) c;
lastWasHexEscapeCode = false;
trigraphDetected = false;
++charsOnLine;
}
else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127)
{
out << "\"\"" << (char) c;
lastWasHexEscapeCode = false;
trigraphDetected = false;
charsOnLine += 3;
}
else
{
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c);
lastWasHexEscapeCode = true;
trigraphDetected = false;
charsOnLine += 4;
}
break;
}
if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine))
&& (numBytesToRead < 0 || i < numBytesToRead - 1))
{
charsOnLine = 0;
out << "\"" << newLine << "\"";
lastWasHexEscapeCode = false;
}
}
}
}
}

View File

@ -1,119 +1,133 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
String EntitlementOptions::getEntitlementsFileContent() const
{
String content =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n";
const auto entitlements = getEntitlements();
for (auto& key : entitlements.getAllKeys())
content += "\t<key>" + key + "</key>\n\t" + entitlements[key] + "\n";
return content + "</dict>\n</plist>\n";
}
StringPairArray EntitlementOptions::getEntitlements() const
{
StringPairArray entitlements;
if (isiOS)
{
if (isAudioPluginProject && shouldEnableIAA)
entitlements.set ("inter-app-audio", "<true/>");
if (isiCloudPermissionsEnabled)
{
entitlements.set ("com.apple.developer.icloud-container-identifiers",
"<array>\n"
" <string>iCloud.$(CFBundleIdentifier)</string>\n"
" </array>");
entitlements.set ("com.apple.developer.icloud-services",
"<array>\n"
" <string>CloudDocuments</string>\n"
" </array>");
entitlements.set ("com.apple.developer.ubiquity-container-identifiers",
"<array>\n"
" <string>iCloud.$(CFBundleIdentifier)</string>\n"
" </array>");
}
}
if (isPushNotificationsEnabled)
entitlements.set (isiOS ? "aps-environment"
: "com.apple.developer.aps-environment",
"<string>development</string>");
if (isAppGroupsEnabled)
{
auto appGroups = StringArray::fromTokens (appGroupIdString, ";", {});
auto groups = String ("<array>");
for (auto group : appGroups)
groups += "\n\t\t<string>" + group.trim() + "</string>";
groups += "\n\t</array>";
entitlements.set ("com.apple.security.application-groups", groups);
}
if (isHardenedRuntimeEnabled)
for (auto& option : hardenedRuntimeOptions)
entitlements.set (option, "<true/>");
if (isAppSandboxEnabled || (! isiOS && isAudioPluginProject && type == ProjectType::Target::AudioUnitv3PlugIn))
{
entitlements.set ("com.apple.security.app-sandbox", "<true/>");
if (isAppSandboxInhertianceEnabled)
{
// no other sandbox options can be specified if sandbox inheritance is enabled!
jassert (appSandboxOptions.isEmpty());
entitlements.set ("com.apple.security.inherit", "<true/>");
}
if (isAppSandboxEnabled)
for (auto& option : appSandboxOptions)
entitlements.set (option, "<true/>");
}
if (isNetworkingMulticastEnabled)
entitlements.set ("com.apple.developer.networking.multicast", "<true/>");
return entitlements;
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
String EntitlementOptions::getEntitlementsFileContent() const
{
String content =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n";
const auto entitlements = getEntitlements();
for (auto& key : entitlements.getAllKeys())
content += "\t<key>" + key + "</key>\n\t" + entitlements[key] + "\n";
return content + "</dict>\n</plist>\n";
}
StringPairArray EntitlementOptions::getEntitlements() const
{
StringPairArray entitlements;
if (isiOS)
{
if (isAudioPluginProject && shouldEnableIAA)
entitlements.set ("inter-app-audio", "<true/>");
if (isiCloudPermissionsEnabled)
{
entitlements.set ("com.apple.developer.icloud-container-identifiers",
"<array>\n"
" <string>iCloud.$(CFBundleIdentifier)</string>\n"
" </array>");
entitlements.set ("com.apple.developer.icloud-services",
"<array>\n"
" <string>CloudDocuments</string>\n"
" </array>");
entitlements.set ("com.apple.developer.ubiquity-container-identifiers",
"<array>\n"
" <string>iCloud.$(CFBundleIdentifier)</string>\n"
" </array>");
}
}
if (isPushNotificationsEnabled)
entitlements.set (isiOS ? "aps-environment"
: "com.apple.developer.aps-environment",
"<string>development</string>");
if (isAppGroupsEnabled)
{
auto appGroups = StringArray::fromTokens (appGroupIdString, ";", {});
String groups = "<array>";
for (auto group : appGroups)
groups += "\n\t\t<string>" + group.trim() + "</string>";
groups += "\n\t</array>";
entitlements.set ("com.apple.security.application-groups", groups);
}
if (isHardenedRuntimeEnabled)
for (auto& option : hardenedRuntimeOptions)
entitlements.set (option, "<true/>");
if (isAppSandboxEnabled || (! isiOS && isAudioPluginProject && type == ProjectType::Target::AudioUnitv3PlugIn))
{
entitlements.set ("com.apple.security.app-sandbox", "<true/>");
if (isAppSandboxInhertianceEnabled)
{
// no other sandbox options can be specified if sandbox inheritance is enabled!
jassert (appSandboxOptions.isEmpty());
jassert (appSandboxTemporaryPaths.empty());
entitlements.set ("com.apple.security.inherit", "<true/>");
}
if (isAppSandboxEnabled)
{
for (auto& option : appSandboxOptions)
entitlements.set (option, "<true/>");
for (auto& option : appSandboxTemporaryPaths)
{
String paths = "<array>";
for (const auto& path : option.values)
paths += "\n\t\t<string>" + path + "</string>";
paths += "\n\t</array>";
entitlements.set (option.key, paths);
}
}
}
if (isNetworkingMulticastEnabled)
entitlements.set ("com.apple.developer.networking.multicast", "<true/>");
return entitlements;
}
}
}

View File

@ -1,56 +1,64 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
struct EntitlementOptions final
{
String getEntitlementsFileContent() const;
ProjectType::Target::Type type = ProjectType::Target::GUIApp;
bool isiOS = false;
bool isAudioPluginProject = false;
bool shouldEnableIAA = false;
bool isiCloudPermissionsEnabled = false;
bool isPushNotificationsEnabled = false;
bool isAppGroupsEnabled = false;
bool isHardenedRuntimeEnabled = false;
bool isAppSandboxEnabled = false;
bool isAppSandboxInhertianceEnabled = false;
bool isNetworkingMulticastEnabled = false;
String appGroupIdString;
StringArray hardenedRuntimeOptions;
StringArray appSandboxOptions;
private:
StringPairArray getEntitlements() const;
};
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
struct EntitlementOptions final
{
String getEntitlementsFileContent() const;
ProjectType::Target::Type type = ProjectType::Target::GUIApp;
bool isiOS = false;
bool isAudioPluginProject = false;
bool shouldEnableIAA = false;
bool isiCloudPermissionsEnabled = false;
bool isPushNotificationsEnabled = false;
bool isAppGroupsEnabled = false;
bool isHardenedRuntimeEnabled = false;
bool isAppSandboxEnabled = false;
bool isAppSandboxInhertianceEnabled = false;
bool isNetworkingMulticastEnabled = false;
String appGroupIdString;
StringArray hardenedRuntimeOptions;
StringArray appSandboxOptions;
struct KeyAndStringArray
{
String key;
StringArray values;
};
std::vector<KeyAndStringArray> appSandboxTemporaryPaths;
private:
StringPairArray getEntitlements() const;
};
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,49 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
struct Icons
{
std::unique_ptr<Drawable> small;
std::unique_ptr<Drawable> big;
};
Array<Drawable*> asArray (const Icons&);
void writeMacIcon (const Icons&, const File&);
void writeWinIcon (const Icons&, const File&);
Image getBestIconForSize (const Icons& icons,
int size,
bool returnNullIfNothingBigEnough);
Image rescaleImageForIcon (Drawable& d, const int size);
RelativePath createXcassetsFolderFromIcons (const Icons& icons,
const File& targetFolder,
String projectFilenameRootString);
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
struct Icons
{
std::unique_ptr<Drawable> small;
std::unique_ptr<Drawable> big;
};
Array<Drawable*> asArray (const Icons&);
void writeMacIcon (const Icons&, const File&);
void writeWinIcon (const Icons&, const File&);
Image getBestIconForSize (const Icons& icons,
int size,
bool returnNullIfNothingBigEnough);
Image rescaleImageForIcon (Drawable& d, const int size);
RelativePath createXcassetsFolderFromIcons (const Icons& icons,
const File& targetFolder,
String projectFilenameRootString);
}
}

View File

@ -1,370 +1,378 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
static XmlElement* getKeyWithName (XmlElement& xml, const String& key)
{
for (auto* element : xml.getChildWithTagNameIterator ("key"))
if (element->getAllSubText().trim().equalsIgnoreCase (key))
return element;
return nullptr;
}
static bool keyFoundAndNotSequentialDuplicate (XmlElement& xml, const String& key)
{
if (auto* element = getKeyWithName (xml, key))
{
if (element->getNextElement() != nullptr && element->getNextElement()->hasTagName ("key"))
{
// found broken plist format (sequential duplicate), fix by removing
xml.removeChildElement (element, true);
return false;
}
// key found (not sequential duplicate)
return true;
}
// key not found
return false;
}
static bool addKeyIfNotFound (XmlElement& xml, const String& key)
{
if (! keyFoundAndNotSequentialDuplicate (xml, key))
{
xml.createNewChildElement ("key")->addTextElement (key);
return true;
}
return false;
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const String& value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement ("string")->addTextElement (value);
}
template <size_t N>
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const char (&value) [N])
{
addPlistDictionaryKey (xml, key, String { value });
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const bool value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement (value ? "true" : "false");
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, int value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement ("integer")->addTextElement (String (value));
}
static void addArrayToPlist (XmlElement& dict, String arrayKey, const StringArray& arrayElements)
{
if (getKeyWithName (dict, arrayKey) != nullptr)
return;
dict.createNewChildElement ("key")->addTextElement (arrayKey);
auto* plistStringArray = dict.createNewChildElement ("array");
for (auto& e : arrayElements)
plistStringArray->createNewChildElement ("string")->addTextElement (e);
}
static int getAUVersionAsHexInteger (const PlistOptions& opts)
{
const auto segments = getVersionSegments (opts.marketingVersion);
const StringArray trimmed (segments.strings.getRawDataPointer(), jmin (segments.size(), 3));
return getVersionAsHexIntegerFromParts (trimmed);
}
//==============================================================================
void PlistOptions::write (const File& infoPlistFile) const
{
writeStreamToFile (infoPlistFile, [&] (MemoryOutputStream& mo) { write (mo); });
}
void PlistOptions::write (MemoryOutputStream& mo) const
{
XmlElement::TextFormat format;
format.dtd = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
createXML()->writeTo (mo, format);
}
std::unique_ptr<XmlElement> PlistOptions::createXML() const
{
auto plist = parseXML (plistToMerge);
if (plist == nullptr || ! plist->hasTagName ("plist"))
plist.reset (new XmlElement ("plist"));
auto* dict = plist->getChildByName ("dict");
if (dict == nullptr)
dict = plist->createNewChildElement ("dict");
if (microphonePermissionEnabled)
addPlistDictionaryKey (*dict, "NSMicrophoneUsageDescription", microphonePermissionText);
if (cameraPermissionEnabled)
addPlistDictionaryKey (*dict, "NSCameraUsageDescription", cameraPermissionText);
if (bluetoothPermissionEnabled)
addPlistDictionaryKey (*dict, "NSBluetoothAlwaysUsageDescription", bluetoothPermissionText);
if (iOS)
{
if (bluetoothPermissionEnabled)
addPlistDictionaryKey (*dict, "NSBluetoothPeripheralUsageDescription", bluetoothPermissionText); // needed for pre iOS 13.0
addPlistDictionaryKey (*dict, "LSRequiresIPhoneOS", true);
addPlistDictionaryKey (*dict, "UIViewControllerBasedStatusBarAppearance", true);
if (shouldAddStoryboardToProject)
addPlistDictionaryKey (*dict, "UILaunchStoryboardName", storyboardName);
}
else
{
if (sendAppleEventsPermissionEnabled)
addPlistDictionaryKey (*dict, "NSAppleEventsUsageDescription", sendAppleEventsPermissionText);
}
addPlistDictionaryKey (*dict, "CFBundleExecutable", executableName);
if (! iOS) // (NB: on iOS this causes error ITMS-90032 during publishing)
addPlistDictionaryKey (*dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String());
addPlistDictionaryKey (*dict, "CFBundleIdentifier", bundleIdentifier);
addPlistDictionaryKey (*dict, "CFBundleName", projectName);
// needed by NSExtension on iOS
addPlistDictionaryKey (*dict, "CFBundleDisplayName", projectName);
addPlistDictionaryKey (*dict, "CFBundlePackageType", getXcodePackageType (type));
addPlistDictionaryKey (*dict, "CFBundleSignature", getXcodeBundleSignature (type));
addPlistDictionaryKey (*dict, "CFBundleShortVersionString", marketingVersion);
addPlistDictionaryKey (*dict, "CFBundleVersion", currentProjectVersion);
addPlistDictionaryKey (*dict, "NSHumanReadableCopyright", companyCopyright);
addPlistDictionaryKey (*dict, "NSHighResolutionCapable", true);
if (applicationCategory.isNotEmpty())
addPlistDictionaryKey (*dict, "LSApplicationCategoryType", applicationCategory);
auto replacedDocExtensions = StringArray::fromTokens (replacePreprocessorDefs (allPreprocessorDefs,
documentExtensions), ",", {});
replacedDocExtensions.trim();
replacedDocExtensions.removeEmptyStrings (true);
if (! replacedDocExtensions.isEmpty() && type != ProjectType::Target::AudioUnitv3PlugIn)
{
dict->createNewChildElement ("key")->addTextElement ("CFBundleDocumentTypes");
auto* dict2 = dict->createNewChildElement ("array")->createNewChildElement ("dict");
XmlElement* arrayTag = nullptr;
for (auto ex : replacedDocExtensions)
{
if (ex.startsWithChar ('.'))
ex = ex.substring (1);
if (arrayTag == nullptr)
{
dict2->createNewChildElement ("key")->addTextElement ("CFBundleTypeExtensions");
arrayTag = dict2->createNewChildElement ("array");
addPlistDictionaryKey (*dict2, "CFBundleTypeName", ex);
addPlistDictionaryKey (*dict2, "CFBundleTypeRole", "Editor");
addPlistDictionaryKey (*dict2, "CFBundleTypeIconFile", "Icon");
addPlistDictionaryKey (*dict2, "NSPersistentStoreTypeKey", "XML");
}
arrayTag->createNewChildElement ("string")->addTextElement (ex);
}
}
if (fileSharingEnabled && type != ProjectType::Target::AudioUnitv3PlugIn)
addPlistDictionaryKey (*dict, "UIFileSharingEnabled", true);
if (documentBrowserEnabled)
addPlistDictionaryKey (*dict, "UISupportsDocumentBrowser", true);
if (iOS)
{
if (type != ProjectType::Target::AudioUnitv3PlugIn)
{
if (statusBarHidden)
addPlistDictionaryKey (*dict, "UIStatusBarHidden", true);
addPlistDictionaryKey (*dict, "UIRequiresFullScreen", requiresFullScreen);
addIosScreenOrientations (*dict);
addIosBackgroundModes (*dict);
}
if (type == ProjectType::Target::StandalonePlugIn && enableIAA)
{
XmlElement audioComponentsPlistKey ("key");
audioComponentsPlistKey.addTextElement ("AudioComponents");
dict->addChildElement (new XmlElement (audioComponentsPlistKey));
XmlElement audioComponentsPlistEntry ("array");
auto* audioComponentsDict = audioComponentsPlistEntry.createNewChildElement ("dict");
addPlistDictionaryKey (*audioComponentsDict, "name", IAAPluginName);
addPlistDictionaryKey (*audioComponentsDict, "manufacturer", pluginManufacturerCode.substring (0, 4));
addPlistDictionaryKey (*audioComponentsDict, "type", IAATypeCode);
addPlistDictionaryKey (*audioComponentsDict, "subtype", pluginCode.substring (0, 4));
addPlistDictionaryKey (*audioComponentsDict, "version", getVersionAsHexInteger (marketingVersion));
dict->addChildElement (new XmlElement (audioComponentsPlistEntry));
}
}
const auto extraOptions = [&]() -> Array<XmlElement>
{
if (type == ProjectType::Target::Type::AudioUnitPlugIn)
return createExtraAudioUnitTargetPlistOptions();
if (type == ProjectType::Target::Type::AudioUnitv3PlugIn)
return createExtraAudioUnitV3TargetPlistOptions();
return {};
}();
for (auto& e : extraOptions)
dict->addChildElement (new XmlElement (e));
return plist;
}
void PlistOptions::addIosScreenOrientations (XmlElement& dict) const
{
addArrayToPlist (dict, "UISupportedInterfaceOrientations", iPhoneScreenOrientations);
if (iPadScreenOrientations != iPhoneScreenOrientations)
addArrayToPlist (dict, "UISupportedInterfaceOrientations~ipad", iPadScreenOrientations);
}
void PlistOptions::addIosBackgroundModes (XmlElement& dict) const
{
StringArray iosBackgroundModes;
if (backgroundAudioEnabled) iosBackgroundModes.add ("audio");
if (backgroundBleEnabled) iosBackgroundModes.add ("bluetooth-central");
if (pushNotificationsEnabled) iosBackgroundModes.add ("remote-notification");
addArrayToPlist (dict, "UIBackgroundModes", iosBackgroundModes);
}
Array<XmlElement> PlistOptions::createExtraAudioUnitTargetPlistOptions() const
{
XmlElement plistKey ("key");
plistKey.addTextElement ("AudioComponents");
XmlElement plistEntry ("array");
auto* dict = plistEntry.createNewChildElement ("dict");
auto truncatedCode = pluginManufacturerCode.substring (0, 4);
auto pluginSubType = pluginCode.substring (0, 4);
if (truncatedCode.toLowerCase() == truncatedCode)
{
throw SaveError ("AudioUnit plugin code identifiers invalid!\n\n"
"You have used only lower case letters in your AU plugin manufacturer identifier. "
"You must have at least one uppercase letter in your AU plugin manufacturer "
"identifier code.");
}
addPlistDictionaryKey (*dict, "name", pluginManufacturer + ": " + pluginName);
addPlistDictionaryKey (*dict, "description", pluginDescription);
addPlistDictionaryKey (*dict, "factoryFunction", pluginAUExportPrefix + "Factory");
addPlistDictionaryKey (*dict, "manufacturer", truncatedCode);
addPlistDictionaryKey (*dict, "type", auMainType.removeCharacters ("'"));
addPlistDictionaryKey (*dict, "subtype", pluginSubType);
addPlistDictionaryKey (*dict, "version", getAUVersionAsHexInteger (*this));
if (isAuSandboxSafe)
{
addPlistDictionaryKey (*dict, "sandboxSafe", true);
}
else if (! suppressResourceUsage)
{
dict->createNewChildElement ("key")->addTextElement ("resourceUsage");
auto* resourceUsageDict = dict->createNewChildElement ("dict");
addPlistDictionaryKey (*resourceUsageDict, "network.client", true);
addPlistDictionaryKey (*resourceUsageDict, "temporary-exception.files.all.read-write", true);
}
return { plistKey, plistEntry };
}
Array<XmlElement> PlistOptions::createExtraAudioUnitV3TargetPlistOptions() const
{
XmlElement plistKey ("key");
plistKey.addTextElement ("NSExtension");
XmlElement plistEntry ("dict");
addPlistDictionaryKey (plistEntry, "NSExtensionPrincipalClass", pluginAUExportPrefix + "FactoryAUv3");
addPlistDictionaryKey (plistEntry, "NSExtensionPointIdentifier", "com.apple.AudioUnit-UI");
plistEntry.createNewChildElement ("key")->addTextElement ("NSExtensionAttributes");
auto* dict = plistEntry.createNewChildElement ("dict");
dict->createNewChildElement ("key")->addTextElement ("AudioComponents");
auto* componentArray = dict->createNewChildElement ("array");
auto* componentDict = componentArray->createNewChildElement ("dict");
addPlistDictionaryKey (*componentDict, "name", pluginManufacturer + ": " + pluginName);
addPlistDictionaryKey (*componentDict, "description", pluginDescription);
addPlistDictionaryKey (*componentDict, "factoryFunction", pluginAUExportPrefix + "FactoryAUv3");
addPlistDictionaryKey (*componentDict, "manufacturer", pluginManufacturerCode.substring (0, 4));
addPlistDictionaryKey (*componentDict, "type", auMainType.removeCharacters ("'"));
addPlistDictionaryKey (*componentDict, "subtype", pluginCode.substring (0, 4));
addPlistDictionaryKey (*componentDict, "version", getAUVersionAsHexInteger (*this));
addPlistDictionaryKey (*componentDict, "sandboxSafe", true);
componentDict->createNewChildElement ("key")->addTextElement ("tags");
auto* tagsArray = componentDict->createNewChildElement ("array");
tagsArray->createNewChildElement ("string")
->addTextElement (isPluginSynth ? "Synth" : "Effects");
if (auMainType.removeCharacters ("'") == "aumi")
tagsArray->createNewChildElement ("string")->addTextElement ("MIDI");
return { plistKey, plistEntry };
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
static XmlElement* getKeyWithName (XmlElement& xml, const String& key)
{
for (auto* element : xml.getChildWithTagNameIterator ("key"))
if (element->getAllSubText().trim().equalsIgnoreCase (key))
return element;
return nullptr;
}
static bool keyFoundAndNotSequentialDuplicate (XmlElement& xml, const String& key)
{
if (auto* element = getKeyWithName (xml, key))
{
if (element->getNextElement() != nullptr && element->getNextElement()->hasTagName ("key"))
{
// found broken plist format (sequential duplicate), fix by removing
xml.removeChildElement (element, true);
return false;
}
// key found (not sequential duplicate)
return true;
}
// key not found
return false;
}
static bool addKeyIfNotFound (XmlElement& xml, const String& key)
{
if (! keyFoundAndNotSequentialDuplicate (xml, key))
{
xml.createNewChildElement ("key")->addTextElement (key);
return true;
}
return false;
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const String& value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement ("string")->addTextElement (value);
}
template <size_t N>
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const char (&value) [N])
{
addPlistDictionaryKey (xml, key, String { value });
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, const bool value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement (value ? "true" : "false");
}
static void addPlistDictionaryKey (XmlElement& xml, const String& key, int value)
{
if (addKeyIfNotFound (xml, key))
xml.createNewChildElement ("integer")->addTextElement (String (value));
}
static void addArrayToPlist (XmlElement& dict, String arrayKey, const StringArray& arrayElements)
{
if (getKeyWithName (dict, arrayKey) != nullptr)
return;
dict.createNewChildElement ("key")->addTextElement (arrayKey);
auto* plistStringArray = dict.createNewChildElement ("array");
for (auto& e : arrayElements)
plistStringArray->createNewChildElement ("string")->addTextElement (e);
}
static int getAUVersionAsHexInteger (const PlistOptions& opts)
{
const auto segments = getVersionSegments (opts.marketingVersion);
const StringArray trimmed (segments.strings.getRawDataPointer(), jmin (segments.size(), 3));
return getVersionAsHexIntegerFromParts (trimmed);
}
//==============================================================================
void PlistOptions::write (const File& infoPlistFile) const
{
writeStreamToFile (infoPlistFile, [&] (MemoryOutputStream& mo) { write (mo); });
}
void PlistOptions::write (MemoryOutputStream& mo) const
{
XmlElement::TextFormat format;
format.dtd = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
createXML()->writeTo (mo, format);
}
std::unique_ptr<XmlElement> PlistOptions::createXML() const
{
auto plist = parseXML (plistToMerge);
if (plist == nullptr || ! plist->hasTagName ("plist"))
plist.reset (new XmlElement ("plist"));
auto* dict = plist->getChildByName ("dict");
if (dict == nullptr)
dict = plist->createNewChildElement ("dict");
if (microphonePermissionEnabled)
addPlistDictionaryKey (*dict, "NSMicrophoneUsageDescription", microphonePermissionText);
if (cameraPermissionEnabled)
addPlistDictionaryKey (*dict, "NSCameraUsageDescription", cameraPermissionText);
if (bluetoothPermissionEnabled)
addPlistDictionaryKey (*dict, "NSBluetoothAlwaysUsageDescription", bluetoothPermissionText);
if (iOS)
{
if (bluetoothPermissionEnabled)
addPlistDictionaryKey (*dict, "NSBluetoothPeripheralUsageDescription", bluetoothPermissionText); // needed for pre iOS 13.0
addPlistDictionaryKey (*dict, "LSRequiresIPhoneOS", true);
addPlistDictionaryKey (*dict, "UIViewControllerBasedStatusBarAppearance", true);
if (shouldAddStoryboardToProject)
addPlistDictionaryKey (*dict, "UILaunchStoryboardName", storyboardName);
}
else
{
if (sendAppleEventsPermissionEnabled)
addPlistDictionaryKey (*dict, "NSAppleEventsUsageDescription", sendAppleEventsPermissionText);
}
addPlistDictionaryKey (*dict, "CFBundleExecutable", executableName);
if (! iOS) // (NB: on iOS this causes error ITMS-90032 during publishing)
addPlistDictionaryKey (*dict, "CFBundleIconFile", iconFile.exists() ? iconFile.getFileName() : String());
addPlistDictionaryKey (*dict, "CFBundleIdentifier", bundleIdentifier);
addPlistDictionaryKey (*dict, "CFBundleName", projectName);
// needed by NSExtension on iOS
addPlistDictionaryKey (*dict, "CFBundleDisplayName", projectName);
addPlistDictionaryKey (*dict, "CFBundlePackageType", getXcodePackageType (type));
addPlistDictionaryKey (*dict, "CFBundleSignature", getXcodeBundleSignature (type));
addPlistDictionaryKey (*dict, "CFBundleShortVersionString", marketingVersion);
addPlistDictionaryKey (*dict, "CFBundleVersion", currentProjectVersion);
addPlistDictionaryKey (*dict, "NSHumanReadableCopyright", companyCopyright);
addPlistDictionaryKey (*dict, "NSHighResolutionCapable", true);
if (applicationCategory.isNotEmpty())
addPlistDictionaryKey (*dict, "LSApplicationCategoryType", applicationCategory);
auto replacedDocExtensions = StringArray::fromTokens (replacePreprocessorDefs (allPreprocessorDefs,
documentExtensions), ",", {});
replacedDocExtensions.trim();
replacedDocExtensions.removeEmptyStrings (true);
if (! replacedDocExtensions.isEmpty() && type != ProjectType::Target::AudioUnitv3PlugIn)
{
dict->createNewChildElement ("key")->addTextElement ("CFBundleDocumentTypes");
auto* dict2 = dict->createNewChildElement ("array")->createNewChildElement ("dict");
XmlElement* arrayTag = nullptr;
for (auto ex : replacedDocExtensions)
{
if (ex.startsWithChar ('.'))
ex = ex.substring (1);
if (arrayTag == nullptr)
{
dict2->createNewChildElement ("key")->addTextElement ("CFBundleTypeExtensions");
arrayTag = dict2->createNewChildElement ("array");
addPlistDictionaryKey (*dict2, "CFBundleTypeName", ex);
addPlistDictionaryKey (*dict2, "CFBundleTypeRole", "Editor");
addPlistDictionaryKey (*dict2, "CFBundleTypeIconFile", "Icon");
addPlistDictionaryKey (*dict2, "NSPersistentStoreTypeKey", "XML");
addPlistDictionaryKey (*dict2, "LSHandlerRank", "Default");
}
arrayTag->createNewChildElement ("string")->addTextElement (ex);
}
}
if (fileSharingEnabled && type != ProjectType::Target::AudioUnitv3PlugIn)
addPlistDictionaryKey (*dict, "UIFileSharingEnabled", true);
if (documentBrowserEnabled)
addPlistDictionaryKey (*dict, "UISupportsDocumentBrowser", true);
if (iOS)
{
if (type != ProjectType::Target::AudioUnitv3PlugIn)
{
if (statusBarHidden)
addPlistDictionaryKey (*dict, "UIStatusBarHidden", true);
addPlistDictionaryKey (*dict, "UIRequiresFullScreen", requiresFullScreen);
addIosScreenOrientations (*dict);
addIosBackgroundModes (*dict);
}
if (type == ProjectType::Target::StandalonePlugIn && enableIAA)
{
XmlElement audioComponentsPlistKey ("key");
audioComponentsPlistKey.addTextElement ("AudioComponents");
dict->addChildElement (new XmlElement (audioComponentsPlistKey));
XmlElement audioComponentsPlistEntry ("array");
auto* audioComponentsDict = audioComponentsPlistEntry.createNewChildElement ("dict");
addPlistDictionaryKey (*audioComponentsDict, "name", IAAPluginName);
addPlistDictionaryKey (*audioComponentsDict, "manufacturer", pluginManufacturerCode.substring (0, 4));
addPlistDictionaryKey (*audioComponentsDict, "type", IAATypeCode);
addPlistDictionaryKey (*audioComponentsDict, "subtype", pluginCode.substring (0, 4));
addPlistDictionaryKey (*audioComponentsDict, "version", getVersionAsHexInteger (marketingVersion));
dict->addChildElement (new XmlElement (audioComponentsPlistEntry));
}
}
const auto extraOptions = [&]() -> Array<XmlElement>
{
if (type == ProjectType::Target::Type::AudioUnitPlugIn)
return createExtraAudioUnitTargetPlistOptions();
if (type == ProjectType::Target::Type::AudioUnitv3PlugIn)
return createExtraAudioUnitV3TargetPlistOptions();
return {};
}();
for (auto& e : extraOptions)
dict->addChildElement (new XmlElement (e));
return plist;
}
void PlistOptions::addIosScreenOrientations (XmlElement& dict) const
{
addArrayToPlist (dict, "UISupportedInterfaceOrientations", iPhoneScreenOrientations);
if (iPadScreenOrientations != iPhoneScreenOrientations)
addArrayToPlist (dict, "UISupportedInterfaceOrientations~ipad", iPadScreenOrientations);
}
void PlistOptions::addIosBackgroundModes (XmlElement& dict) const
{
StringArray iosBackgroundModes;
if (backgroundAudioEnabled) iosBackgroundModes.add ("audio");
if (backgroundBleEnabled) iosBackgroundModes.add ("bluetooth-central");
if (pushNotificationsEnabled) iosBackgroundModes.add ("remote-notification");
addArrayToPlist (dict, "UIBackgroundModes", iosBackgroundModes);
}
Array<XmlElement> PlistOptions::createExtraAudioUnitTargetPlistOptions() const
{
XmlElement plistKey ("key");
plistKey.addTextElement ("AudioComponents");
XmlElement plistEntry ("array");
auto* dict = plistEntry.createNewChildElement ("dict");
auto truncatedCode = pluginManufacturerCode.substring (0, 4);
auto pluginSubType = pluginCode.substring (0, 4);
if (truncatedCode.toLowerCase() == truncatedCode)
{
throw SaveError ("AudioUnit plugin code identifiers invalid!\n\n"
"You have used only lower case letters in your AU plugin manufacturer identifier. "
"You must have at least one uppercase letter in your AU plugin manufacturer "
"identifier code.");
}
addPlistDictionaryKey (*dict, "name", pluginManufacturer + ": " + pluginName);
addPlistDictionaryKey (*dict, "description", pluginDescription);
addPlistDictionaryKey (*dict, "factoryFunction", pluginAUExportPrefix + "Factory");
addPlistDictionaryKey (*dict, "manufacturer", truncatedCode);
addPlistDictionaryKey (*dict, "type", auMainType.removeCharacters ("'"));
addPlistDictionaryKey (*dict, "subtype", pluginSubType);
addPlistDictionaryKey (*dict, "version", getAUVersionAsHexInteger (*this));
if (isAuSandboxSafe)
{
addPlistDictionaryKey (*dict, "sandboxSafe", true);
}
else if (! suppressResourceUsage)
{
dict->createNewChildElement ("key")->addTextElement ("resourceUsage");
auto* resourceUsageDict = dict->createNewChildElement ("dict");
addPlistDictionaryKey (*resourceUsageDict, "network.client", true);
addPlistDictionaryKey (*resourceUsageDict, "temporary-exception.files.all.read-write", true);
}
if (isPluginARAEffect)
{
dict->createNewChildElement ("key")->addTextElement ("tags");
auto* tagsArray = dict->createNewChildElement ("array");
tagsArray->createNewChildElement ("string")->addTextElement ("ARA");
}
return { plistKey, plistEntry };
}
Array<XmlElement> PlistOptions::createExtraAudioUnitV3TargetPlistOptions() const
{
XmlElement plistKey ("key");
plistKey.addTextElement ("NSExtension");
XmlElement plistEntry ("dict");
addPlistDictionaryKey (plistEntry, "NSExtensionPrincipalClass", pluginAUExportPrefix + "FactoryAUv3");
addPlistDictionaryKey (plistEntry, "NSExtensionPointIdentifier", "com.apple.AudioUnit-UI");
plistEntry.createNewChildElement ("key")->addTextElement ("NSExtensionAttributes");
auto* dict = plistEntry.createNewChildElement ("dict");
dict->createNewChildElement ("key")->addTextElement ("AudioComponents");
auto* componentArray = dict->createNewChildElement ("array");
auto* componentDict = componentArray->createNewChildElement ("dict");
addPlistDictionaryKey (*componentDict, "name", pluginManufacturer + ": " + pluginName);
addPlistDictionaryKey (*componentDict, "description", pluginDescription);
addPlistDictionaryKey (*componentDict, "factoryFunction", pluginAUExportPrefix + "FactoryAUv3");
addPlistDictionaryKey (*componentDict, "manufacturer", pluginManufacturerCode.substring (0, 4));
addPlistDictionaryKey (*componentDict, "type", auMainType.removeCharacters ("'"));
addPlistDictionaryKey (*componentDict, "subtype", pluginCode.substring (0, 4));
addPlistDictionaryKey (*componentDict, "version", getAUVersionAsHexInteger (*this));
addPlistDictionaryKey (*componentDict, "sandboxSafe", true);
componentDict->createNewChildElement ("key")->addTextElement ("tags");
auto* tagsArray = componentDict->createNewChildElement ("array");
tagsArray->createNewChildElement ("string")
->addTextElement (isPluginSynth ? "Synth" : "Effects");
if (auMainType.removeCharacters ("'") == "aumi")
tagsArray->createNewChildElement ("string")->addTextElement ("MIDI");
return { plistKey, plistEntry };
}
}
}

View File

@ -1,106 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class PlistOptions final
{
public:
void write (const File& infoPlistFile) const;
//==============================================================================
ProjectType::Target::Type type = ProjectType::Target::Type::GUIApp;
String executableName;
String bundleIdentifier;
String plistToMerge;
bool iOS = false;
bool microphonePermissionEnabled = false;
String microphonePermissionText;
bool cameraPermissionEnabled = false;
String cameraPermissionText;
bool bluetoothPermissionEnabled = false;
String bluetoothPermissionText;
bool sendAppleEventsPermissionEnabled = false;
String sendAppleEventsPermissionText;
bool shouldAddStoryboardToProject = false;
String storyboardName;
File iconFile;
String projectName;
String marketingVersion;
String currentProjectVersion;
String companyCopyright;
String applicationCategory;
StringPairArray allPreprocessorDefs;
String documentExtensions;
bool fileSharingEnabled = false;
bool documentBrowserEnabled = false;
bool statusBarHidden = false;
bool requiresFullScreen = false;
bool backgroundAudioEnabled = false;
bool backgroundBleEnabled = false;
bool pushNotificationsEnabled = false;
bool enableIAA = false;
String IAAPluginName;
String pluginManufacturerCode;
String IAATypeCode;
String pluginCode;
StringArray iPhoneScreenOrientations;
StringArray iPadScreenOrientations;
String pluginName;
String pluginManufacturer;
String pluginDescription;
String pluginAUExportPrefix;
String auMainType;
bool isAuSandboxSafe = false;
bool isPluginSynth = false;
bool suppressResourceUsage = false;
private:
void write (MemoryOutputStream&) const;
std::unique_ptr<XmlElement> createXML() const;
void addIosScreenOrientations (XmlElement&) const;
void addIosBackgroundModes (XmlElement&) const;
Array<XmlElement> createExtraAudioUnitTargetPlistOptions() const;
Array<XmlElement> createExtraAudioUnitV3TargetPlistOptions() const;
};
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class PlistOptions final
{
public:
void write (const File& infoPlistFile) const;
//==============================================================================
ProjectType::Target::Type type = ProjectType::Target::Type::GUIApp;
String executableName;
String bundleIdentifier;
String plistToMerge;
bool iOS = false;
bool microphonePermissionEnabled = false;
String microphonePermissionText;
bool cameraPermissionEnabled = false;
String cameraPermissionText;
bool bluetoothPermissionEnabled = false;
String bluetoothPermissionText;
bool sendAppleEventsPermissionEnabled = false;
String sendAppleEventsPermissionText;
bool shouldAddStoryboardToProject = false;
String storyboardName;
File iconFile;
String projectName;
String marketingVersion;
String currentProjectVersion;
String companyCopyright;
String applicationCategory;
StringPairArray allPreprocessorDefs;
String documentExtensions;
bool fileSharingEnabled = false;
bool documentBrowserEnabled = false;
bool statusBarHidden = false;
bool requiresFullScreen = false;
bool backgroundAudioEnabled = false;
bool backgroundBleEnabled = false;
bool pushNotificationsEnabled = false;
bool enableIAA = false;
String IAAPluginName;
String pluginManufacturerCode;
String IAATypeCode;
String pluginCode;
StringArray iPhoneScreenOrientations;
StringArray iPadScreenOrientations;
String pluginName;
String pluginManufacturer;
String pluginDescription;
String pluginAUExportPrefix;
String auMainType;
bool isAuSandboxSafe = false;
bool isPluginSynth = false;
bool suppressResourceUsage = false;
bool isPluginARAEffect = false;
private:
void write (MemoryOutputStream&) const;
std::unique_ptr<XmlElement> createXML() const;
void addIosScreenOrientations (XmlElement&) const;
void addIosBackgroundModes (XmlElement&) const;
Array<XmlElement> createExtraAudioUnitTargetPlistOptions() const;
Array<XmlElement> createExtraAudioUnitV3TargetPlistOptions() const;
};
}
}

View File

@ -1,275 +1,319 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
class ProjectType
{
public:
//==============================================================================
virtual ~ProjectType() { getAllTypes().removeFirstMatchingValue (this); }
const String& getType() const noexcept { return type; }
const String& getDescription() const noexcept { return desc; }
//==============================================================================
static Array<ProjectType*> getAllTypes();
static const ProjectType* findType (const String& typeCode)
{
const auto& types = getAllTypes();
for (auto i = types.size(); --i >= 0;)
if (types.getUnchecked(i)->getType() == typeCode)
return types.getUnchecked(i);
jassertfalse;
return nullptr;
}
//==============================================================================
virtual bool isStaticLibrary() const { return false; }
virtual bool isDynamicLibrary() const { return false; }
virtual bool isGUIApplication() const { return false; }
virtual bool isCommandLineApp() const { return false; }
virtual bool isAudioPlugin() const { return false; }
//==============================================================================
struct Target
{
enum Type
{
GUIApp = 0,
ConsoleApp = 1,
StaticLibrary = 2,
DynamicLibrary = 3,
VSTPlugIn = 10,
VST3PlugIn = 11,
AAXPlugIn = 12,
RTASPlugIn = 13,
AudioUnitPlugIn = 14,
AudioUnitv3PlugIn = 15,
StandalonePlugIn = 16,
UnityPlugIn = 17,
SharedCodeTarget = 20, // internal
AggregateTarget = 21,
unspecified = 30
};
enum TargetFileType
{
executable = 0,
staticLibrary = 1,
sharedLibraryOrDLL = 2,
pluginBundle = 3,
macOSAppex = 4,
unknown = 5
};
//==============================================================================
explicit Target (Type targetType) : type (targetType) {}
const char* getName() const noexcept
{
switch (type)
{
case GUIApp: return "App";
case ConsoleApp: return "ConsoleApp";
case StaticLibrary: return "Static Library";
case DynamicLibrary: return "Dynamic Library";
case VSTPlugIn: return "VST";
case VST3PlugIn: return "VST3";
case AudioUnitPlugIn: return "AU";
case StandalonePlugIn: return "Standalone Plugin";
case AudioUnitv3PlugIn: return "AUv3 AppExtension";
case AAXPlugIn: return "AAX";
case RTASPlugIn: return "RTAS";
case UnityPlugIn: return "Unity Plugin";
case SharedCodeTarget: return "Shared Code";
case AggregateTarget: return "All";
case unspecified:
default: break;
}
return "undefined";
}
static Type typeFromName (const String& name)
{
if (name == "App") return Type::GUIApp;
if (name == "ConsoleApp") return Type::ConsoleApp;
if (name == "Static Library") return Type::StaticLibrary;
if (name == "Dynamic Library") return Type::DynamicLibrary;
if (name == "VST") return Type::VSTPlugIn;
if (name == "VST3") return Type::VST3PlugIn;
if (name == "AU") return Type::AudioUnitPlugIn;
if (name == "Standalone Plugin") return Type::StandalonePlugIn;
if (name == "AUv3 AppExtension") return Type::AudioUnitv3PlugIn;
if (name == "AAX") return Type::AAXPlugIn;
if (name == "RTAS") return Type::RTASPlugIn;
if (name == "Unity Plugin") return Type::UnityPlugIn;
if (name == "Shared Code") return Type::SharedCodeTarget;
if (name == "All") return Type::AggregateTarget;
jassertfalse;
return Type::ConsoleApp;
}
TargetFileType getTargetFileType() const noexcept
{
switch (type)
{
case GUIApp: return executable;
case ConsoleApp: return executable;
case StaticLibrary: return staticLibrary;
case DynamicLibrary: return sharedLibraryOrDLL;
case VSTPlugIn: return pluginBundle;
case VST3PlugIn: return pluginBundle;
case AudioUnitPlugIn: return pluginBundle;
case StandalonePlugIn: return executable;
case AudioUnitv3PlugIn: return macOSAppex;
case AAXPlugIn: return pluginBundle;
case RTASPlugIn: return pluginBundle;
case UnityPlugIn: return pluginBundle;
case SharedCodeTarget: return staticLibrary;
case AggregateTarget:
case unspecified:
default: break;
}
return unknown;
}
const Type type;
private:
//==============================================================================
Target& operator= (const Target&) = delete;
};
virtual bool supportsTargetType (Target::Type /*targetType*/) const { return false; }
protected:
ProjectType (const String& t, const String& d)
: type (t), desc (d)
{}
private:
const String type, desc;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectType)
};
//==============================================================================
struct ProjectType_GUIApp : public ProjectType
{
ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {}
static const char* getTypeName() noexcept { return "guiapp"; }
bool isGUIApplication() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::GUIApp); }
};
struct ProjectType_ConsoleApp : public ProjectType
{
ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {}
static const char* getTypeName() noexcept { return "consoleapp"; }
bool isCommandLineApp() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::ConsoleApp); }
};
struct ProjectType_StaticLibrary : public ProjectType
{
ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {}
static const char* getTypeName() noexcept { return "library"; }
bool isStaticLibrary() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::StaticLibrary); }
};
struct ProjectType_DLL : public ProjectType
{
ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {}
static const char* getTypeName() noexcept { return "dll"; }
bool isDynamicLibrary() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::DynamicLibrary); }
};
struct ProjectType_AudioPlugin : public ProjectType
{
ProjectType_AudioPlugin() : ProjectType (getTypeName(), "Audio Plug-in") {}
static const char* getTypeName() noexcept { return "audioplug"; }
bool isAudioPlugin() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override
{
switch (targetType)
{
case Target::VSTPlugIn:
case Target::VST3PlugIn:
case Target::AAXPlugIn:
case Target::RTASPlugIn:
case Target::AudioUnitPlugIn:
case Target::AudioUnitv3PlugIn:
case Target::StandalonePlugIn:
case Target::UnityPlugIn:
case Target::SharedCodeTarget:
case Target::AggregateTarget:
return true;
case Target::GUIApp:
case Target::ConsoleApp:
case Target::StaticLibrary:
case Target::DynamicLibrary:
case Target::unspecified:
default:
break;
}
return false;
}
};
//==============================================================================
inline Array<ProjectType*> ProjectType::getAllTypes()
{
static ProjectType_GUIApp guiApp;
static ProjectType_ConsoleApp consoleApp;
static ProjectType_StaticLibrary staticLib;
static ProjectType_DLL dll;
static ProjectType_AudioPlugin plugin;
return Array<ProjectType*>(&guiApp, &consoleApp, &staticLib, &dll, &plugin);
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
class ProjectType
{
public:
//==============================================================================
virtual ~ProjectType() { getAllTypes().removeFirstMatchingValue (this); }
const String& getType() const noexcept { return type; }
const String& getDescription() const noexcept { return desc; }
//==============================================================================
static Array<ProjectType*> getAllTypes();
static const ProjectType* findType (const String& typeCode)
{
const auto& types = getAllTypes();
for (auto i = types.size(); --i >= 0;)
if (types.getUnchecked(i)->getType() == typeCode)
return types.getUnchecked(i);
jassertfalse;
return nullptr;
}
//==============================================================================
virtual bool isStaticLibrary() const { return false; }
virtual bool isDynamicLibrary() const { return false; }
virtual bool isGUIApplication() const { return false; }
virtual bool isCommandLineApp() const { return false; }
virtual bool isAudioPlugin() const { return false; }
virtual bool isARAAudioPlugin() const { return false; }
//==============================================================================
struct Target
{
enum Type
{
GUIApp = 0,
ConsoleApp = 1,
StaticLibrary = 2,
DynamicLibrary = 3,
VSTPlugIn = 10,
VST3PlugIn = 11,
AAXPlugIn = 12,
AudioUnitPlugIn = 14,
AudioUnitv3PlugIn = 15,
StandalonePlugIn = 16,
UnityPlugIn = 17,
LV2PlugIn = 18,
SharedCodeTarget = 20, // internal
AggregateTarget = 21,
LV2TurtleProgram = 25, // internal
unspecified = 30
};
enum TargetFileType
{
executable = 0,
staticLibrary = 1,
sharedLibraryOrDLL = 2,
pluginBundle = 3,
macOSAppex = 4,
unknown = 5
};
//==============================================================================
explicit Target (Type targetType) : type (targetType) {}
const char* getName() const noexcept
{
switch (type)
{
case GUIApp: return "App";
case ConsoleApp: return "ConsoleApp";
case StaticLibrary: return "Static Library";
case DynamicLibrary: return "Dynamic Library";
case VSTPlugIn: return "VST";
case VST3PlugIn: return "VST3";
case AudioUnitPlugIn: return "AU";
case StandalonePlugIn: return "Standalone Plugin";
case AudioUnitv3PlugIn: return "AUv3 AppExtension";
case AAXPlugIn: return "AAX";
case UnityPlugIn: return "Unity Plugin";
case LV2PlugIn: return "LV2 Plugin";
case SharedCodeTarget: return "Shared Code";
case AggregateTarget: return "All";
case LV2TurtleProgram: return "LV2 Manifest Helper";
case unspecified: break;
}
return "undefined";
}
static Type typeFromName (const String& name)
{
if (name == "App") return Type::GUIApp;
if (name == "ConsoleApp") return Type::ConsoleApp;
if (name == "Static Library") return Type::StaticLibrary;
if (name == "Dynamic Library") return Type::DynamicLibrary;
if (name == "VST") return Type::VSTPlugIn;
if (name == "VST3") return Type::VST3PlugIn;
if (name == "AU") return Type::AudioUnitPlugIn;
if (name == "Standalone Plugin") return Type::StandalonePlugIn;
if (name == "AUv3 AppExtension") return Type::AudioUnitv3PlugIn;
if (name == "AAX") return Type::AAXPlugIn;
if (name == "Unity Plugin") return Type::UnityPlugIn;
if (name == "LV2 Plugin") return Type::LV2PlugIn;
if (name == "Shared Code") return Type::SharedCodeTarget;
if (name == "All") return Type::AggregateTarget;
if (name == "LV2 Manifest Helper") return Type::LV2TurtleProgram;
jassertfalse;
return Type::ConsoleApp;
}
TargetFileType getTargetFileType() const noexcept
{
switch (type)
{
case GUIApp: return executable;
case ConsoleApp: return executable;
case StaticLibrary: return staticLibrary;
case DynamicLibrary: return sharedLibraryOrDLL;
case VSTPlugIn: return pluginBundle;
case VST3PlugIn: return pluginBundle;
case AudioUnitPlugIn: return pluginBundle;
case StandalonePlugIn: return executable;
case AudioUnitv3PlugIn: return macOSAppex;
case AAXPlugIn: return pluginBundle;
case UnityPlugIn: return pluginBundle;
case LV2PlugIn: return pluginBundle;
case SharedCodeTarget: return staticLibrary;
case LV2TurtleProgram: return executable;
case AggregateTarget:
case unspecified:
break;
}
return unknown;
}
const Type type;
private:
//==============================================================================
Target& operator= (const Target&) = delete;
};
virtual bool supportsTargetType (Target::Type /*targetType*/) const { return false; }
protected:
ProjectType (const String& t, const String& d)
: type (t), desc (d)
{}
private:
const String type, desc;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectType)
};
//==============================================================================
struct ProjectType_GUIApp : public ProjectType
{
ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {}
static const char* getTypeName() noexcept { return "guiapp"; }
bool isGUIApplication() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::GUIApp); }
};
struct ProjectType_ConsoleApp : public ProjectType
{
ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {}
static const char* getTypeName() noexcept { return "consoleapp"; }
bool isCommandLineApp() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::ConsoleApp); }
};
struct ProjectType_StaticLibrary : public ProjectType
{
ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {}
static const char* getTypeName() noexcept { return "library"; }
bool isStaticLibrary() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::StaticLibrary); }
};
struct ProjectType_DLL : public ProjectType
{
ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {}
static const char* getTypeName() noexcept { return "dll"; }
bool isDynamicLibrary() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::DynamicLibrary); }
};
struct ProjectType_AudioPlugin : public ProjectType
{
ProjectType_AudioPlugin() : ProjectType (getTypeName(), "Audio Plug-in") {}
static const char* getTypeName() noexcept { return "audioplug"; }
bool isAudioPlugin() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override
{
switch (targetType)
{
case Target::VSTPlugIn:
case Target::VST3PlugIn:
case Target::AAXPlugIn:
case Target::AudioUnitPlugIn:
case Target::AudioUnitv3PlugIn:
case Target::StandalonePlugIn:
case Target::UnityPlugIn:
case Target::LV2PlugIn:
case Target::LV2TurtleProgram:
case Target::SharedCodeTarget:
case Target::AggregateTarget:
return true;
case Target::GUIApp:
case Target::ConsoleApp:
case Target::StaticLibrary:
case Target::DynamicLibrary:
case Target::unspecified:
break;
}
return false;
}
};
struct ProjectType_ARAAudioPlugin : public ProjectType
{
ProjectType_ARAAudioPlugin() : ProjectType (getTypeName(), "ARA Audio Plug-in") {}
static const char* getTypeName() noexcept { return "araaudioplug"; }
bool isAudioPlugin() const override { return true; }
bool isARAAudioPlugin() const override { return true; }
bool supportsTargetType (Target::Type targetType) const override
{
switch (targetType)
{
case Target::VSTPlugIn:
case Target::VST3PlugIn:
case Target::AAXPlugIn:
case Target::AudioUnitPlugIn:
case Target::AudioUnitv3PlugIn:
case Target::StandalonePlugIn:
case Target::UnityPlugIn:
case Target::SharedCodeTarget:
case Target::AggregateTarget:
return true;
case Target::GUIApp:
case Target::ConsoleApp:
case Target::StaticLibrary:
case Target::DynamicLibrary:
case Target::unspecified:
case Target::LV2PlugIn:
case Target::LV2TurtleProgram:
break;
}
return false;
}
};
//==============================================================================
inline Array<ProjectType*> ProjectType::getAllTypes()
{
static ProjectType_GUIApp guiApp;
static ProjectType_ConsoleApp consoleApp;
static ProjectType_StaticLibrary staticLib;
static ProjectType_DLL dll;
static ProjectType_AudioPlugin plugin;
static ProjectType_ARAAudioPlugin araplugin;
return Array<ProjectType*>(&guiApp, &consoleApp, &staticLib, &dll, &plugin, &araplugin);
}
}
}

View File

@ -1,129 +1,129 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
/** Manipulates a cross-platform partial file path. (Needed because File is designed
for absolute paths on the active OS)
*/
class RelativePath
{
public:
//==============================================================================
enum RootFolder
{
unknown,
projectFolder,
buildTargetFolder
};
//==============================================================================
RelativePath()
: root (unknown)
{}
RelativePath (const String& relPath, const RootFolder rootType)
: path (unixStylePath (relPath)), root (rootType)
{}
RelativePath (const File& file, const File& rootFolder, const RootFolder rootType)
: path (unixStylePath (getRelativePathFrom (file, rootFolder))), root (rootType)
{}
RootFolder getRoot() const { return root; }
String toUnixStyle() const { return unixStylePath (path); }
String toWindowsStyle() const { return windowsStylePath (path); }
String getFileName() const { return getFakeFile().getFileName(); }
String getFileNameWithoutExtension() const { return getFakeFile().getFileNameWithoutExtension(); }
String getFileExtension() const { return getFakeFile().getFileExtension(); }
bool hasFileExtension (StringRef extension) const { return getFakeFile().hasFileExtension (extension); }
bool isAbsolute() const { return isAbsolutePath (path); }
RelativePath withFileExtension (const String& extension) const
{
return RelativePath (path.upToLastOccurrenceOf (".", ! extension.startsWithChar ('.'), false) + extension, root);
}
RelativePath getParentDirectory() const
{
String p (path);
if (path.endsWithChar ('/'))
p = p.dropLastCharacters (1);
return RelativePath (p.upToLastOccurrenceOf ("/", false, false), root);
}
RelativePath getChildFile (const String& subpath) const
{
if (isAbsolutePath (subpath))
return RelativePath (subpath, root);
String p (toUnixStyle());
if (! p.endsWithChar ('/'))
p << '/';
return RelativePath (p + subpath, root);
}
RelativePath rebased (const File& originalRoot, const File& newRoot, const RootFolder newRootType) const
{
if (isAbsolute())
return RelativePath (path, newRootType);
return RelativePath (getRelativePathFrom (originalRoot.getChildFile (toUnixStyle()), newRoot), newRootType);
}
private:
//==============================================================================
String path;
RootFolder root;
File getFakeFile() const
{
#if JUCE_WINDOWS
if (isAbsolutePath (path))
{
// This is a hack to convert unix-style absolute paths into valid absolute Windows paths to avoid hitting
// an assertion in File::parseAbsolutePath().
if (path.startsWithChar (L'/') || path.startsWithChar (L'$') || path.startsWithChar (L'~'))
return File (String ("C:\\") + windowsStylePath (path.substring (1)));
return File (path);
}
#endif
// This method gets called very often, so we'll cache this directory.
static const File currentWorkingDirectory (File::getCurrentWorkingDirectory());
return currentWorkingDirectory.getChildFile (path);
}
};
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
//==============================================================================
/** Manipulates a cross-platform partial file path. (Needed because File is designed
for absolute paths on the active OS)
*/
class RelativePath
{
public:
//==============================================================================
enum RootFolder
{
unknown,
projectFolder,
buildTargetFolder
};
//==============================================================================
RelativePath()
: root (unknown)
{}
RelativePath (const String& relPath, const RootFolder rootType)
: path (unixStylePath (relPath)), root (rootType)
{}
RelativePath (const File& file, const File& rootFolder, const RootFolder rootType)
: path (unixStylePath (getRelativePathFrom (file, rootFolder))), root (rootType)
{}
RootFolder getRoot() const { return root; }
String toUnixStyle() const { return unixStylePath (path); }
String toWindowsStyle() const { return windowsStylePath (path); }
String getFileName() const { return getFakeFile().getFileName(); }
String getFileNameWithoutExtension() const { return getFakeFile().getFileNameWithoutExtension(); }
String getFileExtension() const { return getFakeFile().getFileExtension(); }
bool hasFileExtension (StringRef extension) const { return getFakeFile().hasFileExtension (extension); }
bool isAbsolute() const { return isAbsolutePath (path); }
RelativePath withFileExtension (const String& extension) const
{
return RelativePath (path.upToLastOccurrenceOf (".", ! extension.startsWithChar ('.'), false) + extension, root);
}
RelativePath getParentDirectory() const
{
String p (path);
if (path.endsWithChar ('/'))
p = p.dropLastCharacters (1);
return RelativePath (p.upToLastOccurrenceOf ("/", false, false), root);
}
RelativePath getChildFile (const String& subpath) const
{
if (isAbsolutePath (subpath))
return RelativePath (subpath, root);
String p (toUnixStyle());
if (! p.endsWithChar ('/'))
p << '/';
return RelativePath (p + subpath, root);
}
RelativePath rebased (const File& originalRoot, const File& newRoot, const RootFolder newRootType) const
{
if (isAbsolute())
return RelativePath (path, newRootType);
return RelativePath (getRelativePathFrom (originalRoot.getChildFile (toUnixStyle()), newRoot), newRootType);
}
private:
//==============================================================================
String path;
RootFolder root;
File getFakeFile() const
{
#if JUCE_WINDOWS
if (isAbsolutePath (path))
{
// This is a hack to convert unix-style absolute paths into valid absolute Windows paths to avoid hitting
// an assertion in File::parseAbsolutePath().
if (path.startsWithChar (L'/') || path.startsWithChar (L'$') || path.startsWithChar (L'~'))
return File (String ("C:\\") + windowsStylePath (path.substring (1)));
return File (path);
}
#endif
// This method gets called very often, so we'll cache this directory.
static const File currentWorkingDirectory (File::getCurrentWorkingDirectory());
return currentWorkingDirectory.getChildFile (path);
}
};
}
}

View File

@ -1,91 +1,91 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
uint64 calculateStreamHashCode (InputStream& in)
{
uint64 t = 0;
const int bufferSize = 4096;
HeapBlock<uint8> buffer;
buffer.malloc (bufferSize);
for (;;)
{
auto num = in.read (buffer, bufferSize);
if (num <= 0)
break;
for (int i = 0; i < num; ++i)
t = t * 65599 + buffer[i];
}
return t;
}
uint64 calculateFileHashCode (const File& file)
{
std::unique_ptr<FileInputStream> stream (file.createInputStream());
return stream != nullptr ? calculateStreamHashCode (*stream) : 0;
}
uint64 calculateMemoryHashCode (const void* data, size_t numBytes)
{
uint64 t = 0;
for (size_t i = 0; i < numBytes; ++i)
t = t * 65599 + static_cast<const uint8*> (data)[i];
return t;
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes)
{
if (file.getSize() == (int64) numBytes
&& calculateMemoryHashCode (data, numBytes) == calculateFileHashCode (file))
return true;
if (file.exists())
return file.replaceWithData (data, numBytes);
return file.getParentDirectory().createDirectory() && file.appendData (data, numBytes);
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData)
{
return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize());
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData)
{
const char* const utf8 = newData.toUTF8();
return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8));
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
uint64 calculateStreamHashCode (InputStream& in)
{
uint64 t = 0;
const int bufferSize = 4096;
HeapBlock<uint8> buffer;
buffer.malloc (bufferSize);
for (;;)
{
auto num = in.read (buffer, bufferSize);
if (num <= 0)
break;
for (int i = 0; i < num; ++i)
t = t * 65599 + buffer[i];
}
return t;
}
uint64 calculateFileHashCode (const File& file)
{
std::unique_ptr<FileInputStream> stream (file.createInputStream());
return stream != nullptr ? calculateStreamHashCode (*stream) : 0;
}
uint64 calculateMemoryHashCode (const void* data, size_t numBytes)
{
uint64 t = 0;
for (size_t i = 0; i < numBytes; ++i)
t = t * 65599 + static_cast<const uint8*> (data)[i];
return t;
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes)
{
if (file.getSize() == (int64) numBytes
&& calculateMemoryHashCode (data, numBytes) == calculateFileHashCode (file))
return true;
if (file.exists())
return file.replaceWithData (data, numBytes);
return file.getParentDirectory().createDirectory() && file.appendData (data, numBytes);
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData)
{
return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize());
}
bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData)
{
const char* const utf8 = newData.toUTF8();
return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8));
}
}
}

View File

@ -1,38 +1,38 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
uint64 calculateStreamHashCode (InputStream& in);
uint64 calculateFileHashCode (const File& file);
uint64 calculateMemoryHashCode (const void* data, size_t numBytes);
bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes);
bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData);
bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData);
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
uint64 calculateStreamHashCode (InputStream& in);
uint64 calculateFileHashCode (const File& file);
uint64 calculateMemoryHashCode (const void* data, size_t numBytes);
bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes);
bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData);
bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData);
}
}

View File

@ -1,97 +1,97 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static String getCommaSeparatedVersionNumber (const String& version)
{
auto versionParts = StringArray::fromTokens (version, ",.", "");
versionParts.trim();
versionParts.removeEmptyStrings();
while (versionParts.size() < 4)
versionParts.add ("0");
return versionParts.joinIntoString (",");
}
void ResourceRcOptions::write (const File& resourceRcFile) const
{
MemoryOutputStream mo;
mo << "#pragma code_page(65001)" << newLine
<< newLine
<< "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine
<< " #include JUCE_USER_DEFINED_RC_FILE" << newLine
<< "#else" << newLine
<< newLine
<< "#undef WIN32_LEAN_AND_MEAN" << newLine
<< "#define WIN32_LEAN_AND_MEAN" << newLine
<< "#include <windows.h>" << newLine
<< newLine
<< "VS_VERSION_INFO VERSIONINFO" << newLine
<< "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine
<< "BEGIN" << newLine
<< " BLOCK \"StringFileInfo\"" << newLine
<< " BEGIN" << newLine
<< " BLOCK \"040904E4\"" << newLine
<< " BEGIN" << newLine;
const auto writeRCValue = [&] (const String& n, const String& value)
{
if (value.isNotEmpty())
mo << " VALUE \"" << n << "\", \""
<< value.replace ("\"", "\"\"") << "\\0\"" << newLine;
};
writeRCValue ("CompanyName", companyName);
writeRCValue ("LegalCopyright", companyCopyright);
writeRCValue ("FileDescription", projectName);
writeRCValue ("FileVersion", version);
writeRCValue ("ProductName", projectName);
writeRCValue ("ProductVersion", version);
mo << " END" << newLine
<< " END" << newLine
<< newLine
<< " BLOCK \"VarFileInfo\"" << newLine
<< " BEGIN" << newLine
<< " VALUE \"Translation\", 0x409, 1252" << newLine
<< " END" << newLine
<< "END" << newLine
<< newLine
<< "#endif" << newLine;
if (icon.existsAsFile())
mo << newLine
<< "IDI_ICON1 ICON DISCARDABLE " << icon.getFileName().quoted()
<< newLine
<< "IDI_ICON2 ICON DISCARDABLE " << icon.getFileName().quoted();
overwriteFileIfDifferentOrThrow (resourceRcFile, mo);
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
static String getCommaSeparatedVersionNumber (const String& version)
{
auto versionParts = StringArray::fromTokens (version, ",.", "");
versionParts.trim();
versionParts.removeEmptyStrings();
while (versionParts.size() < 4)
versionParts.add ("0");
return versionParts.joinIntoString (",");
}
void ResourceRcOptions::write (const File& resourceRcFile) const
{
MemoryOutputStream mo;
mo << "#pragma code_page(65001)" << newLine
<< newLine
<< "#ifdef JUCE_USER_DEFINED_RC_FILE" << newLine
<< " #include JUCE_USER_DEFINED_RC_FILE" << newLine
<< "#else" << newLine
<< newLine
<< "#undef WIN32_LEAN_AND_MEAN" << newLine
<< "#define WIN32_LEAN_AND_MEAN" << newLine
<< "#include <windows.h>" << newLine
<< newLine
<< "VS_VERSION_INFO VERSIONINFO" << newLine
<< "FILEVERSION " << getCommaSeparatedVersionNumber (version) << newLine
<< "BEGIN" << newLine
<< " BLOCK \"StringFileInfo\"" << newLine
<< " BEGIN" << newLine
<< " BLOCK \"040904E4\"" << newLine
<< " BEGIN" << newLine;
const auto writeRCValue = [&] (const String& n, const String& value)
{
if (value.isNotEmpty())
mo << " VALUE \"" << n << "\", \""
<< value.replace ("\"", "\"\"") << "\\0\"" << newLine;
};
writeRCValue ("CompanyName", companyName);
writeRCValue ("LegalCopyright", companyCopyright);
writeRCValue ("FileDescription", projectName);
writeRCValue ("FileVersion", version);
writeRCValue ("ProductName", projectName);
writeRCValue ("ProductVersion", version);
mo << " END" << newLine
<< " END" << newLine
<< newLine
<< " BLOCK \"VarFileInfo\"" << newLine
<< " BEGIN" << newLine
<< " VALUE \"Translation\", 0x409, 1252" << newLine
<< " END" << newLine
<< "END" << newLine
<< newLine
<< "#endif" << newLine;
if (icon.existsAsFile())
mo << newLine
<< "IDI_ICON1 ICON DISCARDABLE " << icon.getFileName().quoted()
<< newLine
<< "IDI_ICON2 ICON DISCARDABLE " << icon.getFileName().quoted();
overwriteFileIfDifferentOrThrow (resourceRcFile, mo);
}
}
}

View File

@ -1,43 +1,43 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class ResourceRcOptions final
{
public:
void write (const File& resourceRcFile) const;
//==============================================================================
String version;
String companyName;
String companyCopyright;
String projectName;
File icon;
};
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
class ResourceRcOptions final
{
public:
void write (const File& resourceRcFile) const;
//==============================================================================
String version;
String companyName;
String companyCopyright;
String projectName;
File icon;
};
}
}

View File

@ -1,60 +1,60 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
StringArray getVersionSegments (StringRef p)
{
auto segments = StringArray::fromTokens (p, ",.", "");
segments.trim();
segments.removeEmptyStrings();
return segments;
}
int getVersionAsHexIntegerFromParts (const StringArray& segments)
{
auto value = (segments[0].getIntValue() << 16)
+ (segments[1].getIntValue() << 8)
+ segments[2].getIntValue();
if (segments.size() > 3)
value = (value << 8) + segments[3].getIntValue();
return value;
}
int getVersionAsHexInteger (StringRef versionString)
{
return getVersionAsHexIntegerFromParts (getVersionSegments (versionString));
}
String getVersionAsHex (StringRef versionString)
{
return "0x" + String::toHexString (getVersionAsHexInteger (versionString));
}
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
StringArray getVersionSegments (StringRef p)
{
auto segments = StringArray::fromTokens (p, ",.", "");
segments.trim();
segments.removeEmptyStrings();
return segments;
}
int getVersionAsHexIntegerFromParts (const StringArray& segments)
{
auto value = (segments[0].getIntValue() << 16)
+ (segments[1].getIntValue() << 8)
+ segments[2].getIntValue();
if (segments.size() > 3)
value = (value << 8) + segments[3].getIntValue();
return value;
}
int getVersionAsHexInteger (StringRef versionString)
{
return getVersionAsHexIntegerFromParts (getVersionSegments (versionString));
}
String getVersionAsHex (StringRef versionString)
{
return "0x" + String::toHexString (getVersionAsHexInteger (versionString));
}
}
}

View File

@ -1,37 +1,37 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
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 6 End-User License
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
End User License Agreement: www.juce.com/juce-6-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
StringArray getVersionSegments (StringRef p);
int getVersionAsHexIntegerFromParts (const StringArray& versionString);
int getVersionAsHexInteger (StringRef versionString);
String getVersionAsHex (StringRef versionString);
}
}
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
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 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-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.
==============================================================================
*/
namespace juce
{
namespace build_tools
{
StringArray getVersionSegments (StringRef p);
int getVersionAsHexIntegerFromParts (const StringArray& versionString);
int getVersionAsHexInteger (StringRef versionString);
String getVersionAsHex (StringRef versionString);
}
}

View File

@ -1,15 +1,15 @@
# ==============================================================================
#
# This file is part of the JUCE library.
# Copyright (c) 2020 - Raw Material Software Limited
# Copyright (c) 2022 - Raw Material Software Limited
#
# 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 6 End-User License
# Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
# Agreement and JUCE Privacy Policy.
#
# End User License Agreement: www.juce.com/juce-6-licence
# End User License Agreement: www.juce.com/juce-7-licence
# Privacy Policy: www.juce.com/juce-privacy-policy
#
# Or: You may also use this code under the terms of the GPL v3 (see
@ -53,20 +53,32 @@ else()
# environment variables, which is unfortunate because we really don't want to cross-compile
# juceaide. If you really want to set the compilers for juceaide, pass the appropriate
# CMAKE_<lang>_COMPILER flags when configuring CMake.
unset(ENV{ASM})
unset(ENV{CC})
unset(ENV{CXX})
if(CMAKE_CROSSCOMPILING)
unset(ENV{ASM})
unset(ENV{CC})
unset(ENV{CXX})
else()
# When building with clang-cl in Clion on Windows for an x64 target, the ABI detection phase
# of the inner build can fail unless we pass through these flags too
set(extra_configure_flags
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
"-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}"
"-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}")
endif()
message(STATUS "Configuring juceaide")
# Looks like we're boostrapping, reinvoke CMake
# Looks like we're bootstrapping, reinvoke CMake
execute_process(COMMAND "${CMAKE_COMMAND}"
"."
"-B${JUCE_BINARY_DIR}/tools"
"-G${CMAKE_GENERATOR}"
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}"
"-DCMAKE_BUILD_TYPE=Debug"
"-DJUCE_BUILD_HELPER_TOOLS=ON"
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
${extra_configure_flags}
WORKING_DIRECTORY "${JUCE_SOURCE_DIR}"
OUTPUT_VARIABLE command_output
ERROR_VARIABLE command_output

File diff suppressed because it is too large Load Diff